/** * Get the index of a memory type that has all the requested property bits set * * @param typeBits Bitmask with bits set for each memory type supported by the resource to request for (from VkMemoryRequirements) * @param properties Bitmask of properties for the memory type to request * @param (Optional) memTypeFound Pointer to a bool that is set to true if a matching memory type has been found * * @return Index of the requested memory type * * @throw Throws an exception if memTypeFound is null and no memory type could be found that supports the requested properties */ public uint getMemoryType(uint typeBits, VkMemoryPropertyFlagBits properties, uint *memTypeFound = null) { for (uint i = 0; i < MemoryProperties.memoryTypeCount; i++) { if ((typeBits & 1) == 1) { if ((MemoryProperties.GetMemoryType(i).propertyFlags & properties) == properties) { if (memTypeFound != null) { *memTypeFound = True; } return(i); } } typeBits >>= 1; } if (memTypeFound != null) { *memTypeFound = False; return(0); } else { throw new InvalidOperationException("Could not find a matching memory type"); } }
public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, ulong size, out VkBuffer buffer, out VkDeviceMemory memory, void *data = null) { VkBuffer b; VkDeviceMemory dm; VkResult result = createBuffer(usageFlags, memoryPropertyFlags, size, &b, &dm, data); buffer = b; memory = dm; return(result); }
/** * Create a buffer on the device * * @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer) * @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent) * @param buffer Pointer to a vk::Vulkan buffer object * @param size Size of the buffer in byes * @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over) * * @return Success if buffer handle and memory have been created and (optionally passed) data has been copied */ public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, vksBuffer buffer, ulong size, void *data = null) { buffer.device = _logicalDevice; // Create the buffer handle VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo(); bufferCreateInfo.sType = BufferCreateInfo; bufferCreateInfo.usage = usageFlags; bufferCreateInfo.size = size; { VkBuffer vkBuffer; vkCreateBuffer(_logicalDevice, &bufferCreateInfo, null, &vkBuffer); buffer.buffer = vkBuffer; } // Create the memory backing up the buffer handle VkMemoryRequirements memReqs; VkMemoryAllocateInfo memAlloc = new VkMemoryAllocateInfo(); memAlloc.sType = MemoryAllocateInfo; vkGetBufferMemoryRequirements(_logicalDevice, buffer.buffer, &memReqs); memAlloc.allocationSize = memReqs.size; // Find a memory type index that fits the properties of the buffer memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); { VkDeviceMemory memory; vkAllocateMemory(_logicalDevice, &memAlloc, null, &memory); buffer.memory = memory; } buffer.alignment = memReqs.alignment; buffer.size = memAlloc.allocationSize; buffer.usageFlags = usageFlags; buffer.memoryPropertyFlags = memoryPropertyFlags; // If a pointer to the buffer data has been passed, map the buffer and copy over the data if (data != null) { buffer.map(); Unsafe.CopyBlock(buffer.mapped, data, (uint)size); buffer.unmap(); } // Initialize a default descriptor that covers the whole buffer size buffer.setupDescriptor(); // Attach the memory to the buffer object return(buffer.bind()); }
private int findMemoryType(int typeFilter, VkMemoryPropertyFlagBits properties) { VkPhysicalDeviceMemoryProperties memProperties; Vulkan.vkGetPhysicalDeviceMemoryProperties(physicalDevice, out memProperties); for (int i = 0; i < memProperties.memoryTypeCount; i++) { if ((typeFilter & (1 << i)) != 0 && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { return(i); } } throw new Exception("failed to find suitable memory type!"); }
/** * Create a buffer on the device * * @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer) * @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent) * @param size Size of the buffer in byes * @param buffer Pointer to the buffer handle acquired by the function * @param memory Pointer to the memory handle acquired by the function * @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over) * * @return Success if buffer handle and memory have been created and (optionally passed) data has been copied */ public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, ulong size, VkBuffer *buffer, VkDeviceMemory *memory, void *data = null) { // Create the buffer handle VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo(); bufferCreateInfo.sType = BufferCreateInfo; bufferCreateInfo.usage = usageFlags; bufferCreateInfo.size = size; bufferCreateInfo.sharingMode = VkSharingMode.Exclusive; vkCreateBuffer(LogicalDevice, &bufferCreateInfo, null, buffer); // Create the memory backing up the buffer handle VkMemoryRequirements memReqs; VkMemoryAllocateInfo memAlloc = new VkMemoryAllocateInfo(); memAlloc.sType = MemoryAllocateInfo; vkGetBufferMemoryRequirements(LogicalDevice, *buffer, &memReqs); memAlloc.allocationSize = memReqs.size; // Find a memory type index that fits the properties of the buffer memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); vkAllocateMemory(LogicalDevice, &memAlloc, null, memory); // If a pointer to the buffer data has been passed, map the buffer and copy over the data if (data != null) { IntPtr mapped; vkMapMemory(LogicalDevice, *memory, 0, size, 0, &mapped); Unsafe.CopyBlock(mapped, data, (uint)size); // If host coherency hasn't been requested, do a manual flush to make writes visible if ((memoryPropertyFlags & VkMemoryPropertyFlagBits.HostCoherent) == 0) { VkMappedMemoryRange mappedRange = new VkMappedMemoryRange(); mappedRange.memory = *memory; mappedRange.offset = 0; mappedRange.size = size; vkFlushMappedMemoryRanges(LogicalDevice, 1, &mappedRange); } vkUnmapMemory(LogicalDevice, *memory); } // Attach the memory to the buffer object vkBindBufferMemory(LogicalDevice, *buffer, *memory, 0); return(VkResult.Success); }
//VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT private uint GetMemoryTypeIndex(VkPhysicalDeviceMemoryProperties memoryProperties, VkMemoryRequirements memoryReq, VkMemoryPropertyFlagBits flags) { uint result = 0; bool heapIndexSet = false; VkMemoryType *memoryTypes = (VkMemoryType *)memoryProperties.memoryTypes; for (uint i = 0; i < memoryProperties.memoryTypeCount; i++) { if (((memoryReq.memoryTypeBits >> (int)i) & 1) == 1 && (memoryTypes[i].propertyFlags & flags) == flags) { result = i; heapIndexSet = true; break; } } if (!heapIndexSet) { result = memoryTypes[0].heapIndex; } return(result); }
public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, vksBuffer buffer, ulong size, IntPtr data) => createBuffer(usageFlags, memoryPropertyFlags, buffer, size, data.ToPointer());