First prototype support for VK_KHR_ray_tracing
Added symbols: vmaCreateAccelerationStructure, vmaDestroyAccelerationStructure.
diff --git a/README.md b/README.md
index e6ef0c0..07f5889 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,7 @@
- VK_KHR_dedicated_allocation: Just enable it and it will be used automatically by the library.
- VK_AMD_device_coherent_memory
- VK_EXT_buffer_device_address / VK_KHR_buffer_device_address
+ - VK_KHR_ray_tracing
- Defragmentation of GPU and CPU memory: Let the library move data around to free some memory blocks and make your allocations better compacted.
- Lost allocations: Allocate memory with appropriate flags and let the library remove allocations that are not used for many frames to make room for new ones.
- Statistics: Obtain detailed statistics about the amount of memory used, unused, number of allocated blocks, number of allocations etc. - globally, per memory heap, and per memory type.
diff --git a/src/VmaUsage.h b/src/VmaUsage.h
index 9adcdc9..67a9750 100644
--- a/src/VmaUsage.h
+++ b/src/VmaUsage.h
@@ -29,6 +29,7 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#define VK_USE_PLATFORM_WIN32_KHR
+#define VK_ENABLE_BETA_EXTENSIONS
#else // #ifdef _WIN32
diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h
index 92a126c..4f1a31b 100644
--- a/src/vk_mem_alloc.h
+++ b/src/vk_mem_alloc.h
@@ -1945,6 +1945,12 @@
#define VMA_CALL_POST
#endif
+#ifndef VMA_DECORATE_RAY_TRACING
+ #define VMA_DECORATE_RAY_TRACING(identifier) identifier##KHR
+ #define VMA_DECORATE_RAY_TRACING_CONSTANT(identifier) identifier##_KHR
+ #define VMA_DECORATE_RAY_TRACING_STRING(str) str "KHR"
+#endif
+
/** \struct VmaAllocator
\brief Represents main object of this library initialized.
@@ -2116,6 +2122,10 @@
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
#endif
+ VMA_DECORATE_RAY_TRACING(PFN_vkCreateAccelerationStructure) VMA_DECORATE_RAY_TRACING(vkCreateAccelerationStructure);
+ VMA_DECORATE_RAY_TRACING(PFN_vkDestroyAccelerationStructure) VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure);
+ VMA_DECORATE_RAY_TRACING(PFN_vkGetAccelerationStructureMemoryRequirements) VMA_DECORATE_RAY_TRACING(vkGetAccelerationStructureMemoryRequirements);
+ VMA_DECORATE_RAY_TRACING(PFN_vkBindAccelerationStructureMemory) VMA_DECORATE_RAY_TRACING(vkBindAccelerationStructureMemory);
} VmaVulkanFunctions;
/// Flags to be used in VmaRecordSettings::flags.
@@ -3663,6 +3673,27 @@
VkImage image,
VmaAllocation allocation);
+/** \brief TODO
+
+TODO
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAccelerationStructure(
+ VmaAllocator allocator,
+ const VMA_DECORATE_RAY_TRACING(VkAccelerationStructureCreateInfo)* pAccelerationStructureCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure)* pAccelerationStructure,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief TODO
+
+TODO
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAccelerationStructure(
+ VmaAllocator allocator,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) accelerationStructrure,
+ VmaAllocation allocation);
+
#ifdef __cplusplus
}
#endif
@@ -4234,9 +4265,10 @@
VMA_SUBALLOCATION_TYPE_FREE = 0,
VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,
VMA_SUBALLOCATION_TYPE_BUFFER = 2,
- VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,
- VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,
- VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,
+ VMA_SUBALLOCATION_TYPE_ACCELERATION_STRUCTURE = 3,
+ VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 4,
+ VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 5,
+ VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 6,
VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
};
@@ -4262,6 +4294,7 @@
case VMA_SUBALLOCATION_TYPE_UNKNOWN:
return true;
case VMA_SUBALLOCATION_TYPE_BUFFER:
+ case VMA_SUBALLOCATION_TYPE_ACCELERATION_STRUCTURE:
return
suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
@@ -6437,6 +6470,12 @@
VkDeviceSize allocationLocalOffset,
VkImage hImage,
const void* pNext);
+ VkResult BindAccelerationStructureMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) hAccelerationStructure,
+ const void* pNext);
private:
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
@@ -7410,6 +7449,10 @@
VkMemoryRequirements& memReq,
bool& requiresDedicatedAllocation,
bool& prefersDedicatedAllocation) const;
+ void GetAccelerationStructureMemoryRequirements(
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructureMemoryRequirementsType) type,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) hAccelerationStructure,
+ VkMemoryRequirements& memReq) const;
// Main allocation function.
VkResult AllocateMemory(
@@ -7489,6 +7532,12 @@
VkDeviceSize memoryOffset,
VkImage image,
const void* pNext);
+ // Call to Vulkan function vkBindAccelerationStructureMemoryKHR
+ VkResult BindVulkanAccelerationStructure(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) accelerationStructure,
+ const void* pNext);
VkResult Map(VmaAllocation hAllocation, void** ppData);
void Unmap(VmaAllocation hAllocation);
@@ -7503,6 +7552,11 @@
VkDeviceSize allocationLocalOffset,
VkImage hImage,
const void* pNext);
+ VkResult BindAccelerationStructureMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) hAccelerationStructure,
+ const void* pNext);
void FlushOrInvalidateAllocation(
VmaAllocation hAllocation,
@@ -8156,6 +8210,7 @@
"FREE",
"UNKNOWN",
"BUFFER",
+ "ACCELERATION_STRUCTURE",
"IMAGE_UNKNOWN",
"IMAGE_LINEAR",
"IMAGE_OPTIMAL",
@@ -11964,6 +12019,23 @@
return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
}
+VkResult VmaDeviceMemoryBlock::BindAccelerationStructureMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) hAccelerationStructure,
+ const void* pNext)
+{
+ VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+ hAllocation->GetBlock() == this);
+ VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&
+ "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
+ const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
+ // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ return hAllocator->BindVulkanAccelerationStructure(m_hMemory, memoryOffset, hAccelerationStructure, pNext);
+}
+
static void InitStatInfo(VmaStatInfo& outInfo)
{
memset(&outInfo, 0, sizeof(outInfo));
@@ -15357,6 +15429,14 @@
}
}
#endif // #if VMA_MEMORY_BUDGET
+ m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkCreateAccelerationStructure) =
+ (VMA_DECORATE_RAY_TRACING(PFN_vkCreateAccelerationStructure))vkGetDeviceProcAddr(m_hDevice, VMA_DECORATE_RAY_TRACING_STRING("vkCreateAccelerationStructure"));
+ m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure) =
+ (PFN_vkDestroyAccelerationStructureNV)vkGetDeviceProcAddr(m_hDevice, VMA_DECORATE_RAY_TRACING_STRING("vkDestroyAccelerationStructure"));
+ m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkGetAccelerationStructureMemoryRequirements) =
+ (PFN_vkGetAccelerationStructureMemoryRequirementsNV)vkGetDeviceProcAddr(m_hDevice, VMA_DECORATE_RAY_TRACING_STRING("vkGetAccelerationStructureMemoryRequirements"));
+ m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkBindAccelerationStructureMemory) =
+ (PFN_vkBindAccelerationStructureMemoryNV)vkGetDeviceProcAddr(m_hDevice, VMA_DECORATE_RAY_TRACING_STRING("vkBindAccelerationStructureMemory"));
#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1
#define VMA_COPY_IF_NOT_NULL(funcName) \
@@ -15392,6 +15472,10 @@
#if VMA_MEMORY_BUDGET
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);
#endif
+ VMA_COPY_IF_NOT_NULL(VMA_DECORATE_RAY_TRACING(vkCreateAccelerationStructure));
+ VMA_COPY_IF_NOT_NULL(VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure));
+ VMA_COPY_IF_NOT_NULL(VMA_DECORATE_RAY_TRACING(vkGetAccelerationStructureMemoryRequirements));
+ VMA_COPY_IF_NOT_NULL(VMA_DECORATE_RAY_TRACING(vkBindAccelerationStructureMemory));
}
#undef VMA_COPY_IF_NOT_NULL
@@ -15435,6 +15519,10 @@
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
}
#endif
+ VMA_ASSERT(m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkCreateAccelerationStructure) != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure) != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkGetAccelerationStructureMemoryRequirements) != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkBindAccelerationStructureMemory) != VMA_NULL);
}
VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
@@ -15813,6 +15901,22 @@
}
}
+void VmaAllocator_T::GetAccelerationStructureMemoryRequirements(
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructureMemoryRequirementsType) type,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) hAccelerationStructure,
+ VkMemoryRequirements& memReq) const
+{
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructureMemoryRequirementsInfo) memReqInfo = { VMA_DECORATE_RAY_TRACING_CONSTANT(VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO) };
+ memReqInfo.type = VMA_DECORATE_RAY_TRACING_CONSTANT(VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT);
+ memReqInfo.accelerationStructure = hAccelerationStructure;
+
+ VkMemoryRequirements2 memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 };
+
+ (*m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkGetAccelerationStructureMemoryRequirements))(m_hDevice, &memReqInfo, &memReq2);
+
+ memReq = memReq2.memoryRequirements;
+}
+
VkResult VmaAllocator_T::AllocateMemory(
const VkMemoryRequirements& vkMemReq,
bool requiresDedicatedAllocation,
@@ -16583,6 +16687,20 @@
}
}
+VkResult VmaAllocator_T::BindVulkanAccelerationStructure(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) accelerationStructure,
+ const void* pNext)
+{
+ VMA_DECORATE_RAY_TRACING(VkBindAccelerationStructureMemoryInfo) bindInfo = { VMA_DECORATE_RAY_TRACING_CONSTANT(VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO) };
+ bindInfo.pNext = pNext;
+ bindInfo.accelerationStructure = accelerationStructure;
+ bindInfo.memory = memory;
+ bindInfo.memoryOffset = memoryOffset;
+ return (*m_VulkanFunctions.VMA_DECORATE_RAY_TRACING(vkBindAccelerationStructureMemory))(m_hDevice, 1, &bindInfo);
+}
+
VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
{
if(hAllocation->CanBecomeLost())
@@ -16681,6 +16799,31 @@
return res;
}
+VkResult VmaAllocator_T::BindAccelerationStructureMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) hAccelerationStructure,
+ const void* pNext)
+{
+ VkResult res = VK_SUCCESS;
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ res = BindVulkanAccelerationStructure(hAllocation->GetMemory(), allocationLocalOffset, hAccelerationStructure, pNext);
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+ VMA_ASSERT(pBlock && "Binding acceleration structure to allocation that doesn't belong to any block. Is the allocation lost?");
+ res = pBlock->BindAccelerationStructureMemory(this, hAllocation, allocationLocalOffset, hAccelerationStructure, pNext);
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
+ }
+ return res;
+}
+
void VmaAllocator_T::FlushOrInvalidateAllocation(
VmaAllocation hAllocation,
VkDeviceSize offset, VkDeviceSize size,
@@ -18460,4 +18603,124 @@
}
}
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAccelerationStructure(
+ VmaAllocator allocator,
+ const VMA_DECORATE_RAY_TRACING(VkAccelerationStructureCreateInfo)* pAccelerationStructureCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure)* pAccelerationStructure,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pAccelerationStructureCreateInfo && pAllocationCreateInfo && pAccelerationStructure && pAllocation);
+
+ VMA_DEBUG_LOG("vmaCreateAccelerationStructure");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *pAccelerationStructure = VK_NULL_HANDLE;
+ *pAllocation = VK_NULL_HANDLE;
+
+ // 1. Create VkAccelerationStructureKHR.
+ VkResult res = (*allocator->GetVulkanFunctions().VMA_DECORATE_RAY_TRACING(vkCreateAccelerationStructure))(
+ allocator->m_hDevice,
+ pAccelerationStructureCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pAccelerationStructure);
+ if(res >= 0)
+ {
+ // 2. vkGetAccelerationStructureMemoryRequirements.
+ VkMemoryRequirements vkMemReq = {};
+ const bool requiresDedicatedAllocation = false;
+ const bool prefersDedicatedAllocation = false;
+ allocator->GetAccelerationStructureMemoryRequirements(
+ VMA_DECORATE_RAY_TRACING_CONSTANT(VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT),
+ *pAccelerationStructure, vkMemReq);
+
+ // 3. Allocate memory using allocator.
+ res = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ VK_NULL_HANDLE, // dedicatedBuffer
+ UINT32_MAX, // dedicatedBufferUsage
+ VK_NULL_HANDLE, // dedicatedImage
+ *pAllocationCreateInfo,
+ VMA_SUBALLOCATION_TYPE_ACCELERATION_STRUCTURE,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ // TODO
+ }
+#endif
+
+ if(res >= 0)
+ {
+ // 3. Bind acceleration structure with memory.
+ if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
+ {
+ res = allocator->BindAccelerationStructureMemory(*pAllocation, 0, *pAccelerationStructure, VMA_NULL);
+ }
+ if(res >= 0)
+ {
+ // All steps succeeded.
+ if(pAllocationInfo != VMA_NULL)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return VK_SUCCESS;
+ }
+ allocator->FreeMemory(
+ 1, // allocationCount
+ pAllocation);
+ *pAllocation = VK_NULL_HANDLE;
+ (*allocator->GetVulkanFunctions().VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure))(allocator->m_hDevice, *pAccelerationStructure, allocator->GetAllocationCallbacks());
+ *pAccelerationStructure = VK_NULL_HANDLE;
+ return res;
+ }
+ (*allocator->GetVulkanFunctions().VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure))(allocator->m_hDevice, *pAccelerationStructure, allocator->GetAllocationCallbacks());
+ *pAccelerationStructure = VK_NULL_HANDLE;
+ return res;
+ }
+ return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAccelerationStructure(
+ VmaAllocator allocator,
+ VMA_DECORATE_RAY_TRACING(VkAccelerationStructure) accelerationStructure,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(accelerationStructure == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyAccelerationStructure");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ // TODO
+ }
+#endif
+
+ if(accelerationStructure != VK_NULL_HANDLE)
+ {
+ (*allocator->GetVulkanFunctions().VMA_DECORATE_RAY_TRACING(vkDestroyAccelerationStructure))(allocator->m_hDevice, accelerationStructure, allocator->GetAllocationCallbacks());
+ }
+ if(allocation != VK_NULL_HANDLE)
+ {
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+ }
+}
+
#endif // #ifdef VMA_IMPLEMENTATION