summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-04 20:33:58 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-04 20:33:58 +0000
commitfa6be16a6251b956810caaaa39d2ef8b9c41615a (patch)
treef5ac4ebe8fbefd9ab90b93d014e648e7c6884988 /Graphics/GraphicsEngineVulkan
parentAdded Vulkan implementation (diff)
downloadDiligentCore-fa6be16a6251b956810caaaa39d2ef8b9c41615a.tar.gz
DiligentCore-fa6be16a6251b956810caaaa39d2ef8b9c41615a.zip
Added KHR extension emulation via NV extension
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt1
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp9
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp28
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp514
7 files changed, 556 insertions, 2 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index 761653a4..6ce17f34 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -124,6 +124,7 @@ set(VULKAN_UTILS_SRC
src/VulkanUtilities/VulkanLogicalDevice.cpp
src/VulkanUtilities/VulkanMemoryManager.cpp
src/VulkanUtilities/VulkanPhysicalDevice.cpp
+ src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
)
set(GENERATE_MIPS_SHADER shaders/GenerateMipsCS.csh)
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
index c2fba2a4..a8366551 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
@@ -239,4 +239,6 @@ private:
const VkPhysicalDeviceFeatures m_EnabledFeatures;
};
+void EnableRayTracingKHRviaNV();
+
} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
index 1e9a6edf..b9bf651c 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
@@ -44,6 +44,7 @@ public:
VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {};
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {};
VkPhysicalDeviceRayTracingFeaturesKHR RayTracing = {};
+ bool RayTracingNV = false; // indicates that KHR extension emulated by NV extension
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {};
VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {};
};
diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index 185f1da5..692b5428 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -273,7 +273,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
auto RayTracingFeats = DeiceExtFeatures.RayTracing;
auto BufferDeviceAddressFeats = DeiceExtFeatures.BufferDeviceAddress;
auto DescriptorIndexingFeats = DeiceExtFeatures.DescriptorIndexing;
- ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE, MeshShaders, "Ray tracing are");
+ ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeiceExtFeatures.RayTracingNV, MeshShaders, "Ray tracing are");
#undef FeatureSupport
@@ -396,7 +396,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
// Ray tracing
if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
{
- if (RayTracingFeats.rayTracing != VK_FALSE)
+ if (DeiceExtFeatures.RayTracingNV)
+ {
+ DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
+ DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME);
+ }
+ else if (RayTracingFeats.rayTracing != VK_FALSE)
{
// required extensions
DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
index 45d9bfa5..87bfc450 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
@@ -60,6 +60,9 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe
// Since we only use one device at this time, load device function entries
// https://github.com/zeux/volk#optimizing-device-calls
volkLoadDevice(m_VkDevice);
+
+ if (PhysicalDevice.GetExtFeatures().RayTracingNV)
+ EnableRayTracingKHRviaNV();
#endif
m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
index 12567cd0..22659277 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
@@ -71,6 +71,8 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
#if DILIGENT_USE_VOLK
if (Instance.IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
+ VkPhysicalDeviceRayTracingPropertiesNV RayTracingNV = {};
+
VkPhysicalDeviceFeatures2 Feats2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
void** NextFeat = &Feats2.pNext;
@@ -131,7 +133,15 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
m_ExtProperties.RayTracing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR;
}
+ else if (IsExtensionSupported(VK_NV_RAY_TRACING_EXTENSION_NAME))
+ {
+ m_ExtFeatures.RayTracingNV = true;
+ *NextProp = &RayTracingNV;
+ NextProp = &RayTracingNV.pNext;
+
+ RayTracingNV.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV;
+ }
// Additional extension that required for ray tracing.
if (IsExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
@@ -164,6 +174,24 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
// Some flags may not be supported by hardware.
vkGetPhysicalDeviceFeatures2KHR(m_VkDevice, &Feats2);
vkGetPhysicalDeviceProperties2KHR(m_VkDevice, &Props2);
+
+ // Emulate KHR extension
+ if (m_ExtFeatures.RayTracingNV)
+ {
+ //m_ExtFeatures.RayTracing.sType
+ //m_ExtFeatures.RayTracing.rayTracingPrimitiveCulling = true; // AZ TODO
+ m_ExtFeatures.RayTracing.rayTracing = VK_TRUE;
+
+ m_ExtProperties.RayTracing.shaderGroupHandleSize = RayTracingNV.shaderGroupHandleSize;
+ m_ExtProperties.RayTracing.maxRecursionDepth = RayTracingNV.maxRecursionDepth;
+ m_ExtProperties.RayTracing.maxShaderGroupStride = RayTracingNV.maxShaderGroupStride;
+ m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment;
+ m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount;
+ m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount;
+ m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount;
+ m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures;
+ m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0;
+ }
}
#endif // DILIGENT_USE_VOLK
}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
new file mode 100644
index 00000000..de16fe6a
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "VulkanErrors.hpp"
+#include "VulkanUtilities/VulkanLogicalDevice.hpp"
+
+// for KHR ray tracing emulation
+#include <mutex>
+#include <unordered_map>
+
+namespace VulkanUtilities
+{
+
+// KHR ray tracing emulation.
+// Will be deprecated after the release of KHR extension.
+#if DILIGENT_USE_VOLK
+static_assert(sizeof(VkAccelerationStructureKHR) == sizeof(VkAccelerationStructureNV), "not compatible with NV extension");
+static_assert(sizeof(VkDeviceAddress) == 8, "not compatible with NV extension");
+
+static std::mutex g_BufferDeviceAddressGuard;
+static std::unordered_map<VkDeviceAddress, VkBuffer> g_DeviceAddressToBuffer;
+static std::unordered_map<VkBuffer, VkDeviceAddress> g_BufferToDeviceAddress;
+static uint32_t g_BufferDeviceAddressCounter = 0;
+static const VkDeviceAddress g_BufferMask = 0xFFFFFFFF00000000ull;
+
+static PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr;
+static PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr;
+static PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr;
+
+static VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device,
+ const VkBufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkBuffer* pBuffer)
+{
+ const_cast<VkBufferCreateInfo*>(pCreateInfo)->usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
+ return Origin_vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+static void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
+ VkBuffer buffer,
+ const VkAllocationCallbacks* pAllocator)
+{
+ Origin_vkDestroyBuffer(device, buffer, pAllocator);
+
+ std::unique_lock<std::mutex> lock{g_BufferDeviceAddressGuard};
+
+ auto iter = g_BufferToDeviceAddress.find(buffer);
+ if (iter != g_BufferToDeviceAddress.end())
+ {
+ g_DeviceAddressToBuffer.erase(iter->second);
+ g_BufferToDeviceAddress.erase(iter);
+ }
+}
+
+static VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo)
+{
+ VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR);
+ VERIFY_EXPR(pInfo->pNext == nullptr);
+
+ std::unique_lock<std::mutex> lock{g_BufferDeviceAddressGuard};
+
+ // find in existing buffers
+ auto iter = g_BufferToDeviceAddress.find(pInfo->buffer);
+ if (iter != g_BufferToDeviceAddress.end())
+ return iter->second;
+
+ // create new device address
+ VkDeviceAddress Addr = VkDeviceAddress(++g_BufferDeviceAddressCounter) << 32;
+ g_BufferToDeviceAddress.insert_or_assign(pInfo->buffer, Addr);
+ g_DeviceAddressToBuffer.insert_or_assign(Addr, pInfo->buffer);
+ return Addr;
+}
+
+struct BufferAndOffset
+{
+ VkBuffer Buffer;
+ VkDeviceSize Offset;
+};
+static BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr)
+{
+ if (Addr == 0)
+ return {VK_NULL_HANDLE, 0};
+
+ std::unique_lock<std::mutex> lock{g_BufferDeviceAddressGuard};
+
+ auto iter = g_DeviceAddressToBuffer.find(Addr & g_BufferMask);
+ if (iter == g_DeviceAddressToBuffer.end())
+ {
+ UNEXPECTED("Failed to map device address to buffer");
+ return {VK_NULL_HANDLE, 0};
+ }
+
+ return {iter->second, Addr & ~g_BufferMask};
+}
+
+static BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressConstKHR& Addr)
+{
+ return DeviceAddressToBuffer(Addr.deviceAddress);
+}
+
+static BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr)
+{
+ return DeviceAddressToBuffer(Addr.deviceAddress);
+}
+
+
+static VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice device,
+ const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureKHR* pAccelerationStructure)
+{
+ VERIFY_EXPR(pCreateInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR);
+ VERIFY_EXPR(pCreateInfo->pNext == nullptr);
+ VERIFY_EXPR(pCreateInfo->deviceAddress == 0);
+
+ VkAccelerationStructureCreateInfoNV CreateInfo = {};
+ std::vector<VkGeometryNV> Geometries;
+
+ CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
+ CreateInfo.compactedSize = pCreateInfo->compactedSize;
+ CreateInfo.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
+ CreateInfo.info.type = pCreateInfo->type;
+ CreateInfo.info.flags = pCreateInfo->flags;
+
+ if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR)
+ {
+ CreateInfo.info.instanceCount = pCreateInfo->maxGeometryCount;
+ }
+ else if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR)
+ {
+ Geometries.resize(pCreateInfo->maxGeometryCount);
+
+ for (uint32_t i = 0; i < pCreateInfo->maxGeometryCount; ++i)
+ {
+ auto& src = pCreateInfo->pGeometryInfos[i];
+ auto& dst = Geometries[i];
+
+ VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR);
+ VERIFY_EXPR(src.pNext == nullptr);
+
+ dst.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
+ dst.pNext = nullptr;
+ dst.geometryType = src.geometryType;
+ dst.flags = 0;
+
+ dst.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
+ dst.geometry.triangles.pNext = nullptr;
+
+ dst.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
+ dst.geometry.aabbs.pNext = nullptr;
+
+ if (dst.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR)
+ {
+ dst.geometry.triangles.vertexData = VK_NULL_HANDLE;
+ dst.geometry.triangles.vertexOffset = 0;
+ dst.geometry.triangles.vertexCount = src.maxVertexCount;
+ dst.geometry.triangles.vertexStride = 0;
+ dst.geometry.triangles.vertexFormat = src.vertexFormat;
+ dst.geometry.triangles.indexData = VK_NULL_HANDLE;
+ dst.geometry.triangles.indexOffset = 0;
+ dst.geometry.triangles.indexCount = 0;
+ dst.geometry.triangles.indexType = src.indexType;
+ dst.geometry.triangles.transformData = VK_NULL_HANDLE;
+ dst.geometry.triangles.transformOffset = 0;
+
+ if (dst.geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR)
+ {
+ VERIFY_EXPR(src.maxVertexCount == src.maxPrimitiveCount * 3);
+ dst.geometry.triangles.vertexCount = src.maxPrimitiveCount * 3;
+ }
+ else
+ {
+ dst.geometry.triangles.indexCount = src.maxPrimitiveCount * 3;
+ }
+ }
+ else if (dst.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR)
+ {
+ dst.geometry.aabbs.aabbData = VK_NULL_HANDLE;
+ dst.geometry.aabbs.numAABBs = src.maxPrimitiveCount;
+ dst.geometry.aabbs.stride = 0;
+ dst.geometry.aabbs.offset = 0;
+ }
+ }
+
+ CreateInfo.info.geometryCount = static_cast<uint32_t>(Geometries.size());
+ CreateInfo.info.pGeometries = Geometries.data();
+ }
+ else
+ {
+ UNEXPECTED("unknown AS type");
+ return VK_RESULT_MAX_ENUM;
+ }
+
+ return vkCreateAccelerationStructureNV(device, &CreateInfo, pAllocator, reinterpret_cast<VkAccelerationStructureNV*>(pAccelerationStructure));
+}
+
+static void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements)
+{
+ VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR);
+ VERIFY_EXPR(pInfo->pNext == nullptr);
+ VERIFY_EXPR(pInfo->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR);
+
+ VkAccelerationStructureMemoryRequirementsInfoNV Info = {};
+
+ Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
+ Info.type = pInfo->type;
+ Info.accelerationStructure = pInfo->accelerationStructure;
+
+ return vkGetAccelerationStructureMemoryRequirementsNV(device, &Info, pMemoryRequirements);
+}
+
+static VkResult VKAPI_CALL Redirect_vkBindAccelerationStructureMemoryKHR(VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos)
+{
+ VERIFY_EXPR(pBindInfos->sType == VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV);
+ return vkBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos);
+}
+
+static VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device,
+ const VkAccelerationStructureDeviceAddressInfoKHR* pInfo)
+{
+ VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR);
+ VERIFY_EXPR(pInfo->pNext == nullptr);
+
+ VkDeviceAddress result = 0;
+ vkGetAccelerationStructureHandleNV(device, pInfo->accelerationStructure, sizeof(result), &result);
+ return result;
+}
+
+static void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer,
+ uint32_t infoCount,
+ const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
+ const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
+{
+ std::vector<VkGeometryNV> Geometries;
+
+ for (uint32_t i = 0; i < infoCount; ++i)
+ {
+ auto& SrcInfo = pInfos[i];
+ auto& SrcOffset = ppOffsetInfos[i];
+
+ VERIFY_EXPR(SrcInfo.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR);
+ VERIFY_EXPR(SrcInfo.pNext == nullptr);
+
+ BufferAndOffset Scratch = DeviceAddressToBuffer(SrcInfo.scratchData);
+
+ VkAccelerationStructureInfoNV Info = {};
+
+ Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
+ Info.pNext = nullptr;
+ Info.type = SrcInfo.type;
+ Info.flags = SrcInfo.flags;
+
+ if (Info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR)
+ {
+ VERIFY_EXPR(SrcInfo.geometryCount == 1);
+ VERIFY_EXPR(SrcInfo.geometryArrayOfPointers == VK_FALSE);
+ VERIFY_EXPR((*SrcInfo.ppGeometries)[0].geometry.instances.arrayOfPointers == VK_FALSE);
+
+ Info.instanceCount = SrcOffset->primitiveCount;
+
+ BufferAndOffset Instance = DeviceAddressToBuffer((*SrcInfo.ppGeometries)[0].geometry.instances.data);
+
+ vkCmdBuildAccelerationStructureNV(commandBuffer, &Info,
+ Instance.Buffer, Instance.Offset + SrcOffset[0].primitiveOffset,
+ SrcInfo.update,
+ SrcInfo.dstAccelerationStructure, SrcInfo.srcAccelerationStructure,
+ Scratch.Buffer, Scratch.Offset);
+ }
+ else if (Info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR)
+ {
+ VERIFY_EXPR(SrcInfo.geometryArrayOfPointers == VK_FALSE);
+
+ Geometries.resize(SrcInfo.geometryCount);
+
+ for (uint32_t j = 0; j < SrcInfo.geometryCount; ++j)
+ {
+ auto& src = (*SrcInfo.ppGeometries)[j];
+ auto& dst = Geometries[j];
+ auto& off = SrcOffset[j];
+
+ VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR);
+ VERIFY_EXPR(src.pNext == nullptr);
+ VERIFY_EXPR(src.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || src.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR);
+
+ dst.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
+ dst.pNext = nullptr;
+ dst.flags = src.flags;
+ dst.geometryType = src.geometryType;
+
+ if (dst.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR)
+ {
+ VERIFY_EXPR(src.geometry.triangles.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR);
+ VERIFY_EXPR(src.geometry.triangles.pNext == nullptr);
+ VERIFY_EXPR(off.firstVertex == 0);
+
+ BufferAndOffset VB = DeviceAddressToBuffer(src.geometry.triangles.vertexData);
+ BufferAndOffset IB = DeviceAddressToBuffer(src.geometry.triangles.indexData);
+ BufferAndOffset TB = DeviceAddressToBuffer(src.geometry.triangles.transformData);
+
+ dst.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
+ dst.geometry.triangles.pNext = nullptr;
+ dst.geometry.triangles.vertexData = VB.Buffer;
+ dst.geometry.triangles.vertexOffset = VB.Offset;
+ dst.geometry.triangles.vertexCount = 0;
+ dst.geometry.triangles.vertexStride = src.geometry.triangles.vertexStride;
+ dst.geometry.triangles.vertexFormat = src.geometry.triangles.vertexFormat;
+ dst.geometry.triangles.indexData = IB.Buffer;
+ dst.geometry.triangles.indexOffset = IB.Offset;
+ dst.geometry.triangles.indexCount = 0;
+ dst.geometry.triangles.indexType = src.geometry.triangles.indexType;
+ dst.geometry.triangles.transformData = TB.Buffer;
+ dst.geometry.triangles.transformOffset = TB.Offset + off.transformOffset;
+
+ if (dst.geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR)
+ {
+ dst.geometry.triangles.vertexOffset += off.primitiveOffset;
+ dst.geometry.triangles.vertexCount = off.primitiveCount * 3;
+ }
+ else
+ {
+ dst.geometry.triangles.indexOffset += off.primitiveOffset;
+ dst.geometry.triangles.indexCount = off.primitiveCount * 3;
+ }
+ }
+ else
+ {
+ VERIFY_EXPR(src.geometry.aabbs.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR);
+ VERIFY_EXPR(src.geometry.aabbs.pNext == nullptr);
+ VERIFY_EXPR(src.geometry.aabbs.stride <= std::numeric_limits<uint32_t>::max());
+
+ BufferAndOffset Data = DeviceAddressToBuffer(src.geometry.aabbs.data);
+
+ dst.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
+ dst.geometry.aabbs.pNext = nullptr;
+ dst.geometry.aabbs.aabbData = Data.Buffer;
+ dst.geometry.aabbs.numAABBs = off.primitiveCount;
+ dst.geometry.aabbs.stride = static_cast<uint32_t>(src.geometry.aabbs.stride);
+ dst.geometry.aabbs.offset = Data.Offset + off.primitiveOffset;
+ }
+ }
+
+ Info.geometryCount = static_cast<uint32_t>(Geometries.size());
+ Info.pGeometries = Geometries.data();
+
+ vkCmdBuildAccelerationStructureNV(commandBuffer, &Info,
+ VK_NULL_HANDLE, 0,
+ SrcInfo.update,
+ SrcInfo.dstAccelerationStructure, SrcInfo.srcAccelerationStructure,
+ Scratch.Buffer, Scratch.Offset);
+ }
+ else
+ {
+ UNEXPECTED("unknown AS type");
+ }
+ }
+}
+
+static void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
+ const VkCopyAccelerationStructureInfoKHR* pInfo)
+{
+ VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR);
+ VERIFY_EXPR(pInfo->pNext == nullptr);
+
+ vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode);
+}
+
+static void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
+ const VkStridedBufferRegionKHR* pRaygenShaderBindingTable,
+ const VkStridedBufferRegionKHR* pMissShaderBindingTable,
+ const VkStridedBufferRegionKHR* pHitShaderBindingTable,
+ const VkStridedBufferRegionKHR* pCallableShaderBindingTable,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth)
+{
+ vkCmdTraceRaysNV(commandBuffer,
+ pRaygenShaderBindingTable->buffer, pRaygenShaderBindingTable->offset,
+ pMissShaderBindingTable->buffer, pMissShaderBindingTable->offset, pMissShaderBindingTable->stride,
+ pHitShaderBindingTable->buffer, pHitShaderBindingTable->offset, pHitShaderBindingTable->stride,
+ pCallableShaderBindingTable->buffer, pCallableShaderBindingTable->offset, pCallableShaderBindingTable->stride,
+ width, height, depth);
+}
+
+static VkResult VKAPI_CALL Redirect_vkGetRayTracingShaderGroupHandlesKHR(VkDevice device,
+ VkPipeline pipeline,
+ uint32_t firstGroup,
+ uint32_t groupCount,
+ size_t dataSize,
+ void* pData)
+{
+ return vkGetRayTracingShaderGroupHandlesNV(device, pipeline, firstGroup, groupCount, dataSize, pData);
+}
+
+static VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines)
+{
+ std::vector<VkRayTracingPipelineCreateInfoNV> Infos;
+ std::vector<VkRayTracingShaderGroupCreateInfoNV> Groups;
+ Infos.resize(createInfoCount);
+
+ size_t GroupCount = 0;
+ for (uint32_t i = 0; i < createInfoCount; ++i)
+ {
+ GroupCount += pCreateInfos[i].groupCount;
+ }
+ Groups.resize(GroupCount);
+ GroupCount = 0;
+
+ for (uint32_t i = 0; i < createInfoCount; ++i)
+ {
+ auto& src = pCreateInfos[i];
+ auto& dst = Infos[i];
+
+ VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR);
+ VERIFY_EXPR(src.pNext == nullptr);
+ VERIFY_EXPR(src.libraries.libraryCount == 0);
+ VERIFY_EXPR(src.libraries.pLibraries == nullptr);
+ VERIFY_EXPR(src.pLibraryInterface == nullptr);
+
+ // copy groups
+ for (uint32_t j = 0; j < src.groupCount; ++j)
+ {
+ auto& srcg = src.pGroups[j];
+ auto& dstg = Groups[GroupCount + j];
+
+ VERIFY_EXPR(srcg.sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR);
+ VERIFY_EXPR(srcg.pNext == nullptr);
+
+ dstg.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
+ dstg.pNext = nullptr;
+ dstg.type = srcg.type;
+ dstg.generalShader = srcg.generalShader;
+ dstg.closestHitShader = srcg.closestHitShader;
+ dstg.anyHitShader = srcg.anyHitShader;
+ dstg.intersectionShader = srcg.intersectionShader;
+
+ VERIFY_EXPR(srcg.pNext == nullptr);
+ }
+
+ dst.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV;
+ dst.pNext = nullptr;
+ dst.flags = src.flags;
+ dst.stageCount = src.stageCount;
+ dst.pStages = src.pStages;
+ dst.groupCount = src.groupCount;
+ dst.pGroups = Groups.data() + GroupCount;
+ dst.maxRecursionDepth = src.maxRecursionDepth;
+ dst.layout = src.layout;
+ dst.basePipelineHandle = src.basePipelineHandle;
+ dst.basePipelineIndex = src.basePipelineIndex;
+
+ GroupCount += src.groupCount;
+ }
+
+ return vkCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, Infos.data(), pAllocator, pPipelines);
+}
+
+void EnableRayTracingKHRviaNV()
+{
+ vkCreateAccelerationStructureKHR = &Redirect_vkCreateAccelerationStructureKHR;
+ vkGetAccelerationStructureMemoryRequirementsKHR = &Redirect_vkGetAccelerationStructureMemoryRequirementsKHR;
+ vkBindAccelerationStructureMemoryKHR = &Redirect_vkBindAccelerationStructureMemoryKHR;
+ vkGetAccelerationStructureDeviceAddressKHR = &Redirect_vkGetAccelerationStructureDeviceAddressKHR;
+ vkCmdBuildAccelerationStructureKHR = &Redirect_vkCmdBuildAccelerationStructureKHR;
+ vkCmdCopyAccelerationStructureKHR = &Redirect_vkCmdCopyAccelerationStructureKHR;
+ vkGetRayTracingShaderGroupHandlesKHR = &Redirect_vkGetRayTracingShaderGroupHandlesKHR;
+ vkCreateRayTracingPipelinesKHR = &Redirect_vkCreateRayTracingPipelinesKHR;
+ vkCmdTraceRaysKHR = &Redirect_vkCmdTraceRaysKHR;
+
+ Origin_vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressKHR;
+ Origin_vkCreateBuffer = vkCreateBuffer;
+ Origin_vkDestroyBuffer = vkDestroyBuffer;
+ vkCreateBuffer = &Wrap_vkCreateBuffer;
+ vkDestroyBuffer = &Wrap_vkDestroyBuffer;
+ vkGetBufferDeviceAddressKHR = &Wrap_vkGetBufferDeviceAddressKHR;
+ vkGetBufferDeviceAddress = &Wrap_vkGetBufferDeviceAddressKHR;
+ vkGetBufferDeviceAddressEXT = &Wrap_vkGetBufferDeviceAddressKHR;
+}
+#endif // DILIGENT_USE_VOLK
+
+} // namespace VulkanUtilities