in Cthulhu/src/VulkanUtil.cpp [266:349]
std::pair<uint64_t, uint32_t> VulkanUtil::allocate(uint32_t nrBytes, bool deviceLocal) {
#ifdef CTHULHU_HAS_VULKAN
if (!isActive_) {
return {0, 0};
}
// Create a buffer, just to get memory requirements
VkBufferCreateInfo bufferCreateInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bufferCreateInfo.size = nrBytes;
bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
// Enable export
VkExternalMemoryBufferCreateInfo infoEx{VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO};
#ifdef _WIN32
infoEx.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
#else
infoEx.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
#endif
bufferCreateInfo.pNext = &infoEx;
VkBuffer buffer;
if (vkCreateBuffer(state_->device, &bufferCreateInfo, nullptr, &buffer) != VK_SUCCESS) {
XR_LOGW("Failed to allocate Vulkan buffer");
return {0, 0};
}
// Require host visible, coherent memory
VkMemoryRequirements memReqs;
vkGetBufferMemoryRequirements(state_->device, buffer, &memReqs);
VkExportMemoryAllocateInfoKHR vulkanExportMemoryAllocateInfoKHR = {};
vulkanExportMemoryAllocateInfoKHR.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
vulkanExportMemoryAllocateInfoKHR.pNext = nullptr;
#ifdef _WIN32
vulkanExportMemoryAllocateInfoKHR.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
#else
vulkanExportMemoryAllocateInfoKHR.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
#endif
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.pNext = &vulkanExportMemoryAllocateInfoKHR;
allocateInfo.allocationSize = memReqs.size;
VkFlags required, preferred, preferredNot;
if (deviceLocal) {
required = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
preferred = 0;
preferredNot = 0;
} else {
required = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
preferred = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
preferredNot = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
allocateInfo.memoryTypeIndex = findMemoryTypeIndex(
state_->memoryProperties, memReqs.memoryTypeBits, required, preferred, preferredNot);
// Allocate the memory
VkDeviceMemory bufferMemory;
if (vkAllocateMemory(state_->device, &allocateInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
XR_LOGW("Failed to allocate Vulkan buffer memory!");
return {0, 0};
}
// We no longer need the buffer
vkDestroyBuffer(state_->device, buffer, nullptr);
#ifdef _WIN32
VkMemoryGetWin32HandleInfoKHR info = {VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR};
HANDLE handle{};
info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
info.memory = bufferMemory;
vkGetMemoryWin32HandleKHR(state_->device, &info, &handle);
#else
VkMemoryGetFdInfoKHR info = {VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR};
int handle{};
info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
info.memory = bufferMemory;
vkGetMemoryFdKHR(state_->device, &info, &handle);
#endif
return {(uint64_t)handle, allocateInfo.memoryTypeIndex};
#endif // CTHULHU_HAS_VULKAN
XR_LOGW("Failed to allocate GPU buffer. Vulkan support was not included in build.");
return {0, 0};
}