vkCreateBuffer()
vkCreateBuffer - Create a new buffer object
// Provided by VK_VERSION_1_0 VkResult vkCreateBuffer( VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer);
vkCreateBuffer(3)
Bufferの作成にはvkCreateBuffer()を使用する。
作成に当たり、VkBufferCreateInfoを埋める必要がある。
VkBufferCreateInfo
VkBufferCreateInfo - Structure specifying the parameters of a newly created buffer object
// Provided by VK_VERSION_1_0 typedef struct VkBufferCreateInfo { VkStructureType sType; const void* pNext; VkBufferCreateFlags flags; VkDeviceSize size; VkBufferUsageFlags usage; VkSharingMode sharingMode; uint32_t queueFamilyIndexCount; const uint32_t* pQueueFamilyIndices; } VkBufferCreateInfo;
- sType is the type of this structure.
- pNext is NULL or a pointer to a structure extending this structure.
- flags is a bitmask of VkBufferCreateFlagBits specifying additional parameters of the buffer.
- size is the size in bytes of the buffer to be created.
- usage is a bitmask of VkBufferUsageFlagBits specifying allowed usages of the buffer.
- sharingMode is a VkSharingMode value specifying the sharing mode of the buffer when it will be accessed by multiple queue families.
- queueFamilyIndexCount is the number of entries in the pQueueFamilyIndices array.
- pQueueFamilyIndices is a pointer to an array of queue families that will access this buffer. It is ignored if sharingMode is not VK_SHARING_MODE_CONCURRENT.
VkSharingMode
VkSharingMode - Buffer and image sharing modes.
Buffer and image objects are created with a sharing mode controlling how they can be accessed from queues.
Sharing ModeとはQueueからのaccess modeのこと。
// Provided by VK_VERSION_1_0 typedef enum VkSharingMode { VK_SHARING_MODE_EXCLUSIVE = 0, VK_SHARING_MODE_CONCURRENT = 1, } VkSharingMode;
メンバはEXCLUSIVEとCONCURRENTの2つのみ。
- VK_SHARING_MODE_EXCLUSIVE specifies that access to any range or image subresource of the object will be exclusive to a single queue family at a time.
- VK_SHARING_MODE_CONCURRENT specifies that concurrent access to any range or image subresource of the object from multiple queue families is supported.
exclusiveは「排他的な、他を入れない」という意味で、concurrentは「同時」という意味。
exclusive とは 意味・読み方・表現 | Weblio英和辞書
concurrent とは 意味・読み方・表現 | Weblio英和辞書
VK_SHARING_MODE_EXCLUSIVE を指定すると、一度にひとつのqueue familyからしかアクセスできず、VK_SHARING_MODE_CONCURRENT を指定すると一度に複数のqueue familyからアクセスできる。
vkAllocateMemory()
vkAllocateMemory - Allocate device memory
作成したBufferをデバイスメモリに割り当てるには、vkAllocateMemory()を使用する。
// Provided by VK_VERSION_1_0 VkResult vkAllocateMemory( VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory);
- device is the logical device that owns the memory.
- pAllocateInfo is a pointer to a VkMemoryAllocateInfo structure describing parameters of the allocation. A successfully returned allocation must use the requested parameters — no substitution is permitted by the implementation.
- pAllocator controls host memory allocation as described in the Memory Allocation chapter.
- pMemory is a pointer to a VkDeviceMemory handle in which information about the allocated memory is returned.
VkMemoryAllocateInfoによる具体的なパラメータの指定が必要。
VkMemoryAllocateInfo
VkMemoryAllocateInfo - Structure containing parameters of a memory allocation
// Provided by VK_VERSION_1_0 typedef struct VkMemoryAllocateInfo { VkStructureType sType; const void* pNext; VkDeviceSize allocationSize; uint32_t memoryTypeIndex; } VkMemoryAllocateInfo;
- sType is the type of this structure.
- pNext is NULL or a pointer to a structure extending this structure.
- allocationSize is the size of the allocation in bytes.
- memoryTypeIndex is an index identifying a memory type from the memoryTypes array of the VkPhysicalDeviceMemoryProperties structure.
使用したいmemory typeを、VkPhysicalDeviceMemoryPropertiesのmemoryTypes[]のindexで指定する必要がある。
VkPhysicalDeviceMemoryProperties
VkPhysicalDeviceMemoryProperties - Structure specifying physical device memory properties
// Provided by VK_VERSION_1_0 typedef struct VkPhysicalDeviceMemoryProperties { uint32_t memoryTypeCount; VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; uint32_t memoryHeapCount; VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; } VkPhysicalDeviceMemoryProperties;
VkPhysicalDeviceMemoryProperties(3)
vkGetBufferMemoryRequirements()でphysical deviceでサポートされているVkPhysicalDeviceMemoryPropertiesが取得できるので、そこから使用するmemory typesのindexを指定してVkMemoryAllocateInfoに記述する。
vkAllocateMemory()の具体例
サンプルコードでよく見かける具体例。
VkMemoryRequirements memReq; vkGetBufferMemoryRequirements(device, buffer, &memReq); VkMemoryAllocateInfo allocInfo{ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = nullptr, .allocationSize = memReq.size, .memoryTypeIndex = 0, // Memory type assigned in the next step };
vkGetBufferMemoryRequirements()でbuffer objectのmemory requiementを取得する。
vkGetBufferMemoryRequirements(3)
このrequirementでallocInfo.allocationSizeの値を埋める。
VkMemoryRequirements
VkMemoryRequirements - Structure specifying memory requirements
// Provided by VK_VERSION_1_0 typedef struct VkMemoryRequirements { VkDeviceSize size; VkDeviceSize alignment; uint32_t memoryTypeBits; } VkMemoryRequirements;
- size is the size, in bytes, of the memory allocation required for the resource.
- alignment is the alignment, in bytes, of the offset within the allocation required for the resource.
- memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource. Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the physical device is supported for the resource.
memoryTypeBitsはphysical deviceでサポートされているビットセットを表す。bitのi番目はVkPhysicalDeviceMemoryProperties.memoryTypesのi番目に対応する。
この事実をもとに、割り当てるメモリで使いたいmemory propertyをもつmemoryTypesは何番目かを調べる。
uint32_t SearchIndex(typeBits, requirements_mask){ for (uint32_t i = 0; i < memReq.memoryTypeCount; i++) { if ((typeBits & 1) == 1) { // Type is available, does it match user properties? if ((memoryProperties.memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) { return i; } } typeBits >>= 1; } throw std::runtime_error("failed to find suitable memory types for buffer"); }
typeBitsにはVkMemoryRequirements.memoryTypeBitsを入れ、requirements_maskには指定したいVkFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BITなど)を入れる。
i番目のindexがi番目のtypeBitsのbitに対応しているので、bitが一致するかどうかを確かめる。一致していた場合、使用したいrequirements_maskがmemoryProperties.memoryTypesのi番目であるかどうかを確かめる。一致していた場合、このiが欲しいiなので、returnしてiを受け取る。一致しない場合、typeBitsを一つ右にシフトして、次のiに対応させてからsearchのループをやり直す。
以上の手順により、requirements_maskに対応するmemoryProperties.memoryTypesのindexを取得できる。
これでVkMemoryAllocateInfoが完成する。