From: Boris Zanin Date: Fri, 18 Oct 2019 13:38:32 +0000 (+0200) Subject: Framework definitions for VK_KHR_ray_tracing X-Git-Tag: upstream/1.3.5~1469 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e69d916f62f1db42df99457aac98f5cff53b68bd;p=platform%2Fupstream%2FVK-GL-CTS.git Framework definitions for VK_KHR_ray_tracing Initial commit required to build VK_KHR_ray_tracing. Also contains framework definitions for wrappers used to run CTS with VK_NV_ray_tracing extention. Components: Framework, Vulkan VK-GL-CTS issue: 2143 Change-Id: I5fa7556f72fd0155f3eadfb0eaf2c8c84c540791 --- diff --git a/AndroidGen.mk b/AndroidGen.mk index d317943..ea11405 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -47,6 +47,7 @@ LOCAL_SRC_FILES := \ external/vulkancts/framework/vulkan/vkPlatform.cpp \ external/vulkancts/framework/vulkan/vkPrograms.cpp \ external/vulkancts/framework/vulkan/vkQueryUtil.cpp \ + external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp \ external/vulkancts/framework/vulkan/vkRef.cpp \ external/vulkancts/framework/vulkan/vkRefUtil.cpp \ external/vulkancts/framework/vulkan/vkRenderDocUtil.cpp \ diff --git a/external/fetch_sources.py b/external/fetch_sources.py index f412f7e..03b57fa 100644 --- a/external/fetch_sources.py +++ b/external/fetch_sources.py @@ -316,18 +316,18 @@ PACKAGES = [ GitRepo( "https://github.com/KhronosGroup/SPIRV-Tools.git", None, - "a9624b4d5d0bb1617d6e20dbaba174b07cee18ee", + "5a97e3a391677ff9baae8ccdf5c03c4d403d848b", "spirv-tools"), GitRepo( "https://github.com/KhronosGroup/glslang.git", None, - "540662253ea35e8e75122aac68f8542f993e3396", + "c7910056825a6791a33149fca20ee299daf6ed25", "glslang", removeTags = ["master-tot"]), GitRepo( "https://github.com/KhronosGroup/SPIRV-Headers.git", None, - "dc77030acc9c6fe7ca21fff54c5a9d7b532d7da6", + "f8bf11a0253a32375c32cad92c841237b96696c0", "spirv-headers"), GitRepo( "https://github.com/google/amber.git", diff --git a/external/openglcts/modules/common/glcSpirvUtils.cpp b/external/openglcts/modules/common/glcSpirvUtils.cpp index 857b812..d30bc3b 100644 --- a/external/openglcts/modules/common/glcSpirvUtils.cpp +++ b/external/openglcts/modules/common/glcSpirvUtils.cpp @@ -59,7 +59,7 @@ EShLanguage getGlslangStage(glu::ShaderType type) { static const EShLanguage stageMap[] = { EShLangVertex, EShLangFragment, EShLangGeometry, EShLangTessControl, EShLangTessEvaluation, EShLangCompute, - EShLangRayGenNV, EShLangAnyHitNV, EShLangClosestHitNV, EShLangMissNV, EShLangIntersectNV, EShLangCallableNV + EShLangRayGen, EShLangAnyHit, EShLangClosestHit, EShLangMiss, EShLangIntersect, EShLangCallable }; return de::getSizedArrayElement(stageMap, type); diff --git a/external/vulkancts/framework/vulkan/CMakeLists.txt b/external/vulkancts/framework/vulkan/CMakeLists.txt index c307da7..37dc216 100644 --- a/external/vulkancts/framework/vulkan/CMakeLists.txt +++ b/external/vulkancts/framework/vulkan/CMakeLists.txt @@ -74,6 +74,8 @@ set(VKUTILNOSHADER_SRCS vkDeviceProperties.hpp vkDeviceProperties.cpp vkDeviceProperties.inl + vkRayTracingUtil.hpp + vkRayTracingUtil.cpp ) set(VKUTIL_SRCS diff --git a/external/vulkancts/framework/vulkan/vkBarrierUtil.cpp b/external/vulkancts/framework/vulkan/vkBarrierUtil.cpp index b0bed43..f047d14 100644 --- a/external/vulkancts/framework/vulkan/vkBarrierUtil.cpp +++ b/external/vulkancts/framework/vulkan/vkBarrierUtil.cpp @@ -88,4 +88,49 @@ VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask, return barrier; } +void cmdPipelineMemoryBarrier (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkMemoryBarrier* pMemoryBarriers, + const size_t memoryBarrierCount, + const VkDependencyFlags dependencyFlags) +{ + const deUint32 memoryBarrierCount32 =static_cast(memoryBarrierCount); + + DE_ASSERT(memoryBarrierCount == memoryBarrierCount32); + + vk.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount32, pMemoryBarriers, 0u, DE_NULL, 0u, DE_NULL); +} + +void cmdPipelineBufferMemoryBarrier (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + const size_t bufferMemoryBarrierCount, + const VkDependencyFlags dependencyFlags) +{ + const deUint32 bufferMemoryBarrierCount32 =static_cast(bufferMemoryBarrierCount); + + DE_ASSERT(bufferMemoryBarrierCount == bufferMemoryBarrierCount32); + + vk.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, DE_NULL, bufferMemoryBarrierCount32, pBufferMemoryBarriers, 0u, DE_NULL); +} + +void cmdPipelineImageMemoryBarrier (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkImageMemoryBarrier* pImageMemoryBarriers, + const size_t imageMemoryBarrierCount, + const VkDependencyFlags dependencyFlags) +{ + const deUint32 imageMemoryBarrierCount32 =static_cast(imageMemoryBarrierCount); + + DE_ASSERT(imageMemoryBarrierCount == imageMemoryBarrierCount32); + + vk.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, DE_NULL, 0u, DE_NULL, imageMemoryBarrierCount32, pImageMemoryBarriers); +} + } // vkt diff --git a/external/vulkancts/framework/vulkan/vkBarrierUtil.hpp b/external/vulkancts/framework/vulkan/vkBarrierUtil.hpp index a803f6d..269a099 100644 --- a/external/vulkancts/framework/vulkan/vkBarrierUtil.hpp +++ b/external/vulkancts/framework/vulkan/vkBarrierUtil.hpp @@ -50,6 +50,30 @@ VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask, const VkAccessFlags dstAccessMask); +void cmdPipelineMemoryBarrier (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkMemoryBarrier* pMemoryBarriers, + const size_t memoryBarrierCount = 1u, + const VkDependencyFlags dependencyFlags = 0); + +void cmdPipelineBufferMemoryBarrier (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + const size_t bufferMemoryBarrierCount = 1u, + const VkDependencyFlags dependencyFlags = 0); + +void cmdPipelineImageMemoryBarrier (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkImageMemoryBarrier* pImageMemoryBarriers, + const size_t imageMemoryBarrierCount = 1u, + const VkDependencyFlags dependencyFlags = 0); + } // vk #endif // _VKBARRIERUTIL_HPP diff --git a/external/vulkancts/framework/vulkan/vkBuilderUtil.cpp b/external/vulkancts/framework/vulkan/vkBuilderUtil.cpp index bbeee7e..4032289 100644 --- a/external/vulkancts/framework/vulkan/vkBuilderUtil.cpp +++ b/external/vulkancts/framework/vulkan/vkBuilderUtil.cpp @@ -200,13 +200,14 @@ DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::write (VkDescriptorSet VkDescriptorType descriptorType, const VkDescriptorImageInfo* pImageInfo, const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) + const VkBufferView* pTexelBufferView, + const void* pNext) { // pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update() const VkWriteDescriptorSet writeParams = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - DE_NULL, + pNext, destSet, //!< destSet destBinding, //!< destBinding destArrayElement, //!< destArrayElement diff --git a/external/vulkancts/framework/vulkan/vkBuilderUtil.hpp b/external/vulkancts/framework/vulkan/vkBuilderUtil.hpp index 3e13b71..24cdbc0 100644 --- a/external/vulkancts/framework/vulkan/vkBuilderUtil.hpp +++ b/external/vulkancts/framework/vulkan/vkBuilderUtil.hpp @@ -163,7 +163,8 @@ public: VkDescriptorType descriptorType, const VkDescriptorImageInfo* pImageInfo, const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView); + const VkBufferView* pTexelBufferView, + const void* pNext = DE_NULL); DescriptorSetUpdateBuilder& copy (VkDescriptorSet srcSet, deUint32 srcBinding, @@ -203,6 +204,14 @@ public: return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, 1u, descriptorType, DE_NULL, DE_NULL, pTexelBufferView); } + inline DescriptorSetUpdateBuilder& writeSingle (VkDescriptorSet destSet, + const Location& destLocation, + VkDescriptorType descriptorType, + const VkWriteDescriptorSetAccelerationStructureKHR* pAccelerationStructure) + { + return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, 1u, descriptorType, DE_NULL, DE_NULL, DE_NULL, pAccelerationStructure); + } + inline DescriptorSetUpdateBuilder& writeArray (VkDescriptorSet destSet, const Location& destLocation, VkDescriptorType descriptorType, diff --git a/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp b/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp new file mode 100644 index 0000000..fb90f95 --- /dev/null +++ b/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp @@ -0,0 +1,2143 @@ +/*------------------------------------------------------------------------- + * Vulkan CTS Framework + * -------------------- + * + * Copyright (c) 2020 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Utilities for creating commonly used Vulkan objects + *//*--------------------------------------------------------------------*/ + +#include "vkRayTracingUtil.hpp" + +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkObjUtil.hpp" +#include "vkBarrierUtil.hpp" + +#include +#include +#include + +namespace vk +{ + +std::string getCommonRayGenerationShader (void) +{ + return + "#version 460 core\n" + "#extension GL_EXT_nonuniform_qualifier : enable\n" + "#extension GL_EXT_ray_tracing : require\n" + "layout(location = 0) rayPayloadEXT vec3 hitValue;\n" + "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n" + "\n" + "void main()\n" + "{\n" + " uint rayFlags = 0;\n" + " uint cullMask = 0xFF;\n" + " float tmin = 0.0;\n" + " float tmax = 9.0;\n" + " vec3 origin = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), (float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n" + " vec3 direct = vec3(0.0, 0.0, -1.0);\n" + " traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n" + "}\n"; +} + +const char* getRayTracingExtensionUsed (void) +{ + return "VK_KHR_ray_tracing"; +} + +RaytracedGeometryBase::RaytracedGeometryBase (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType) + : m_geometryType (geometryType) + , m_vertexFormat (vertexFormat) + , m_indexType (indexType) + , m_geometryFlags ((VkGeometryFlagsKHR)0u) +{ +} + +RaytracedGeometryBase::~RaytracedGeometryBase () +{ +} + +de::SharedPtr makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType) +{ + switch (vertexFormat) + { + case VK_FORMAT_R32G32_SFLOAT: + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_UINT32: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr(new RaytracedGeometry(geometryType)); + default: TCU_THROW(InternalError, "Wrong index type"); + }; + case VK_FORMAT_R32G32B32_SFLOAT: + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_UINT32: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr(new RaytracedGeometry(geometryType)); + default: TCU_THROW(InternalError, "Wrong index type"); + }; + case VK_FORMAT_R16G16_SFLOAT: + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_UINT32: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr(new RaytracedGeometry(geometryType)); + default: TCU_THROW(InternalError, "Wrong index type"); + }; + case VK_FORMAT_R16G16B16A16_SFLOAT: + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_UINT32: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr(new RaytracedGeometry(geometryType)); + default: TCU_THROW(InternalError, "Wrong index type"); + }; + case VK_FORMAT_R16G16_SNORM: + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_UINT32: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr(new RaytracedGeometry(geometryType)); + default: TCU_THROW(InternalError, "Wrong index type"); + }; + case VK_FORMAT_R16G16B16A16_SNORM: + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_UINT32: return de::SharedPtr(new RaytracedGeometry(geometryType)); + case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr(new RaytracedGeometry(geometryType)); + default: TCU_THROW(InternalError, "Wrong index type"); + }; + default: + TCU_THROW(InternalError, "Wrong vertex format"); + }; + +} + +static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR (const void* hostAddress) +{ + // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported. + VkDeviceOrHostAddressConstKHR result; + + deMemset(&result, 0, sizeof(result)); + + result.hostAddress = hostAddress; + + return result; +} + +static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR (void* hostAddress) +{ + // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported. + VkDeviceOrHostAddressKHR result; + + deMemset(&result, 0, sizeof(result)); + + result.hostAddress = hostAddress; + + return result; +} + +static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR (const DeviceInterface& vk, + const VkDevice device, + VkBuffer buffer, + VkDeviceSize offset) +{ + // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported. + VkDeviceOrHostAddressConstKHR result; + + deMemset(&result, 0, sizeof(result)); + + VkBufferDeviceAddressInfo bufferDeviceAddressInfo = + { + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + buffer, // VkBuffer buffer + }; + result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset; + + return result; +} + +static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR (const DeviceInterface& vk, + const VkDevice device, + VkBuffer buffer, + VkDeviceSize offset) +{ + // VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported. + VkDeviceOrHostAddressKHR result; + + deMemset(&result, 0, sizeof(result)); + + VkBufferDeviceAddressInfo bufferDeviceAddressInfo = + { + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + buffer, // VkBuffer buffer + }; + result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset; + + return result; +} + +static inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureGeometryDataKHR (const VkAccelerationStructureGeometryTrianglesDataKHR& triangles) +{ + VkAccelerationStructureGeometryDataKHR result; + + deMemset(&result, 0, sizeof(result)); + + result.triangles = triangles; + + return result; +} + +static inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureGeometryDataKHR (const VkAccelerationStructureGeometryAabbsDataKHR& aabbs) +{ + VkAccelerationStructureGeometryDataKHR result; + + deMemset(&result, 0, sizeof(result)); + + result.aabbs = aabbs; + + return result; +} + +static inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureInstancesDataKHR (const VkAccelerationStructureGeometryInstancesDataKHR& instances) +{ + VkAccelerationStructureGeometryDataKHR result; + + deMemset(&result, 0, sizeof(result)); + + result.instances = instances; + + return result; +} + +static inline VkAccelerationStructureInstanceKHR makeVkAccelerationStructureInstanceKHR (const VkTransformMatrixKHR& transform, + deUint32 instanceCustomIndex, + deUint32 mask, + deUint32 instanceShaderBindingTableRecordOffset, + VkGeometryInstanceFlagsKHR flags, + deUint64 accelerationStructureReference) +{ + VkAccelerationStructureInstanceKHR instance = { transform, 0, 0, 0, 0, accelerationStructureReference }; + instance.instanceCustomIndex = instanceCustomIndex & 0xFFFFFF; + instance.mask = mask & 0xFF; + instance.instanceShaderBindingTableRecordOffset = instanceShaderBindingTableRecordOffset & 0xFFFFFF; + instance.flags = flags & 0xFF; + return instance; +} + +static inline VkMemoryRequirements getAccelerationStructureMemoryRequirements (const DeviceInterface& vk, + const VkDevice device, + const VkAccelerationStructureKHR accelerationStructure, + const VkAccelerationStructureMemoryRequirementsTypeKHR memoryRequirementsType, + const VkAccelerationStructureBuildTypeKHR buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) +{ + const VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirementsInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + memoryRequirementsType, // VkAccelerationStructureMemoryRequirementsTypeKHR type; + buildType, // VkAccelerationStructureBuildTypeKHR buildType; + accelerationStructure // VkAccelerationStructureKHR accelerationStructure; + }; + VkMemoryRequirements2 memoryRequirements2 = + { + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType sType; + DE_NULL, // void* pNext; + {0, 0, 0} // VkMemoryRequirements memoryRequirements; + }; + + vk.getAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirementsInfoKHR, &memoryRequirements2); + + return memoryRequirements2.memoryRequirements; +} + +VkResult getRayTracingShaderGroupHandlesKHR (const DeviceInterface& vk, + const VkDevice device, + const VkPipeline pipeline, + const deUint32 firstGroup, + const deUint32 groupCount, + const deUintptr dataSize, + void* pData) +{ + return vk.getRayTracingShaderGroupHandlesKHR(device, pipeline, firstGroup, groupCount, dataSize, pData); +} + +VkResult getRayTracingShaderGroupHandles (const DeviceInterface& vk, + const VkDevice device, + const VkPipeline pipeline, + const deUint32 firstGroup, + const deUint32 groupCount, + const deUintptr dataSize, + void* pData) +{ + return getRayTracingShaderGroupHandlesKHR(vk, device, pipeline, firstGroup, groupCount, dataSize, pData); +} + +VkResult finishDeferredOperation (const DeviceInterface& vk, + VkDevice device, + VkDeferredOperationKHR deferredOperation) +{ + VkResult result = vk.deferredOperationJoinKHR(device, deferredOperation); + + while (result == VK_THREAD_IDLE_KHR) + { + std::this_thread::yield(); + result = vk.deferredOperationJoinKHR(device, deferredOperation); + } + + switch( result ) + { + case VK_SUCCESS: + { + // Deferred operation has finished. Query its result + result = vk.getDeferredOperationResultKHR(device, deferredOperation); + + break; + } + + case VK_THREAD_DONE_KHR: + { + // Deferred operation is being wrapped up by another thread + // wait for that thread to finish + do + { + std::this_thread::yield(); + result = vk.getDeferredOperationResultKHR(device, deferredOperation); + } while (result == VK_NOT_READY); + + break; + } + + default: + { + DE_ASSERT(false); + + break; + } + } + + return result; +} + +SerialStorage::SerialStorage (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + const VkAccelerationStructureBuildTypeKHR buildType, + const VkDeviceSize storageSize) + : m_buildType (buildType) +{ + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(storageSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + m_buffer = de::MovePtr(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress)); +} + +VkDeviceOrHostAddressKHR SerialStorage::getAddress (const DeviceInterface& vk, + const VkDevice device) +{ + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + return makeDeviceOrHostAddressKHR(vk, device, m_buffer->get(), 0); + else + return makeDeviceOrHostAddressKHR(m_buffer->getAllocation().getHostPtr()); +} + +VkDeviceOrHostAddressConstKHR SerialStorage::getAddressConst (const DeviceInterface& vk, + const VkDevice device) +{ + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + return makeDeviceOrHostAddressConstKHR(vk, device, m_buffer->get(), 0); + else + return makeDeviceOrHostAddressConstKHR(m_buffer->getAllocation().getHostPtr()); +} + + +BottomLevelAccelerationStructure::~BottomLevelAccelerationStructure () +{ +} + +BottomLevelAccelerationStructure::BottomLevelAccelerationStructure () + : m_geometriesData () +{ +} + +void BottomLevelAccelerationStructure::setGeometryData (const std::vector& geometryData, + const bool triangles, + const VkGeometryFlagsKHR geometryFlags) +{ + if (triangles) + DE_ASSERT((geometryData.size() % 3) == 0); + else + DE_ASSERT((geometryData.size() % 2) == 0); + + setGeometryCount(1u); + + addGeometry(geometryData, triangles, geometryFlags); +} + +void BottomLevelAccelerationStructure::setDefaultGeometryData (const VkShaderStageFlagBits testStage) +{ + bool trianglesData = false; + float z = 0.0f; + std::vector geometryData; + + switch (testStage) + { + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: z = -1.0f; trianglesData = true; break; + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: z = -1.0f; trianglesData = true; break; + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: z = -1.0f; trianglesData = true; break; + case VK_SHADER_STAGE_MISS_BIT_KHR: z = -9.9f; trianglesData = true; break; + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: z = -1.0f; trianglesData = false; break; + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: z = -1.0f; trianglesData = true; break; + default: TCU_THROW(InternalError, "Unacceptable stage"); + } + + if (trianglesData) + { + geometryData.reserve(6); + + geometryData.push_back(tcu::Vec3(-1.0f, -1.0f, z)); + geometryData.push_back(tcu::Vec3(-1.0f, +1.0f, z)); + geometryData.push_back(tcu::Vec3(+1.0f, -1.0f, z)); + geometryData.push_back(tcu::Vec3(-1.0f, +1.0f, z)); + geometryData.push_back(tcu::Vec3(+1.0f, -1.0f, z)); + geometryData.push_back(tcu::Vec3(+1.0f, +1.0f, z)); + } + else + { + geometryData.reserve(2); + + geometryData.push_back(tcu::Vec3(-1.0f, -1.0f, z)); + geometryData.push_back(tcu::Vec3(+1.0f, +1.0f, z)); + } + + setGeometryCount(1u); + + addGeometry(geometryData, trianglesData); +} + +void BottomLevelAccelerationStructure::setGeometryCount (const size_t geometryCount) +{ + m_geometriesData.clear(); + + m_geometriesData.reserve(geometryCount); +} + +void BottomLevelAccelerationStructure::addGeometry (de::SharedPtr& raytracedGeometry) +{ + m_geometriesData.push_back(raytracedGeometry); +} + +void BottomLevelAccelerationStructure::addGeometry (const std::vector& geometryData, + const bool triangles, + const VkGeometryFlagsKHR geometryFlags) +{ + DE_ASSERT(geometryData.size() > 0); + DE_ASSERT((triangles && geometryData.size() % 3 == 0) || (!triangles && geometryData.size() % 2 == 0)); + + if (!triangles) + for (size_t posNdx = 0; posNdx < geometryData.size() / 2; ++posNdx) + { + DE_ASSERT(geometryData[2 * posNdx].x() <= geometryData[2 * posNdx + 1].x()); + DE_ASSERT(geometryData[2 * posNdx].y() <= geometryData[2 * posNdx + 1].y()); + DE_ASSERT(geometryData[2 * posNdx].z() <= geometryData[2 * posNdx + 1].z()); + } + + de::SharedPtr geometry = makeRaytracedGeometry(triangles ? VK_GEOMETRY_TYPE_TRIANGLES_KHR : VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR); + for (auto it = begin(geometryData), eit = end(geometryData); it != eit; ++it) + geometry->addVertex(*it); + + geometry->setGeometryFlags(geometryFlags); + addGeometry(geometry); +} + +BufferWithMemory* createVertexBuffer (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + const std::vector>& geometriesData) +{ + DE_ASSERT(geometriesData.size() != 0); + + VkDeviceSize bufferSizeBytes = 0; + for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx) + bufferSizeBytes += deAlignSize(geometriesData[geometryNdx]->getVertexByteSize(),8); + + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress); +} + +void updateVertexBuffer (const DeviceInterface& vk, + const VkDevice device, + const std::vector>& geometriesData, + BufferWithMemory* vertexBuffer) +{ + const Allocation& geometryAlloc = vertexBuffer->getAllocation(); + deUint8* bufferStart = static_cast(geometryAlloc.getHostPtr()); + VkDeviceSize bufferOffset = 0; + + for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx) + { + const void* geometryPtr = geometriesData[geometryNdx]->getVertexPointer(); + const size_t geometryPtrSize = geometriesData[geometryNdx]->getVertexByteSize(); + + deMemcpy(&bufferStart[bufferOffset], geometryPtr, geometryPtrSize); + + bufferOffset += deAlignSize(geometryPtrSize,8); + } + + flushMappedMemoryRange(vk, device, geometryAlloc.getMemory(), geometryAlloc.getOffset(), VK_WHOLE_SIZE); +} + +BufferWithMemory* createIndexBuffer (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + const std::vector>& geometriesData) +{ + DE_ASSERT(!geometriesData.empty()); + + VkDeviceSize bufferSizeBytes = 0; + for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx) + if(geometriesData[geometryNdx]->getIndexType() != VK_INDEX_TYPE_NONE_KHR) + bufferSizeBytes += deAlignSize(geometriesData[geometryNdx]->getIndexByteSize(),8); + + if (bufferSizeBytes == 0) + return DE_NULL; + + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress); +} + +void updateIndexBuffer (const DeviceInterface& vk, + const VkDevice device, + const std::vector>& geometriesData, + BufferWithMemory* indexBuffer) +{ + const Allocation& indexAlloc = indexBuffer->getAllocation(); + deUint8* bufferStart = static_cast(indexAlloc.getHostPtr()); + VkDeviceSize bufferOffset = 0; + + for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx) + { + if (geometriesData[geometryNdx]->getIndexType() != VK_INDEX_TYPE_NONE_KHR) + { + const void* indexPtr = geometriesData[geometryNdx]->getIndexPointer(); + const size_t indexPtrSize = geometriesData[geometryNdx]->getIndexByteSize(); + + deMemcpy(&bufferStart[bufferOffset], indexPtr, indexPtrSize); + + bufferOffset += deAlignSize(indexPtrSize, 8); + } + } + + flushMappedMemoryRange(vk, device, indexAlloc.getMemory(), indexAlloc.getOffset(), VK_WHOLE_SIZE); +} + +class BottomLevelAccelerationStructureKHR : public BottomLevelAccelerationStructure +{ +public: + static deUint32 getRequiredAllocationCount (void); + + BottomLevelAccelerationStructureKHR (); + BottomLevelAccelerationStructureKHR (const BottomLevelAccelerationStructureKHR& other) = delete; + virtual ~BottomLevelAccelerationStructureKHR (); + + void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) override; + void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR flags) override; + void setDeferredOperation (const bool deferredOperation) override; + void setUseArrayOfPointers (const bool useArrayOfPointers) override; + void setIndirectBuildParameters (const VkBuffer indirectBuffer, + const VkDeviceSize indirectBufferOffset, + const deUint32 indirectBufferStride) override; + VkBuildAccelerationStructureFlagsKHR getBuildFlags () const override; + + void create (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + VkDeviceAddress deviceAddress, + VkDeviceSize compactCopySize) override; + void build (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer) override; + void copyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + BottomLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) override; + + void serialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) override; + void deserialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) override; + + const VkAccelerationStructureKHR* getPtr (void) const override; + +protected: + VkAccelerationStructureBuildTypeKHR m_buildType; + VkBuildAccelerationStructureFlagsKHR m_buildFlags; + bool m_deferredOperation; + bool m_useArrayOfPointers; + de::MovePtr m_vertexBuffer; + de::MovePtr m_indexBuffer; + de::MovePtr m_accelerationStructureAlloc; + de::MovePtr m_scratchBuffer; + Move m_accelerationStructureKHR; + VkBuffer m_indirectBuffer; + VkDeviceSize m_indirectBufferOffset; + deUint32 m_indirectBufferStride; +}; + +deUint32 BottomLevelAccelerationStructureKHR::getRequiredAllocationCount (void) +{ + /* + de::MovePtr m_geometryBuffer; // but only when m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR + de::MovePtr m_accelerationStructureAlloc; + de::MovePtr m_scratchBuffer; + */ + return 3u; +} + +BottomLevelAccelerationStructureKHR::~BottomLevelAccelerationStructureKHR () +{ +} + +BottomLevelAccelerationStructureKHR::BottomLevelAccelerationStructureKHR () + : BottomLevelAccelerationStructure () + , m_buildType (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + , m_buildFlags (0u) + , m_deferredOperation (false) + , m_useArrayOfPointers (false) + , m_vertexBuffer () + , m_indexBuffer () + , m_accelerationStructureAlloc () + , m_scratchBuffer () + , m_accelerationStructureKHR () + , m_indirectBuffer (DE_NULL) + , m_indirectBufferOffset (0) + , m_indirectBufferStride (0) +{ +} + +void BottomLevelAccelerationStructureKHR::setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) +{ + m_buildType = buildType; +} + +void BottomLevelAccelerationStructureKHR::setBuildFlags (const VkBuildAccelerationStructureFlagsKHR flags) +{ + m_buildFlags = flags; +} + +void BottomLevelAccelerationStructureKHR::setDeferredOperation (const bool deferredOperation) +{ + m_deferredOperation = deferredOperation; +} + +void BottomLevelAccelerationStructureKHR::setUseArrayOfPointers (const bool useArrayOfPointers) +{ + m_useArrayOfPointers = useArrayOfPointers; +} + +void BottomLevelAccelerationStructureKHR::setIndirectBuildParameters (const VkBuffer indirectBuffer, + const VkDeviceSize indirectBufferOffset, + const deUint32 indirectBufferStride) +{ + m_indirectBuffer = indirectBuffer; + m_indirectBufferOffset = indirectBufferOffset; + m_indirectBufferStride = indirectBufferStride; +} + +VkBuildAccelerationStructureFlagsKHR BottomLevelAccelerationStructureKHR::getBuildFlags () const +{ + return m_buildFlags; +} + +void BottomLevelAccelerationStructureKHR::create (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + VkDeviceAddress deviceAddress, + VkDeviceSize compactCopySize) +{ + DE_ASSERT(!m_geometriesData.empty() != !(compactCopySize==0)); // logical xor + + { + std::vector accelerationStructureCreateGeometryTypeInfosKHR(m_geometriesData.size()); + + for (size_t geometryNdx = 0; geometryNdx < m_geometriesData.size(); ++geometryNdx) + { + de::SharedPtr& geometryData = m_geometriesData[geometryNdx]; + const VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationStructureCreateGeometryTypeInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + geometryData->getGeometryType(), // VkGeometryTypeKHR geometryType; + geometryData->getPrimitiveCount(), // deUint32 maxPrimitiveCount; + geometryData->getIndexType(), // VkIndexType indexType; + geometryData->getVertexCount(), // deUint32 maxVertexCount; + geometryData->getVertexFormat(), // VkFormat vertexFormat; + DE_FALSE // VkBool32 allowsTransforms; + }; + + accelerationStructureCreateGeometryTypeInfosKHR[geometryNdx] = accelerationStructureCreateGeometryTypeInfoKHR; + } + + const VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + compactCopySize, // VkDeviceSize compactedSize; + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, // VkAccelerationStructureTypeKHR type; + m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags; + static_cast(accelerationStructureCreateGeometryTypeInfosKHR.size()), // deUint32 maxGeometryCount; + dataOrNullPtr(accelerationStructureCreateGeometryTypeInfosKHR), // const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos; + deviceAddress // VkDeviceAddress deviceAddress; + }; + + m_accelerationStructureKHR = createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL); + } + + { + const VkMemoryRequirements memoryRequirements = getAccelerationStructureMemoryRequirements(vk, device, m_accelerationStructureKHR.get(), VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR, m_buildType); + + m_accelerationStructureAlloc = allocator.allocate(memoryRequirements, vk::MemoryRequirement::Local); + } + + { + const VkBindAccelerationStructureMemoryInfoKHR bindAccelerationStructureMemoryInfoKHR = + { + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + m_accelerationStructureKHR.get(), // VkAccelerationStructureKHR accelerationStructure; + m_accelerationStructureAlloc->getMemory(), // VkDeviceMemory memory; + m_accelerationStructureAlloc->getOffset(), // VkDeviceSize memoryOffset; + 0, // deUint32 deviceIndexCount; + DE_NULL, // const deUint32* pDeviceIndices; + }; + + VK_CHECK(vk.bindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationStructureMemoryInfoKHR)); + } + + { + const VkMemoryRequirements memoryRequirements = getAccelerationStructureMemoryRequirements(vk, device, m_accelerationStructureKHR.get(), VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR, m_buildType); + if (memoryRequirements.size > 0u) + { + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(memoryRequirements.size, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + m_scratchBuffer = de::MovePtr(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress)); + } + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR && !m_geometriesData.empty()) + { + m_vertexBuffer = de::MovePtr(createVertexBuffer(vk, device, allocator, m_geometriesData)); + m_indexBuffer = de::MovePtr(createIndexBuffer(vk, device, allocator, m_geometriesData)); + } +} + +void BottomLevelAccelerationStructureKHR::build (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer) +{ + DE_ASSERT(!m_geometriesData.empty()); + DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL); + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + updateVertexBuffer(vk, device, m_geometriesData, m_vertexBuffer.get()); + if(m_indexBuffer.get() != DE_NULL) + updateIndexBuffer(vk, device, m_geometriesData, m_indexBuffer.get()); + } + + { + std::vector accelerationStructureGeometriesKHR (m_geometriesData.size()); + std::vector accelerationStructureGeometriesKHRPointers (m_geometriesData.size()); + std::vector accelerationStructureBuildOffsetInfoKHR (m_geometriesData.size()); + VkDeviceSize vertexBufferOffset = 0, indexBufferOffset = 0; + + for (size_t geometryNdx = 0; geometryNdx < m_geometriesData.size(); ++geometryNdx) + { + de::SharedPtr& geometryData = m_geometriesData[geometryNdx]; + VkDeviceOrHostAddressConstKHR vertexData, indexData; + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vertexData = makeDeviceOrHostAddressConstKHR(vk, device, m_vertexBuffer->get(), vertexBufferOffset); + vertexBufferOffset += deAlignSize(geometryData->getVertexByteSize(), 8); + + if (geometryData->getIndexType() != VK_INDEX_TYPE_NONE_KHR) + { + indexData = makeDeviceOrHostAddressConstKHR(vk, device, m_indexBuffer->get(), indexBufferOffset); + indexBufferOffset += deAlignSize(geometryData->getIndexByteSize(), 8); + } + else + indexData = makeDeviceOrHostAddressConstKHR(DE_NULL); + } + else + { + vertexData = makeDeviceOrHostAddressConstKHR( geometryData->getVertexPointer() ); + if (m_indexBuffer.get() != DE_NULL) + indexData = makeDeviceOrHostAddressConstKHR( geometryData->getIndexPointer() ); + else + indexData = makeDeviceOrHostAddressConstKHR(DE_NULL); + } + + const VkAccelerationStructureGeometryTrianglesDataKHR accelerationStructureGeometryTrianglesDataKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + geometryData->getVertexFormat(), // VkFormat vertexFormat; + vertexData, // VkDeviceOrHostAddressConstKHR vertexData; + geometryData->getVertexStride(), // VkDeviceSize vertexStride; + geometryData->getIndexType(), // VkIndexType indexType; + indexData, // VkDeviceOrHostAddressConstKHR indexData; + makeDeviceOrHostAddressConstKHR(DE_NULL), // VkDeviceOrHostAddressConstKHR transformData; + }; + + const VkAccelerationStructureGeometryAabbsDataKHR accelerationStructureGeometryAabbsDataKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + vertexData, // VkDeviceOrHostAddressConstKHR data; + geometryData->getAABBStride() // VkDeviceSize stride; + }; + const VkAccelerationStructureGeometryDataKHR geometry = (geometryData->isTrianglesType()) + ? makeVkAccelerationStructureGeometryDataKHR(accelerationStructureGeometryTrianglesDataKHR) + : makeVkAccelerationStructureGeometryDataKHR(accelerationStructureGeometryAabbsDataKHR); + const VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + geometryData->getGeometryType(), // VkGeometryTypeKHR geometryType; + geometry, // VkAccelerationStructureGeometryDataKHR geometry; + geometryData->getGeometryFlags() // VkGeometryFlagsKHR flags; + }; + + const VkAccelerationStructureBuildOffsetInfoKHR accelerationStructureBuildOffsetInfosKHR = + { + geometryData->getPrimitiveCount(), // deUint32 primitiveCount; + 0, // deUint32 primitiveOffset; + 0, // deUint32 firstVertex; + 0 // deUint32 firstTransform; + }; + + accelerationStructureGeometriesKHR[geometryNdx] = accelerationStructureGeometryKHR; + accelerationStructureGeometriesKHRPointers[geometryNdx] = &accelerationStructureGeometriesKHR[geometryNdx]; + accelerationStructureBuildOffsetInfoKHR[geometryNdx] = accelerationStructureBuildOffsetInfosKHR; + } + + VkAccelerationStructureGeometryKHR* accelerationStructureGeometriesKHRPointer = accelerationStructureGeometriesKHR.data(); + VkAccelerationStructureGeometryKHR** accelerationStructureGeometry = (m_useArrayOfPointers) + ? accelerationStructureGeometriesKHRPointers.data() + : &accelerationStructureGeometriesKHRPointer; + VkDeviceOrHostAddressKHR scratchData = (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + ? makeDeviceOrHostAddressKHR(vk, device, m_scratchBuffer->get(), 0) + : makeDeviceOrHostAddressKHR(m_scratchBuffer->getAllocation().getHostPtr()); + + VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, // VkAccelerationStructureTypeKHR type; + m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags; + DE_FALSE, // VkBool32 update; + DE_NULL, // VkAccelerationStructureKHR srcAccelerationStructure; + m_accelerationStructureKHR.get(), // VkAccelerationStructureKHR dstAccelerationStructure; + (VkBool32)( m_useArrayOfPointers ? DE_TRUE : DE_FALSE ), // VkBool32 geometryArrayOfPointers; + static_cast(accelerationStructureGeometriesKHR.size()), // deUint32 geometryCount; + (const VkAccelerationStructureGeometryKHR**)accelerationStructureGeometry, // const VkAccelerationStructureGeometryKHR** ppGeometries; + scratchData // VkDeviceOrHostAddressKHR scratchData; + }; + VkAccelerationStructureBuildOffsetInfoKHR* accelerationStructureBuildOffsetInfoKHRPtr = accelerationStructureBuildOffsetInfoKHR.data(); + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + if (m_indirectBuffer == DE_NULL) + vk.cmdBuildAccelerationStructureKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildOffsetInfoKHR**)&accelerationStructureBuildOffsetInfoKHRPtr); + else + vk.cmdBuildAccelerationStructureIndirectKHR(cmdBuffer, &accelerationStructureBuildGeometryInfoKHR, m_indirectBuffer, m_indirectBufferOffset, m_indirectBufferStride); + } + else if (!m_deferredOperation) + { + VK_CHECK(vk.buildAccelerationStructureKHR(device, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildOffsetInfoKHR**)&accelerationStructureBuildOffsetInfoKHRPtr)); + } + else + { + VkDeferredOperationKHR deferredOperation = DE_NULL; + + VK_CHECK(vk.createDeferredOperationKHR(device, DE_NULL, &deferredOperation)); + + VkDeferredOperationInfoKHR deferredOperationInfoKHR = + { + VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + deferredOperation // VkDeferredOperationKHR operationHandle; + }; + + accelerationStructureBuildGeometryInfoKHR.pNext = &deferredOperationInfoKHR; + + VkResult result = vk.buildAccelerationStructureKHR(device, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildOffsetInfoKHR**)&accelerationStructureBuildOffsetInfoKHRPtr); + + DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS); + DE_UNREF(result); + + VK_CHECK(finishDeferredOperation(vk, device, deferredOperation)); + + accelerationStructureBuildGeometryInfoKHR.pNext = DE_NULL; + } + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks); + + cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier); + } +} + +void BottomLevelAccelerationStructureKHR::copyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + BottomLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) +{ + VkCopyAccelerationStructureInfoKHR copyAccelerationStructureInfo = + { + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + *(accelerationStructure->getPtr()), // VkAccelerationStructureKHR src; + *(getPtr()), // VkAccelerationStructureKHR dst; + compactCopySize > 0u ? VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR : VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR // VkCopyAccelerationStructureModeKHR mode; + }; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vk.cmdCopyAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo); + } + else if (!m_deferredOperation) + { + VK_CHECK(vk.copyAccelerationStructureKHR(device, ©AccelerationStructureInfo)); + } + else + { + VkDeferredOperationKHR deferredOperation = DE_NULL; + + VK_CHECK(vk.createDeferredOperationKHR(device, DE_NULL, &deferredOperation)); + + VkDeferredOperationInfoKHR deferredOperationInfoKHR = + { + VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + deferredOperation // VkDeferredOperationKHR operationHandle; + }; + + copyAccelerationStructureInfo.pNext = &deferredOperationInfoKHR; + + VkResult result = vk.copyAccelerationStructureKHR(device, ©AccelerationStructureInfo); + + DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS); + DE_UNREF(result); + + VK_CHECK(finishDeferredOperation(vk, device, deferredOperation)); + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks); + + cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier); + } +} + +void BottomLevelAccelerationStructureKHR::serialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) +{ + VkCopyAccelerationStructureToMemoryInfoKHR copyAccelerationStructureInfo = + { + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + *(getPtr()), // VkAccelerationStructureKHR src; + storage->getAddress(vk,device), // VkDeviceOrHostAddressKHR dst; + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode; + }; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vk.cmdCopyAccelerationStructureToMemoryKHR(cmdBuffer, ©AccelerationStructureInfo); + } + else + { + VK_CHECK(vk.copyAccelerationStructureToMemoryKHR(device, ©AccelerationStructureInfo)); + } + // There is no deferred operation for vkCopyAccelerationStructureToMemoryKHR +} + +void BottomLevelAccelerationStructureKHR::deserialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) +{ + VkCopyMemoryToAccelerationStructureInfoKHR copyAccelerationStructureInfo = + { + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + storage->getAddressConst(vk,device), // VkDeviceOrHostAddressConstKHR src; + *(getPtr()), // VkAccelerationStructureKHR dst; + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode; + }; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vk.cmdCopyMemoryToAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo); + } + else + { + VK_CHECK(vk.copyMemoryToAccelerationStructureKHR(device, ©AccelerationStructureInfo)); + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks); + + cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier); + } +} + +const VkAccelerationStructureKHR* BottomLevelAccelerationStructureKHR::getPtr (void) const +{ + return &m_accelerationStructureKHR.get(); +} + +deUint32 BottomLevelAccelerationStructure::getRequiredAllocationCount (void) +{ + return BottomLevelAccelerationStructureKHR::getRequiredAllocationCount(); +} + +void BottomLevelAccelerationStructure::createAndBuild (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress) +{ + create(vk, device, allocator, deviceAddress, 0u); + build(vk, device, cmdBuffer); +} + +void BottomLevelAccelerationStructure::createAndCopyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress, + BottomLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) +{ + create(vk, device, allocator, deviceAddress, compactCopySize); + copyFrom(vk, device, cmdBuffer, accelerationStructure, compactCopySize); +} + +void BottomLevelAccelerationStructure::createAndDeserializeFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress, + SerialStorage* storage) +{ + create(vk, device, allocator, deviceAddress, 0u); + deserialize(vk, device, cmdBuffer, storage); +} + +de::MovePtr makeBottomLevelAccelerationStructure () +{ + return de::MovePtr(new BottomLevelAccelerationStructureKHR); +} + +TopLevelAccelerationStructure::~TopLevelAccelerationStructure () +{ +} + +TopLevelAccelerationStructure::TopLevelAccelerationStructure () + : m_bottomLevelInstances () +{ +} + +void TopLevelAccelerationStructure::setInstanceCount (const size_t instanceCount) +{ + m_bottomLevelInstances.reserve(instanceCount); + m_instanceData.reserve(instanceCount); +} + +void TopLevelAccelerationStructure::addInstance (de::SharedPtr bottomLevelStructure, + const VkTransformMatrixKHR& matrix, + deUint32 instanceCustomIndex, + deUint32 mask, + deUint32 instanceShaderBindingTableRecordOffset, + VkGeometryInstanceFlagsKHR flags) +{ + m_bottomLevelInstances.push_back(bottomLevelStructure); + m_instanceData.push_back(InstanceData(matrix, instanceCustomIndex, mask, instanceShaderBindingTableRecordOffset, flags)); +} + +void TopLevelAccelerationStructure::createAndBuild (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress) +{ + create(vk, device, allocator, deviceAddress, 0u); + build(vk, device, cmdBuffer); +} + +void TopLevelAccelerationStructure::createAndCopyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress, + TopLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) +{ + create(vk, device, allocator, deviceAddress, compactCopySize); + copyFrom(vk, device, cmdBuffer, accelerationStructure, compactCopySize); +} + +void TopLevelAccelerationStructure::createAndDeserializeFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress, + SerialStorage* storage) +{ + create(vk, device, allocator, deviceAddress, 0u); + deserialize(vk, device, cmdBuffer, storage); +} + +BufferWithMemory* createInstanceBuffer (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + std::vector > bottomLevelInstances, + std::vector instanceData) +{ + DE_ASSERT(bottomLevelInstances.size() != 0); + DE_ASSERT(bottomLevelInstances.size() == instanceData.size()); + DE_UNREF(instanceData); + + const VkDeviceSize bufferSizeBytes = bottomLevelInstances.size() * sizeof(VkAccelerationStructureInstanceKHR); + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress); +} + +void updateInstanceBuffer (const DeviceInterface& vk, + const VkDevice device, + std::vector > bottomLevelInstances, + std::vector instanceData, + BufferWithMemory* instanceBuffer, + VkAccelerationStructureBuildTypeKHR buildType) +{ + DE_ASSERT(bottomLevelInstances.size() != 0); + DE_ASSERT(bottomLevelInstances.size() == instanceData.size()); + + const Allocation& instancesAlloc = instanceBuffer->getAllocation(); + + deUint8* bufferStart = static_cast(instancesAlloc.getHostPtr()); + VkDeviceSize bufferOffset = 0; + + for (size_t instanceNdx = 0; instanceNdx < bottomLevelInstances.size(); ++instanceNdx) + { + const BottomLevelAccelerationStructure& bottomLevelAccelerationStructure = *bottomLevelInstances[instanceNdx]; + const VkAccelerationStructureKHR accelerationStructureKHR = *bottomLevelAccelerationStructure.getPtr(); + + // This part needs to be fixed once a new version of the VkAccelerationStructureInstanceKHR will be added to vkStructTypes.inl + VkDeviceAddress accelerationStructureAddress; + if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + VkAccelerationStructureDeviceAddressInfoKHR asDeviceAddressInfo = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + accelerationStructureKHR // VkAccelerationStructureKHR accelerationStructure; + }; + accelerationStructureAddress = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo); + } + + const deUint64 structureReference = (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + ? deUint64(accelerationStructureAddress) + : deUint64(&accelerationStructureKHR); + + VkAccelerationStructureInstanceKHR accelerationStructureInstanceKHR = makeVkAccelerationStructureInstanceKHR + ( + instanceData[instanceNdx].matrix, // VkTransformMatrixKHR transform; + instanceData[instanceNdx].instanceCustomIndex, // deUint32 instanceCustomIndex:24; + instanceData[instanceNdx].mask, // deUint32 mask:8; + instanceData[instanceNdx].instanceShaderBindingTableRecordOffset, // deUint32 instanceShaderBindingTableRecordOffset:24; + instanceData[instanceNdx].flags, // VkGeometryInstanceFlagsKHR flags:8; + structureReference // deUint64 accelerationStructureReference; + ); + + deMemcpy(&bufferStart[bufferOffset], &accelerationStructureInstanceKHR, sizeof(VkAccelerationStructureInstanceKHR)); + + bufferOffset += sizeof(VkAccelerationStructureInstanceKHR); + } + + flushMappedMemoryRange(vk, device, instancesAlloc.getMemory(), instancesAlloc.getOffset(), VK_WHOLE_SIZE); +} + +class TopLevelAccelerationStructureKHR : public TopLevelAccelerationStructure +{ +public: + static deUint32 getRequiredAllocationCount (void); + + TopLevelAccelerationStructureKHR (); + TopLevelAccelerationStructureKHR (const TopLevelAccelerationStructureKHR& other) = delete; + virtual ~TopLevelAccelerationStructureKHR (); + + void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) override; + void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR flags) override; + void setDeferredOperation (const bool deferredOperation) override; + void setUseArrayOfPointers (const bool useArrayOfPointers) override; + void setIndirectBuildParameters (const VkBuffer indirectBuffer, + const VkDeviceSize indirectBufferOffset, + const deUint32 indirectBufferStride) override; + VkBuildAccelerationStructureFlagsKHR getBuildFlags () const override; + + void create (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + VkDeviceAddress deviceAddress, + VkDeviceSize compactCopySize) override; + void build (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer) override; + void copyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + TopLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) override; + + void serialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) override; + void deserialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) override; + + const VkAccelerationStructureKHR* getPtr (void) const override; + +protected: + VkAccelerationStructureBuildTypeKHR m_buildType; + VkBuildAccelerationStructureFlagsKHR m_buildFlags; + bool m_deferredOperation; + bool m_useArrayOfPointers; + de::MovePtr m_instanceBuffer; + de::MovePtr m_instanceAddressBuffer; + de::MovePtr m_accelerationStructureAlloc; + de::MovePtr m_scratchBuffer; + Move m_accelerationStructureKHR; + VkBuffer m_indirectBuffer; + VkDeviceSize m_indirectBufferOffset; + deUint32 m_indirectBufferStride; +}; + +deUint32 TopLevelAccelerationStructureKHR::getRequiredAllocationCount (void) +{ + /* + de::MovePtr m_instanceBuffer; + de::MovePtr m_accelerationStructureAlloc; + de::MovePtr m_scratchBuffer; + */ + return 3u; +} + +TopLevelAccelerationStructureKHR::TopLevelAccelerationStructureKHR () + : TopLevelAccelerationStructure () + , m_buildType (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + , m_buildFlags (0u) + , m_deferredOperation (false) + , m_useArrayOfPointers (false) + , m_instanceBuffer () + , m_instanceAddressBuffer () + , m_accelerationStructureAlloc () + , m_scratchBuffer () + , m_accelerationStructureKHR () + , m_indirectBuffer (DE_NULL) + , m_indirectBufferOffset (0) + , m_indirectBufferStride (0) +{ +} + +TopLevelAccelerationStructureKHR::~TopLevelAccelerationStructureKHR () +{ +} + +void TopLevelAccelerationStructureKHR::setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) +{ + m_buildType = buildType; +} + +void TopLevelAccelerationStructureKHR::setBuildFlags (const VkBuildAccelerationStructureFlagsKHR flags) +{ + m_buildFlags = flags; +} + +void TopLevelAccelerationStructureKHR::setDeferredOperation (const bool deferredOperation) +{ + m_deferredOperation = deferredOperation; +} + +void TopLevelAccelerationStructureKHR::setUseArrayOfPointers (const bool useArrayOfPointers) +{ + m_useArrayOfPointers = useArrayOfPointers; +} + +void TopLevelAccelerationStructureKHR::setIndirectBuildParameters (const VkBuffer indirectBuffer, + const VkDeviceSize indirectBufferOffset, + const deUint32 indirectBufferStride) +{ + m_indirectBuffer = indirectBuffer; + m_indirectBufferOffset = indirectBufferOffset; + m_indirectBufferStride = indirectBufferStride; +} + +VkBuildAccelerationStructureFlagsKHR TopLevelAccelerationStructureKHR::getBuildFlags () const +{ + return m_buildFlags; +} + +void TopLevelAccelerationStructureKHR::create (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + VkDeviceAddress deviceAddress, + VkDeviceSize compactCopySize) +{ + DE_ASSERT(!m_bottomLevelInstances.empty() != !(compactCopySize == 0)); // logical xor + + { + const VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationStructureCreateGeometryTypeInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_GEOMETRY_TYPE_INSTANCES_KHR, // VkGeometryTypeKHR geometryType; + static_cast(m_bottomLevelInstances.size()), // deUint32 maxPrimitiveCount; + VK_INDEX_TYPE_NONE_KHR, // VkIndexType indexType; + 0u, // deUint32 maxVertexCount; + VK_FORMAT_UNDEFINED, // VkFormat vertexFormat; + DE_FALSE // VkBool32 allowsTransforms; + }; + const VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + compactCopySize, // VkDeviceSize compactedSize; + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, // VkAccelerationStructureTypeKHR type; + m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags; + 1u, // deUint32 maxGeometryCount; + &accelerationStructureCreateGeometryTypeInfoKHR, // const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos; + deviceAddress // VkDeviceAddress deviceAddress; + }; + + m_accelerationStructureKHR = createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL); + } + + { + const VkMemoryRequirements memoryRequirements = getAccelerationStructureMemoryRequirements(vk, device, m_accelerationStructureKHR.get(), VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR, m_buildType); + + m_accelerationStructureAlloc = allocator.allocate(memoryRequirements, vk::MemoryRequirement::Local); + } + + { + const VkBindAccelerationStructureMemoryInfoKHR bindAccelerationStructureMemoryInfoKHR = + { + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + m_accelerationStructureKHR.get(), // VkAccelerationStructureKHR accelerationStructure; + m_accelerationStructureAlloc->getMemory(), // VkDeviceMemory memory; + m_accelerationStructureAlloc->getOffset(), // VkDeviceSize memoryOffset; + 0, // deUint32 deviceIndexCount; + DE_NULL, // const deUint32* pDeviceIndices; + }; + + VK_CHECK(vk.bindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationStructureMemoryInfoKHR)); + } + + { + const VkMemoryRequirements memoryRequirements = getAccelerationStructureMemoryRequirements(vk, device, m_accelerationStructureKHR.get(), VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR, m_buildType); + if(memoryRequirements.size > 0u) + { + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(memoryRequirements.size, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + m_scratchBuffer = de::MovePtr(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress)); + } + } + + if (m_useArrayOfPointers) + { + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bottomLevelInstances.size() * sizeof(VkDeviceOrHostAddressConstKHR), VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + m_instanceAddressBuffer = de::MovePtr(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress)); + } + + if(!m_bottomLevelInstances.empty()) + m_instanceBuffer = de::MovePtr(createInstanceBuffer(vk, device, allocator, m_bottomLevelInstances, m_instanceData)); +} + +void TopLevelAccelerationStructureKHR::build (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer) +{ + DE_ASSERT(!m_bottomLevelInstances.empty()); + DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL); + + updateInstanceBuffer(vk, device, m_bottomLevelInstances, m_instanceData, m_instanceBuffer.get(), m_buildType); + + VkDeviceOrHostAddressConstKHR instancesData; + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + if (m_useArrayOfPointers) + { + deUint8* bufferStart = static_cast(m_instanceAddressBuffer->getAllocation().getHostPtr()); + VkDeviceSize bufferOffset = 0; + VkDeviceOrHostAddressConstKHR firstInstance = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceBuffer->get(), 0); + for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx) + { + VkDeviceOrHostAddressConstKHR currentInstance; + currentInstance.deviceAddress = firstInstance.deviceAddress + instanceNdx * sizeof(VkAccelerationStructureInstanceKHR); + + deMemcpy(&bufferStart[bufferOffset], ¤tInstance, sizeof(VkDeviceOrHostAddressConstKHR)); + bufferOffset += sizeof(VkDeviceOrHostAddressConstKHR); + } + flushMappedMemoryRange(vk, device, m_instanceAddressBuffer->getAllocation().getMemory(), m_instanceAddressBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE); + + instancesData = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceAddressBuffer->get(), 0); + } + else + instancesData = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceBuffer->get(), 0); + } + else + { + if (m_useArrayOfPointers) + { + deUint8* bufferStart = static_cast(m_instanceAddressBuffer->getAllocation().getHostPtr()); + VkDeviceSize bufferOffset = 0; + for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx) + { + VkDeviceOrHostAddressConstKHR currentInstance; + currentInstance.hostAddress = (deUint8*)m_instanceBuffer->getAllocation().getHostPtr() + instanceNdx * sizeof(VkAccelerationStructureInstanceKHR); + + deMemcpy(&bufferStart[bufferOffset], ¤tInstance, sizeof(VkDeviceOrHostAddressConstKHR)); + bufferOffset += sizeof(VkDeviceOrHostAddressConstKHR); + } + instancesData = makeDeviceOrHostAddressConstKHR(m_instanceAddressBuffer->getAllocation().getHostPtr()); + } + else + instancesData = makeDeviceOrHostAddressConstKHR(m_instanceBuffer->getAllocation().getHostPtr()); + } + + VkAccelerationStructureGeometryInstancesDataKHR accelerationStructureGeometryInstancesDataKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkBool32)( m_useArrayOfPointers ? DE_TRUE : DE_FALSE ), // VkBool32 arrayOfPointers; + instancesData // VkDeviceOrHostAddressConstKHR data; + }; + + VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_GEOMETRY_TYPE_INSTANCES_KHR, // VkGeometryTypeKHR geometryType; + makeVkAccelerationStructureInstancesDataKHR(accelerationStructureGeometryInstancesDataKHR), // VkAccelerationStructureGeometryDataKHR geometry; + (VkGeometryFlagsKHR)0u // VkGeometryFlagsKHR flags; + }; + VkAccelerationStructureGeometryKHR* accelerationStructureGeometryKHRPointer = &accelerationStructureGeometryKHR; + + VkDeviceOrHostAddressKHR scratchData; + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + scratchData = makeDeviceOrHostAddressKHR(vk, device, m_scratchBuffer->get(), 0); + else + scratchData = makeDeviceOrHostAddressKHR(m_scratchBuffer->getAllocation().getHostPtr()); + + VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR = + { + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, // VkAccelerationStructureTypeKHR type; + m_buildFlags, // VkBuildAccelerationStructureFlagsKHR flags; + DE_FALSE, // VkBool32 update; + DE_NULL, // VkAccelerationStructureKHR srcAccelerationStructure; + m_accelerationStructureKHR.get(), // VkAccelerationStructureKHR dstAccelerationStructure; + DE_FALSE, // VkBool32 geometryArrayOfPointers; + 1u, // deUint32 geometryCount; + (const VkAccelerationStructureGeometryKHR**)&accelerationStructureGeometryKHRPointer, // const VkAccelerationStructureGeometryKHR** ppGeometries; + scratchData // VkDeviceOrHostAddressKHR scratchData; + }; + + VkAccelerationStructureBuildOffsetInfoKHR accelerationStructureBuildOffsetInfoKHR = + { + (deUint32)m_bottomLevelInstances.size(), // deUint32 primitiveCount; + 0, // deUint32 primitiveOffset; + 0, // deUint32 firstVertex; + 0 // deUint32 firstTransform; + }; + VkAccelerationStructureBuildOffsetInfoKHR* accelerationStructureBuildOffsetInfoKHRPtr = &accelerationStructureBuildOffsetInfoKHR; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + if (m_indirectBuffer == DE_NULL) + vk.cmdBuildAccelerationStructureKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildOffsetInfoKHR**)&accelerationStructureBuildOffsetInfoKHRPtr); + else + vk.cmdBuildAccelerationStructureIndirectKHR(cmdBuffer, &accelerationStructureBuildGeometryInfoKHR, m_indirectBuffer, m_indirectBufferOffset, m_indirectBufferStride); + } + else if (!m_deferredOperation) + { + VK_CHECK(vk.buildAccelerationStructureKHR(device, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildOffsetInfoKHR**)&accelerationStructureBuildOffsetInfoKHRPtr)); + } + else + { + VkDeferredOperationKHR deferredOperation = DE_NULL; + + VK_CHECK(vk.createDeferredOperationKHR(device, DE_NULL, &deferredOperation)); + + VkDeferredOperationInfoKHR deferredOperationInfoKHR = + { + VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + deferredOperation // VkDeferredOperationKHR operationHandle; + }; + + accelerationStructureBuildGeometryInfoKHR.pNext = &deferredOperationInfoKHR; + + VkResult result = vk.buildAccelerationStructureKHR(device, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildOffsetInfoKHR**)&accelerationStructureBuildOffsetInfoKHRPtr); + + DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS); + DE_UNREF(result); + + VK_CHECK(finishDeferredOperation(vk, device, deferredOperation)); + + accelerationStructureBuildGeometryInfoKHR.pNext = DE_NULL; + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks); + + cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier); + } +} + +void TopLevelAccelerationStructureKHR::copyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + TopLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) +{ + VkCopyAccelerationStructureInfoKHR copyAccelerationStructureInfo = + { + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + *(accelerationStructure->getPtr()), // VkAccelerationStructureKHR src; + *(getPtr()), // VkAccelerationStructureKHR dst; + compactCopySize > 0u ? VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR : VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR // VkCopyAccelerationStructureModeKHR mode; + }; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vk.cmdCopyAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo); + } + else if (!m_deferredOperation) + { + VK_CHECK(vk.copyAccelerationStructureKHR(device, ©AccelerationStructureInfo)); + } + else + { + VkDeferredOperationKHR deferredOperation = DE_NULL; + + VK_CHECK(vk.createDeferredOperationKHR(device, DE_NULL, &deferredOperation)); + + VkDeferredOperationInfoKHR deferredOperationInfoKHR = + { + VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + deferredOperation // VkDeferredOperationKHR operationHandle; + }; + + copyAccelerationStructureInfo.pNext = &deferredOperationInfoKHR; + + VkResult result = vk.copyAccelerationStructureKHR(device, ©AccelerationStructureInfo); + + DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS); + DE_UNREF(result); + + VK_CHECK(finishDeferredOperation(vk, device, deferredOperation)); + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks); + + cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier); + } + +} + +void TopLevelAccelerationStructureKHR::serialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) +{ + VkCopyAccelerationStructureToMemoryInfoKHR copyAccelerationStructureInfo = + { + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + *(getPtr()), // VkAccelerationStructureKHR src; + storage->getAddress(vk,device), // VkDeviceOrHostAddressKHR dst; + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode; + }; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vk.cmdCopyAccelerationStructureToMemoryKHR(cmdBuffer, ©AccelerationStructureInfo); + } + else + { + VK_CHECK(vk.copyAccelerationStructureToMemoryKHR(device, ©AccelerationStructureInfo)); + } + // There is no deferred operation for vkCopyAccelerationStructureToMemoryKHR +} + +void TopLevelAccelerationStructureKHR::deserialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) +{ + VkCopyMemoryToAccelerationStructureInfoKHR copyAccelerationStructureInfo = + { + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + storage->getAddressConst(vk,device), // VkDeviceOrHostAddressConstKHR src; + *(getPtr()), // VkAccelerationStructureKHR dst; + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR // VkCopyAccelerationStructureModeKHR mode; + }; + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + vk.cmdCopyMemoryToAccelerationStructureKHR(cmdBuffer, ©AccelerationStructureInfo); + } + else + { + VK_CHECK(vk.copyMemoryToAccelerationStructureKHR(device, ©AccelerationStructureInfo)); + } + + if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + const VkAccessFlags accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + const VkMemoryBarrier memBarrier = makeMemoryBarrier(accessMasks, accessMasks); + + cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier); + } +} + +const VkAccelerationStructureKHR* TopLevelAccelerationStructureKHR::getPtr (void) const +{ + return &m_accelerationStructureKHR.get(); +} + +deUint32 TopLevelAccelerationStructure::getRequiredAllocationCount (void) +{ + return TopLevelAccelerationStructureKHR::getRequiredAllocationCount(); +} + +de::MovePtr makeTopLevelAccelerationStructure () +{ + return de::MovePtr(new TopLevelAccelerationStructureKHR); +} + +bool queryAccelerationStructureSizeKHR (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + const std::vector& accelerationStructureHandles, + VkAccelerationStructureBuildTypeKHR buildType, + const VkQueryPool queryPool, + VkQueryType queryType, + deUint32 firstQuery, + std::vector& results) +{ + DE_ASSERT(queryType == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR || queryType == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR); + + if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) + { + // queryPool must be large enough to contain at least (firstQuery + accelerationStructureHandles.size()) queries + vk.cmdResetQueryPool(cmdBuffer, queryPool, firstQuery, deUint32(accelerationStructureHandles.size())); + vk.cmdWriteAccelerationStructuresPropertiesKHR(cmdBuffer, deUint32(accelerationStructureHandles.size()), accelerationStructureHandles.data(), queryType, queryPool, firstQuery); + // results cannot be retrieved to CPU at the moment - you need to do it using getQueryPoolResults after cmdBuffer is executed. Meanwhile function returns a vector of 0s. + results.resize(accelerationStructureHandles.size(), 0u); + return false; + } + // buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR + results.resize(accelerationStructureHandles.size(), 0u); + vk.writeAccelerationStructuresPropertiesKHR(device, deUint32(accelerationStructureHandles.size()), accelerationStructureHandles.data(), queryType, sizeof(VkDeviceSize), results.data(), sizeof(VkDeviceSize)); + // results will contain proper values + return true; +} + +bool queryAccelerationStructureSize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + const std::vector& accelerationStructureHandles, + VkAccelerationStructureBuildTypeKHR buildType, + const VkQueryPool queryPool, + VkQueryType queryType, + deUint32 firstQuery, + std::vector& results) +{ + return queryAccelerationStructureSizeKHR(vk, device, cmdBuffer, accelerationStructureHandles, buildType, queryPool, queryType, firstQuery, results); +} + +RayTracingPipeline::RayTracingPipeline () + : m_shadersModules () + , m_pipelineLibraries () + , m_shaderCreateInfos () + , m_shadersGroupCreateInfos () + , m_pipelineCreateFlags (0U) + , m_maxRecursionDepth (1U) + , m_maxPayloadSize (0U) + , m_maxAttributeSize (0U) + , m_maxCallableSize (0U) + , m_deferredOperation (false) +{ +} + +RayTracingPipeline::~RayTracingPipeline () +{ +} + +#define CHECKED_ASSIGN_SHADER(SHADER, STAGE) \ + if (SHADER == VK_SHADER_UNUSED_KHR) \ + SHADER = STAGE; \ + else \ + TCU_THROW(InternalError, "Attempt to reassign shader") + +void RayTracingPipeline::addShader (VkShaderStageFlagBits shaderStage, Move shaderModule, deUint32 group) +{ + if (group >= m_shadersGroupCreateInfos.size()) + { + for (size_t groupNdx = m_shadersGroupCreateInfos.size(); groupNdx <= group; ++groupNdx) + { + VkRayTracingShaderGroupCreateInfoKHR shaderGroupCreateInfo = + { + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR, // VkRayTracingShaderGroupTypeKHR type; + VK_SHADER_UNUSED_KHR, // deUint32 generalShader; + VK_SHADER_UNUSED_KHR, // deUint32 closestHitShader; + VK_SHADER_UNUSED_KHR, // deUint32 anyHitShader; + VK_SHADER_UNUSED_KHR, // deUint32 intersectionShader; + DE_NULL, // const void* pShaderGroupCaptureReplayHandle; + }; + + m_shadersGroupCreateInfos.push_back(shaderGroupCreateInfo); + } + } + + const deUint32 shaderStageNdx = (deUint32)m_shaderCreateInfos.size(); + VkRayTracingShaderGroupCreateInfoKHR& shaderGroupCreateInfo = m_shadersGroupCreateInfos[group]; + + switch (shaderStage) + { + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader, shaderStageNdx); break; + case VK_SHADER_STAGE_MISS_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader, shaderStageNdx); break; + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader, shaderStageNdx); break; + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.anyHitShader, shaderStageNdx); break; + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.closestHitShader, shaderStageNdx); break; + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.intersectionShader, shaderStageNdx); break; + default: TCU_THROW(InternalError, "Unacceptable stage"); + } + + switch (shaderStage) + { + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + case VK_SHADER_STAGE_MISS_BIT_KHR: + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + { + DE_ASSERT(shaderGroupCreateInfo.type == VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR); + shaderGroupCreateInfo.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + + break; + } + + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + { + DE_ASSERT(shaderGroupCreateInfo.type != VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR); + shaderGroupCreateInfo.type = (shaderGroupCreateInfo.intersectionShader == VK_SHADER_UNUSED_KHR) + ? VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR + : VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; + + break; + } + + default: TCU_THROW(InternalError, "Unacceptable stage"); + } + + { + const VkPipelineShaderStageCreateInfo shaderCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + shaderStage, // VkShaderStageFlagBits stage; + *shaderModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + m_shaderCreateInfos.push_back(shaderCreateInfo); + } + + m_shadersModules.push_back(makeVkSharedPtr(shaderModule)); +} + +void RayTracingPipeline::addLibrary (de::SharedPtr> pipelineLibrary) +{ + m_pipelineLibraries.push_back(pipelineLibrary); +} + +Move RayTracingPipeline::createPipelineKHR (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const std::vector>>& pipelineLibraries) +{ + for (size_t groupNdx = 0; groupNdx < m_shadersGroupCreateInfos.size(); ++groupNdx) + DE_ASSERT(m_shadersGroupCreateInfos[groupNdx].sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR); + + DE_ASSERT(m_shaderCreateInfos.size() > 0); + DE_ASSERT(m_shadersGroupCreateInfos.size() > 0); + + std::vector vkPipelineLibraries; + for (auto it = begin(pipelineLibraries), eit = end(pipelineLibraries); it != eit; ++it) + vkPipelineLibraries.push_back( it->get()->get() ); + const VkPipelineLibraryCreateInfoKHR librariesCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + deUint32(vkPipelineLibraries.size()), // deUint32 libraryCount; + dataOrNullPtr(vkPipelineLibraries) // VkPipeline* pLibraries; + }; + const VkRayTracingPipelineInterfaceCreateInfoKHR pipelineInterfaceCreateInfo = + { + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + m_maxPayloadSize, // deUint32 maxPayloadSize; + m_maxAttributeSize, // deUint32 maxAttributeSize; + m_maxCallableSize // deUint32 maxCallableSize; + }; + const bool addPipelineInterfaceCreateInfo = m_maxPayloadSize != 0 || m_maxAttributeSize != 0 || m_maxCallableSize != 0; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pipelineInterfaceCreateInfoPtr = addPipelineInterfaceCreateInfo ? &pipelineInterfaceCreateInfo : DE_NULL; + Move deferredOperation = (m_deferredOperation ? createDeferredOperationKHR(vk, device) : Move()); + VkDeferredOperationInfoKHR deferredOperationInfoKHR = + { + VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + *deferredOperation // VkDeferredOperationKHR operationHandle; + }; + const VkDeferredOperationInfoKHR* deferredOperationInfoPtr = m_deferredOperation ? &deferredOperationInfoKHR : DE_NULL; + const VkRayTracingPipelineCreateInfoKHR pipelineCreateInfo = + { + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, // VkStructureType sType; + deferredOperationInfoPtr, // const void* pNext; + m_pipelineCreateFlags, // VkPipelineCreateFlags flags; + (deUint32)m_shaderCreateInfos.size(), // deUint32 stageCount; + m_shaderCreateInfos.data(), // const VkPipelineShaderStageCreateInfo* pStages; + (deUint32)m_shadersGroupCreateInfos.size(), // deUint32 groupCount; + m_shadersGroupCreateInfos.data(), // const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + m_maxRecursionDepth, // deUint32 maxRecursionDepth; + librariesCreateInfo, // VkPipelineLibraryCreateInfoKHR libraries; + pipelineInterfaceCreateInfoPtr, // VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + pipelineLayout, // VkPipelineLayout layout; + (VkPipeline)DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + VkPipeline object = DE_NULL; + VkResult result = vk.createRayTracingPipelinesKHR(device, DE_NULL, 1u, &pipelineCreateInfo, DE_NULL, &object); + Move pipeline (check(object), Deleter(vk, device, DE_NULL)); + + if (m_deferredOperation) + { + DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS); + DE_UNREF(result); + + VK_CHECK(finishDeferredOperation(vk, device, *deferredOperation)); + } + + return pipeline; +} + + +Move RayTracingPipeline::createPipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const std::vector>>& pipelineLibraries) +{ + return createPipelineKHR(vk, device, pipelineLayout, pipelineLibraries); +} + +std::vector>> RayTracingPipeline::createPipelineWithLibraries (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout) +{ + for (size_t groupNdx = 0; groupNdx < m_shadersGroupCreateInfos.size(); ++groupNdx) + DE_ASSERT(m_shadersGroupCreateInfos[groupNdx].sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR); + + DE_ASSERT(m_shaderCreateInfos.size() > 0); + DE_ASSERT(m_shadersGroupCreateInfos.size() > 0); + + std::vector>> result, allLibraries, firstLibraries; + for(auto it=begin(m_pipelineLibraries), eit=end(m_pipelineLibraries); it!=eit; ++it) + { + auto childLibraries = (*it)->get()->createPipelineWithLibraries(vk, device, pipelineLayout); + DE_ASSERT(childLibraries.size() > 0); + firstLibraries.push_back(childLibraries[0]); + std::copy(begin(childLibraries), end(childLibraries), std::back_inserter(allLibraries)); + } + result.push_back(makeVkSharedPtr(createPipeline(vk, device, pipelineLayout, firstLibraries))); + std::copy(begin(allLibraries), end(allLibraries), std::back_inserter(result)); + return result; +} + +de::MovePtr RayTracingPipeline::createShaderBindingTable (const DeviceInterface& vk, + const VkDevice device, + const VkPipeline pipeline, + Allocator& allocator, + const deUint32& shaderGroupHandleSize, + const deUint32 shaderGroupBaseAlignment, + const deUint32& firstGroup, + const deUint32& groupCount, + const VkBufferCreateFlags& additionalBufferCreateFlags, + const VkBufferUsageFlags& additionalBufferUsageFlags, + const MemoryRequirement& additionalMemoryRequirement, + const VkDeviceAddress& opaqueCaptureAddress, + const deUint32 shaderBindingTableOffset, + const deUint32 shaderRecordSize) +{ + DE_ASSERT(shaderGroupBaseAlignment != 0u); + DE_ASSERT((shaderBindingTableOffset % shaderGroupBaseAlignment) == 0); + DE_UNREF(shaderGroupBaseAlignment); + + const deUint32 sbtSize = shaderBindingTableOffset + groupCount * deAlign32(shaderGroupHandleSize + shaderRecordSize, shaderGroupHandleSize); + const VkBufferUsageFlags sbtFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | additionalBufferUsageFlags; + VkBufferCreateInfo sbtCreateInfo = makeBufferCreateInfo(sbtSize, sbtFlags); + sbtCreateInfo.flags |= additionalBufferCreateFlags; + VkBufferOpaqueCaptureAddressCreateInfo sbtCaptureAddressInfo = + { + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + deUint64(opaqueCaptureAddress) // deUint64 opaqueCaptureAddress; + }; + if (opaqueCaptureAddress != 0u) + sbtCreateInfo.pNext = &sbtCaptureAddressInfo; + const MemoryRequirement sbtMemRequirements = MemoryRequirement::HostVisible | MemoryRequirement::Coherent | additionalMemoryRequirement; + de::MovePtr sbtBuffer = de::MovePtr(new BufferWithMemory(vk, device, allocator, sbtCreateInfo, sbtMemRequirements)); + vk::Allocation& sbtAlloc = sbtBuffer->getAllocation(); + + // collect shader group handles + std::vector shaderHandles (groupCount * shaderGroupHandleSize); + VK_CHECK(getRayTracingShaderGroupHandles(vk, device, pipeline, firstGroup, groupCount, groupCount * shaderGroupHandleSize, shaderHandles.data())); + + // reserve place for ShaderRecordKHR after each shader handle ( ShaderRecordKHR size might be 0 ). Also take alignment into consideration + deUint8* shaderBegin = (deUint8*)sbtAlloc.getHostPtr() + shaderBindingTableOffset; + for (deUint32 idx = 0; idx < groupCount; ++idx) + { + deUint8* shaderSrcPos = shaderHandles.data() + idx * shaderGroupHandleSize; + deUint8* shaderDstPos = shaderBegin + idx * deAlign32(shaderGroupHandleSize + shaderRecordSize, shaderGroupHandleSize); + deMemcpy(shaderDstPos, shaderSrcPos, shaderGroupHandleSize); + } + + flushMappedMemoryRange(vk, device, sbtAlloc.getMemory(), sbtAlloc.getOffset(), VK_WHOLE_SIZE); + + return sbtBuffer; +} + +void RayTracingPipeline::setCreateFlags (const VkPipelineCreateFlags& pipelineCreateFlags) +{ + m_pipelineCreateFlags = pipelineCreateFlags; +} + +void RayTracingPipeline::setMaxRecursionDepth (const deUint32& maxRecursionDepth) +{ + m_maxRecursionDepth = maxRecursionDepth; +} + +void RayTracingPipeline::setMaxPayloadSize (const deUint32& maxPayloadSize) +{ + m_maxPayloadSize = maxPayloadSize; +} + +void RayTracingPipeline::setMaxAttributeSize (const deUint32& maxAttributeSize) +{ + m_maxAttributeSize = maxAttributeSize; +} + +void RayTracingPipeline::setMaxCallableSize (const deUint32& maxCallableSize) +{ + m_maxCallableSize = maxCallableSize; +} + +void RayTracingPipeline::setDeferredOperation (const bool deferredOperation) +{ + m_deferredOperation = deferredOperation; +} + +class RayTracingPropertiesKHR : public RayTracingProperties +{ +public: + RayTracingPropertiesKHR () = delete; + RayTracingPropertiesKHR (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice); + virtual ~RayTracingPropertiesKHR (); + + virtual deUint32 getShaderGroupHandleSize (void) { return m_rayTracingPropertiesKHR.shaderGroupHandleSize; }; + virtual deUint32 getMaxRecursionDepth (void) { return m_rayTracingPropertiesKHR.maxRecursionDepth; }; + virtual deUint32 getMaxShaderGroupStride (void) { return m_rayTracingPropertiesKHR.maxShaderGroupStride; }; + virtual deUint32 getShaderGroupBaseAlignment (void) { return m_rayTracingPropertiesKHR.shaderGroupBaseAlignment; }; + virtual deUint64 getMaxGeometryCount (void) { return m_rayTracingPropertiesKHR.maxGeometryCount; }; + virtual deUint64 getMaxInstanceCount (void) { return m_rayTracingPropertiesKHR.maxInstanceCount; }; + virtual deUint64 getMaxPrimitiveCount (void) { return m_rayTracingPropertiesKHR.maxPrimitiveCount; }; + virtual deUint32 getMaxDescriptorSetAccelerationStructures (void) { return m_rayTracingPropertiesKHR.maxDescriptorSetAccelerationStructures; }; + +protected: + VkPhysicalDeviceRayTracingPropertiesKHR m_rayTracingPropertiesKHR; +}; + +RayTracingPropertiesKHR::~RayTracingPropertiesKHR () +{ +} + +RayTracingPropertiesKHR::RayTracingPropertiesKHR (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice) + : RayTracingProperties (vki, physicalDevice) +{ + m_rayTracingPropertiesKHR = getPhysicalDeviceExtensionProperties(vki, physicalDevice); +} + +de::MovePtr makeRayTracingProperties (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice) +{ + return de::MovePtr(new RayTracingPropertiesKHR(vki, physicalDevice)); +} + +static inline void cmdTraceRaysKHR (const DeviceInterface& vk, + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* raygenShaderBindingTableRegion, + const VkStridedBufferRegionKHR* missShaderBindingTableRegion, + const VkStridedBufferRegionKHR* hitShaderBindingTableRegion, + const VkStridedBufferRegionKHR* callableShaderBindingTableRegion, + deUint32 width, + deUint32 height, + deUint32 depth) +{ + return vk.cmdTraceRaysKHR(commandBuffer, + raygenShaderBindingTableRegion, + missShaderBindingTableRegion, + hitShaderBindingTableRegion, + callableShaderBindingTableRegion, + width, + height, + depth); +} + + +void cmdTraceRays (const DeviceInterface& vk, + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* raygenShaderBindingTableRegion, + const VkStridedBufferRegionKHR* missShaderBindingTableRegion, + const VkStridedBufferRegionKHR* hitShaderBindingTableRegion, + const VkStridedBufferRegionKHR* callableShaderBindingTableRegion, + deUint32 width, + deUint32 height, + deUint32 depth) +{ + DE_ASSERT(raygenShaderBindingTableRegion != DE_NULL); + DE_ASSERT(missShaderBindingTableRegion != DE_NULL); + DE_ASSERT(hitShaderBindingTableRegion != DE_NULL); + DE_ASSERT(callableShaderBindingTableRegion != DE_NULL); + DE_ASSERT(width > 0); + DE_ASSERT(height > 0); + DE_ASSERT(depth > 0); + + return cmdTraceRaysKHR(vk, + commandBuffer, + raygenShaderBindingTableRegion, + missShaderBindingTableRegion, + hitShaderBindingTableRegion, + callableShaderBindingTableRegion, + width, + height, + depth); +} + +static inline void cmdTraceRaysIndirectKHR (const DeviceInterface& vk, + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* raygenShaderBindingTableRegion, + const VkStridedBufferRegionKHR* missShaderBindingTableRegion, + const VkStridedBufferRegionKHR* hitShaderBindingTableRegion, + const VkStridedBufferRegionKHR* callableShaderBindingTableRegion, + VkBuffer buffer, + VkDeviceSize offset) +{ + DE_ASSERT(raygenShaderBindingTableRegion != DE_NULL); + DE_ASSERT(missShaderBindingTableRegion != DE_NULL); + DE_ASSERT(hitShaderBindingTableRegion != DE_NULL); + DE_ASSERT(callableShaderBindingTableRegion != DE_NULL); + DE_ASSERT(buffer != DE_NULL); + + return vk.cmdTraceRaysIndirectKHR(commandBuffer, + raygenShaderBindingTableRegion, + missShaderBindingTableRegion, + hitShaderBindingTableRegion, + callableShaderBindingTableRegion, + buffer, + offset); +} + +void cmdTraceRaysIndirect (const DeviceInterface& vk, + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* raygenShaderBindingTableRegion, + const VkStridedBufferRegionKHR* missShaderBindingTableRegion, + const VkStridedBufferRegionKHR* hitShaderBindingTableRegion, + const VkStridedBufferRegionKHR* callableShaderBindingTableRegion, + VkBuffer buffer, + VkDeviceSize offset) +{ + return cmdTraceRaysIndirectKHR(vk, + commandBuffer, + raygenShaderBindingTableRegion, + missShaderBindingTableRegion, + hitShaderBindingTableRegion, + callableShaderBindingTableRegion, + buffer, + offset); +} + +} // vk diff --git a/external/vulkancts/framework/vulkan/vkRayTracingUtil.hpp b/external/vulkancts/framework/vulkan/vkRayTracingUtil.hpp new file mode 100644 index 0000000..8446d74 --- /dev/null +++ b/external/vulkancts/framework/vulkan/vkRayTracingUtil.hpp @@ -0,0 +1,595 @@ +#ifndef _VKRAYTRACINGUTIL_HPP +#define _VKRAYTRACINGUTIL_HPP +/*------------------------------------------------------------------------- + * Vulkan CTS Framework + * -------------------- + * + * Copyright (c) 2020 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Vulkan ray tracing utility. + *//*--------------------------------------------------------------------*/ + +#include "vkDefs.hpp" +#include "vkRef.hpp" +#include "vkMemUtil.hpp" +#include "vkBufferWithMemory.hpp" + +#include "deFloat16.h" + +#include "tcuVector.hpp" +#include "tcuVectorType.hpp" + +#include + +namespace vk +{ +const VkTransformMatrixKHR identityMatrix3x4 = { { { 1.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f } } }; + +template +inline de::SharedPtr> makeVkSharedPtr(Move move) +{ + return de::SharedPtr>(new Move(move)); +} + +template +inline de::SharedPtr > makeVkSharedPtr(de::MovePtr movePtr) +{ + return de::SharedPtr >(new de::MovePtr(movePtr)); +} + +template +inline const T* dataOrNullPtr(const std::vector& v) +{ + return (v.empty() ? DE_NULL : v.data()); +} + +template +inline T* dataOrNullPtr(std::vector& v) +{ + return (v.empty() ? DE_NULL : v.data()); +} + +inline std::string updateRayTracingGLSL (const std::string& str) +{ + return str; +} + +std::string getCommonRayGenerationShader (void); + +const char* getRayTracingExtensionUsed (void); + +class RaytracedGeometryBase +{ +public: + RaytracedGeometryBase () = delete; + RaytracedGeometryBase (const RaytracedGeometryBase& geometry) = delete; + RaytracedGeometryBase (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType); + virtual ~RaytracedGeometryBase (); + + inline VkGeometryTypeKHR getGeometryType (void) const { return m_geometryType; } + inline bool isTrianglesType (void) const { return m_geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR; } + inline VkFormat getVertexFormat (void) const { return m_vertexFormat; } + inline VkIndexType getIndexType (void) const { return m_indexType; } + inline bool usesIndices (void) const { return m_indexType != VK_INDEX_TYPE_NONE_KHR; } + inline VkGeometryFlagsKHR getGeometryFlags (void) const { return m_geometryFlags; } + inline void setGeometryFlags (const VkGeometryFlagsKHR geometryFlags) { m_geometryFlags = geometryFlags; } + virtual deUint32 getVertexCount (void) const = 0; + virtual const deUint8* getVertexPointer (void) const = 0; + virtual VkDeviceSize getVertexStride (void) const = 0; + virtual size_t getVertexByteSize (void) const = 0; + virtual VkDeviceSize getAABBStride (void) const = 0; + virtual deUint32 getIndexCount (void) const = 0; + virtual const deUint8* getIndexPointer (void) const = 0; + virtual VkDeviceSize getIndexStride (void) const = 0; + virtual size_t getIndexByteSize (void) const = 0; + virtual deUint32 getPrimitiveCount (void) const = 0; + virtual void addVertex (const tcu::Vec3& vertex) = 0; + virtual void addIndex (const deUint32& index) = 0; +private: + VkGeometryTypeKHR m_geometryType; + VkFormat m_vertexFormat; + VkIndexType m_indexType; + VkGeometryFlagsKHR m_geometryFlags; +}; + +template +inline T convertSatRte (float f) +{ + // \note Doesn't work for 64-bit types + DE_STATIC_ASSERT(sizeof(T) < sizeof(deUint64)); + DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0)); + + deInt64 minVal = std::numeric_limits::min(); + deInt64 maxVal = std::numeric_limits::max(); + float q = deFloatFrac(f); + deInt64 intVal = (deInt64)(f-q); + + // Rounding. + if (q == 0.5f) + { + if (intVal % 2 != 0) + intVal++; + } + else if (q > 0.5f) + intVal++; + // else Don't add anything + + // Saturate. + intVal = de::max(minVal, de::min(maxVal, intVal)); + + return (T)intVal; +} + +inline deInt16 deFloat32ToSNorm16 (float src) +{ + const deInt16 range = (deInt32)((1u << 15) - 1u); + const deInt16 intVal = convertSatRte(src * (float)range); + return de::clamp(intVal, -range, range); +} + +typedef tcu::Vector Vec2_16; +typedef tcu::Vector Vec4_16; +typedef tcu::Vector Vec2_16SNorm; +typedef tcu::Vector Vec4_16SNorm; + +template VkFormat vertexFormatFromType () { TCU_THROW(TestError, "Unknown VkFormat"); } +template<> inline VkFormat vertexFormatFromType () { return VK_FORMAT_R32G32_SFLOAT; } +template<> inline VkFormat vertexFormatFromType () { return VK_FORMAT_R32G32B32_SFLOAT; } +template<> inline VkFormat vertexFormatFromType () { return VK_FORMAT_R16G16_SFLOAT; } +template<> inline VkFormat vertexFormatFromType () { return VK_FORMAT_R16G16B16A16_SFLOAT; } +template<> inline VkFormat vertexFormatFromType () { return VK_FORMAT_R16G16_SNORM; } +template<> inline VkFormat vertexFormatFromType () { return VK_FORMAT_R16G16B16A16_SNORM; } + +struct EmptyIndex {}; +template VkIndexType indexTypeFromType () { TCU_THROW(TestError, "Unknown VkIndexType"); } +template<> inline VkIndexType indexTypeFromType () { return VK_INDEX_TYPE_UINT16; } +template<> inline VkIndexType indexTypeFromType () { return VK_INDEX_TYPE_UINT32; } +template<> inline VkIndexType indexTypeFromType () { return VK_INDEX_TYPE_NONE_KHR; } + +template V convertFloatTo (const tcu::Vec3& vertex) { DE_UNREF(vertex); TCU_THROW(TestError, "Unknown data format"); } +template<> inline tcu::Vec2 convertFloatTo (const tcu::Vec3& vertex) { return tcu::Vec2(vertex.x(), vertex.y()); } +template<> inline tcu::Vec3 convertFloatTo (const tcu::Vec3& vertex) { return vertex; } +template<> inline Vec2_16 convertFloatTo (const tcu::Vec3& vertex) { return Vec2_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y())); } +template<> inline Vec4_16 convertFloatTo (const tcu::Vec3& vertex) { return Vec4_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y()), deFloat32To16(vertex.z()), deFloat32To16(0.0f)); } +template<> inline Vec2_16SNorm convertFloatTo (const tcu::Vec3& vertex) { return Vec2_16SNorm(deFloat32ToSNorm16(vertex.x()), deFloat32ToSNorm16(vertex.y())); } +template<> inline Vec4_16SNorm convertFloatTo (const tcu::Vec3& vertex) { return Vec4_16SNorm(deFloat32ToSNorm16(vertex.x()), deFloat32ToSNorm16(vertex.y()), deFloat32ToSNorm16(vertex.z()), deFloat32ToSNorm16(0.0f)); } + +template V convertIndexTo (deUint32 index) { DE_UNREF(index); TCU_THROW(TestError, "Unknown index format"); } +template<> inline EmptyIndex convertIndexTo (deUint32 index) { DE_UNREF(index); TCU_THROW(TestError, "Cannot add empty index"); } +template<> inline deUint16 convertIndexTo (deUint32 index) { return static_cast(index); } +template<> inline deUint32 convertIndexTo (deUint32 index) { return index; } + +template +class RaytracedGeometry : public RaytracedGeometryBase +{ +public: + RaytracedGeometry () = delete; + RaytracedGeometry (const RaytracedGeometry& geometry) = delete; + RaytracedGeometry (VkGeometryTypeKHR geometryType); + RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector& vertices, const std::vector& indices = std::vector()); + + deUint32 getVertexCount (void) const override; + const deUint8* getVertexPointer (void) const override; + VkDeviceSize getVertexStride (void) const override; + size_t getVertexByteSize (void) const override; + VkDeviceSize getAABBStride (void) const override; + deUint32 getIndexCount (void) const override; + const deUint8* getIndexPointer (void) const override; + VkDeviceSize getIndexStride (void) const override; + size_t getIndexByteSize (void) const override; + deUint32 getPrimitiveCount (void) const override; + + void addVertex (const tcu::Vec3& vertex) override; + void addIndex (const deUint32& index) override; +private: + std::vector m_vertices; + std::vector m_indices; +}; + +template +RaytracedGeometry::RaytracedGeometry (VkGeometryTypeKHR geometryType) + : RaytracedGeometryBase(geometryType, vertexFormatFromType(), indexTypeFromType()) +{ +} + +template +RaytracedGeometry::RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector& vertices, const std::vector& indices) + : RaytracedGeometryBase(geometryType, vertexFormatFromType(), indexTypeFromType()) + , m_vertices(vertices) + , m_indices(indices) +{ +} + +template +deUint32 RaytracedGeometry::getVertexCount (void) const +{ + return static_cast( isTrianglesType() ? m_vertices.size() : 0); +} + +template +const deUint8* RaytracedGeometry::getVertexPointer (void) const +{ + return reinterpret_cast(m_vertices.empty() ? DE_NULL : m_vertices.data()); +} + +template +VkDeviceSize RaytracedGeometry::getVertexStride (void) const +{ + return static_cast(sizeof(V)); +} + +template +VkDeviceSize RaytracedGeometry::getAABBStride (void) const +{ + return static_cast(2 * sizeof(V)); +} + +template +size_t RaytracedGeometry::getVertexByteSize (void) const +{ + return static_cast(m_vertices.size() * sizeof(V)); +} + +template +deUint32 RaytracedGeometry::getIndexCount (void) const +{ + return static_cast(isTrianglesType() ? m_indices.size() : 0); +} + +template +const deUint8* RaytracedGeometry::getIndexPointer (void) const +{ + return reinterpret_cast(m_indices.empty() ? DE_NULL : m_indices.data()); +} + +template +VkDeviceSize RaytracedGeometry::getIndexStride (void) const +{ + return static_cast(sizeof(I)); +} + +template +size_t RaytracedGeometry::getIndexByteSize (void) const +{ + return static_cast(m_indices.size() * sizeof(I)); +} + +template +deUint32 RaytracedGeometry::getPrimitiveCount (void) const +{ + return static_cast(isTrianglesType() ? (usesIndices() ? m_indices.size() / 3 : m_vertices.size() / 3) : (m_vertices.size() / 2)); +} + +template +void RaytracedGeometry::addVertex (const tcu::Vec3& vertex) +{ + m_vertices.push_back(convertFloatTo(vertex)); +} + +template +void RaytracedGeometry::addIndex (const deUint32& index) +{ + m_indices.push_back(convertIndexTo(index)); +} + +de::SharedPtr makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType); + +class SerialStorage +{ +public: + SerialStorage () = delete; + SerialStorage (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + const VkAccelerationStructureBuildTypeKHR buildType, + const VkDeviceSize storageSize); + + VkDeviceOrHostAddressKHR getAddress (const DeviceInterface& vk, + const VkDevice device); + VkDeviceOrHostAddressConstKHR getAddressConst (const DeviceInterface& vk, + const VkDevice device); +protected: + VkAccelerationStructureBuildTypeKHR m_buildType; + de::MovePtr m_buffer; + +}; + +class BottomLevelAccelerationStructure +{ +public: + static deUint32 getRequiredAllocationCount (void); + + BottomLevelAccelerationStructure (); + BottomLevelAccelerationStructure (const BottomLevelAccelerationStructure& other) = delete; + virtual ~BottomLevelAccelerationStructure (); + + virtual void setGeometryData (const std::vector& geometryData, + const bool triangles, + const VkGeometryFlagsKHR geometryFlags = 0); + virtual void setDefaultGeometryData (const VkShaderStageFlagBits testStage); + virtual void setGeometryCount (const size_t geometryCount); + virtual void addGeometry (de::SharedPtr& raytracedGeometry); + virtual void addGeometry (const std::vector& geometryData, + const bool triangles, + const VkGeometryFlagsKHR geometryFlags = 0); + + virtual void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) = DE_NULL; + virtual void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR flags) = DE_NULL; + virtual void setDeferredOperation (const bool deferredOperation) = DE_NULL; + virtual void setUseArrayOfPointers (const bool useArrayOfPointers) = DE_NULL; + virtual void setIndirectBuildParameters (const VkBuffer indirectBuffer, + const VkDeviceSize indirectBufferOffset, + const deUint32 indirectBufferStride) = DE_NULL; + virtual VkBuildAccelerationStructureFlagsKHR getBuildFlags () const = DE_NULL; + + // methods specific for each acceleration structure + virtual void create (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + VkDeviceAddress deviceAddress, + VkDeviceSize compactCopySize) = DE_NULL; + virtual void build (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer) = DE_NULL; + virtual void copyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + BottomLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) = DE_NULL; + + virtual void serialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) = DE_NULL; + virtual void deserialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) = DE_NULL; + + // helper methods for typical acceleration structure creation tasks + void createAndBuild (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress = 0u ); + void createAndCopyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress = 0u, + BottomLevelAccelerationStructure* accelerationStructure = DE_NULL, + VkDeviceSize compactCopySize = 0u); + void createAndDeserializeFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress = 0u, + SerialStorage* storage = DE_NULL); + + virtual const VkAccelerationStructureKHR* getPtr (void) const = DE_NULL; +protected: + std::vector> m_geometriesData; +}; + +de::MovePtr makeBottomLevelAccelerationStructure (); + +struct InstanceData +{ + InstanceData (VkTransformMatrixKHR matrix_, + deUint32 instanceCustomIndex_, + deUint32 mask_, + deUint32 instanceShaderBindingTableRecordOffset_, + VkGeometryInstanceFlagsKHR flags_) + : matrix(matrix_), instanceCustomIndex(instanceCustomIndex_), mask(mask_), instanceShaderBindingTableRecordOffset(instanceShaderBindingTableRecordOffset_), flags(flags_) + { + } + VkTransformMatrixKHR matrix; + deUint32 instanceCustomIndex; + deUint32 mask; + deUint32 instanceShaderBindingTableRecordOffset; + VkGeometryInstanceFlagsKHR flags; +}; + +class TopLevelAccelerationStructure +{ +public: + static deUint32 getRequiredAllocationCount (void); + + TopLevelAccelerationStructure (); + TopLevelAccelerationStructure (const TopLevelAccelerationStructure& other) = delete; + virtual ~TopLevelAccelerationStructure (); + + virtual void setInstanceCount (const size_t instanceCount); + virtual void addInstance (de::SharedPtr bottomLevelStructure, + const VkTransformMatrixKHR& matrix = identityMatrix3x4, + deUint32 instanceCustomIndex = 0, + deUint32 mask = 0xFF, + deUint32 instanceShaderBindingTableRecordOffset = 0, + VkGeometryInstanceFlagsKHR flags = VkGeometryInstanceFlagBitsKHR(0u) ); + + virtual void setBuildType (const VkAccelerationStructureBuildTypeKHR buildType) = DE_NULL; + virtual void setBuildFlags (const VkBuildAccelerationStructureFlagsKHR flags) = DE_NULL; + virtual void setDeferredOperation (const bool deferredOperation) = DE_NULL; + virtual void setUseArrayOfPointers (const bool useArrayOfPointers) = DE_NULL; + virtual void setIndirectBuildParameters (const VkBuffer indirectBuffer, + const VkDeviceSize indirectBufferOffset, + const deUint32 indirectBufferStride) = DE_NULL; + virtual VkBuildAccelerationStructureFlagsKHR getBuildFlags () const = DE_NULL; + + // methods specific for each acceleration structure + virtual void create (const DeviceInterface& vk, + const VkDevice device, + Allocator& allocator, + VkDeviceAddress deviceAddress, + VkDeviceSize compactCopySize) = DE_NULL; + virtual void build (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer) = DE_NULL; + virtual void copyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + TopLevelAccelerationStructure* accelerationStructure, + VkDeviceSize compactCopySize) = DE_NULL; + + virtual void serialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) = DE_NULL; + virtual void deserialize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + SerialStorage* storage) = DE_NULL; + + // helper methods for typical acceleration structure creation tasks + void createAndBuild (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress = 0u ); + void createAndCopyFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress = 0u, + TopLevelAccelerationStructure* accelerationStructure = DE_NULL, + VkDeviceSize compactCopySize = 0u); + void createAndDeserializeFrom (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + Allocator& allocator, + VkDeviceAddress deviceAddress = 0u, + SerialStorage* storage = DE_NULL); + + virtual const VkAccelerationStructureKHR* getPtr (void) const = DE_NULL; + +protected: + std::vector > m_bottomLevelInstances; + std::vector m_instanceData; +}; + +de::MovePtr makeTopLevelAccelerationStructure (); + +bool queryAccelerationStructureSize (const DeviceInterface& vk, + const VkDevice device, + const VkCommandBuffer cmdBuffer, + const std::vector& accelerationStructureHandles, + VkAccelerationStructureBuildTypeKHR buildType, + const VkQueryPool queryPool, + VkQueryType queryType, + deUint32 firstQuery, + std::vector& results); + +class RayTracingPipeline +{ +public: + RayTracingPipeline (); + ~RayTracingPipeline (); + + void addShader (VkShaderStageFlagBits shaderStage, + Move shaderModule, + deUint32 group); + void addLibrary (de::SharedPtr> pipelineLibrary); + Move createPipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const std::vector>>& pipelineLibraries = std::vector>>()); + std::vector>> createPipelineWithLibraries (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout); + de::MovePtr createShaderBindingTable (const DeviceInterface& vk, + const VkDevice device, + const VkPipeline pipeline, + Allocator& allocator, + const deUint32& shaderGroupHandleSize, + const deUint32 shaderGroupBaseAlignment, + const deUint32& firstGroup, + const deUint32& groupCount, + const VkBufferCreateFlags& additionalBufferCreateFlags = VkBufferCreateFlags(0u), + const VkBufferUsageFlags& additionalBufferUsageFlags = VkBufferUsageFlags(0u), + const MemoryRequirement& additionalMemoryRequirement = MemoryRequirement::Any, + const VkDeviceAddress& opaqueCaptureAddress = 0u, + const deUint32 shaderBindingTableOffset = 0u, + const deUint32 shaderRecordSize = 0u); + void setCreateFlags (const VkPipelineCreateFlags& pipelineCreateFlags); + void setMaxRecursionDepth (const deUint32& maxRecursionDepth); + void setMaxPayloadSize (const deUint32& maxPayloadSize); + void setMaxAttributeSize (const deUint32& maxAttributeSize); + void setMaxCallableSize (const deUint32& maxCallableSize); + void setDeferredOperation (const bool deferredOperation); + +protected: + Move createPipelineKHR (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const std::vector>>& pipelineLibraries); + + std::vector > > m_shadersModules; + std::vector>> m_pipelineLibraries; + std::vector m_shaderCreateInfos; + std::vector m_shadersGroupCreateInfos; + VkPipelineCreateFlags m_pipelineCreateFlags; + deUint32 m_maxRecursionDepth; + deUint32 m_maxPayloadSize; + deUint32 m_maxAttributeSize; + deUint32 m_maxCallableSize; + bool m_deferredOperation; +}; + +class RayTracingProperties +{ +protected: + RayTracingProperties () {}; + +public: + RayTracingProperties (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice) { DE_UNREF(vki); DE_UNREF(physicalDevice); }; + virtual ~RayTracingProperties () {}; + + virtual deUint32 getShaderGroupHandleSize (void) = DE_NULL; + virtual deUint32 getMaxRecursionDepth (void) = DE_NULL; + virtual deUint32 getMaxShaderGroupStride (void) = DE_NULL; + virtual deUint32 getShaderGroupBaseAlignment (void) = DE_NULL; + virtual deUint64 getMaxGeometryCount (void) = DE_NULL; + virtual deUint64 getMaxInstanceCount (void) = DE_NULL; + virtual deUint64 getMaxPrimitiveCount (void) = DE_NULL; + virtual deUint32 getMaxDescriptorSetAccelerationStructures (void) = DE_NULL; +}; + +de::MovePtr makeRayTracingProperties (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice); + +void cmdTraceRays (const DeviceInterface& vk, + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* raygenShaderBindingTableRegion, + const VkStridedBufferRegionKHR* missShaderBindingTableRegion, + const VkStridedBufferRegionKHR* hitShaderBindingTableRegion, + const VkStridedBufferRegionKHR* callableShaderBindingTableRegion, + deUint32 width, + deUint32 height, + deUint32 depth); + +void cmdTraceRaysIndirect (const DeviceInterface& vk, + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* raygenShaderBindingTableRegion, + const VkStridedBufferRegionKHR* missShaderBindingTableRegion, + const VkStridedBufferRegionKHR* hitShaderBindingTableRegion, + const VkStridedBufferRegionKHR* callableShaderBindingTableRegion, + VkBuffer buffer, + VkDeviceSize offset); +} // vk + +#endif // _VKRAYTRACINGUTIL_HPP diff --git a/external/vulkancts/framework/vulkan/vkRefUtil.cpp b/external/vulkancts/framework/vulkan/vkRefUtil.cpp index dbe70d5..6551cbb 100644 --- a/external/vulkancts/framework/vulkan/vkRefUtil.cpp +++ b/external/vulkancts/framework/vulkan/vkRefUtil.cpp @@ -50,17 +50,28 @@ Move createComputePipeline (const DeviceInterface& vk, return Move(check(object), Deleter(vk, device, pAllocator)); } -Move createRayTracingPipelineNV (const DeviceInterface& vk, - VkDevice device, - VkPipelineCache pipelineCache, - const VkRayTracingPipelineCreateInfoNV* pCreateInfo, - const VkAllocationCallbacks* pAllocator) +Move createRayTracingPipelineNV (const DeviceInterface& vk, + VkDevice device, + VkPipelineCache pipelineCache, + const VkRayTracingPipelineCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator) { VkPipeline object = 0; VK_CHECK(vk.createRayTracingPipelinesNV(device, pipelineCache, 1u, pCreateInfo, pAllocator, &object)); return Move(check(object), Deleter(vk, device, pAllocator)); } +Move createRayTracingPipelineKHR (const DeviceInterface& vk, + VkDevice device, + VkPipelineCache pipelineCache, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator) +{ + VkPipeline object = 0; + VK_CHECK(vk.createRayTracingPipelinesKHR(device, pipelineCache, 1u, pCreateInfo, pAllocator, &object)); + return Move(check(object), Deleter(vk, device, pAllocator)); +} + Move allocateCommandBuffer (const DeviceInterface& vk, VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo) { VkCommandBuffer object = 0; diff --git a/external/vulkancts/framework/vulkan/vkRefUtil.hpp b/external/vulkancts/framework/vulkan/vkRefUtil.hpp index a966b20..7032842 100644 --- a/external/vulkancts/framework/vulkan/vkRefUtil.hpp +++ b/external/vulkancts/framework/vulkan/vkRefUtil.hpp @@ -46,6 +46,11 @@ Move createRayTracingPipelineNV(const DeviceInterface& vk, VkPipelineCache pipelineCache, const VkRayTracingPipelineCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator = DE_NULL); +Move createRayTracingPipelineKHR (const DeviceInterface& vk, + VkDevice device, + VkPipelineCache pipelineCache, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator = DE_NULL); Move allocateCommandBuffer (const DeviceInterface& vk, VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo); Move allocateDescriptorSet (const DeviceInterface& vk, VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo); diff --git a/external/vulkancts/framework/vulkan/vkShaderToSpirV.cpp b/external/vulkancts/framework/vulkan/vkShaderToSpirV.cpp index 9916c59..031b69b 100644 --- a/external/vulkancts/framework/vulkan/vkShaderToSpirV.cpp +++ b/external/vulkancts/framework/vulkan/vkShaderToSpirV.cpp @@ -56,12 +56,12 @@ EShLanguage getGlslangStage (glu::ShaderType type) EShLangTessControl, EShLangTessEvaluation, EShLangCompute, - EShLangRayGenNV, - EShLangAnyHitNV, - EShLangClosestHitNV, - EShLangMissNV, - EShLangIntersectNV, - EShLangCallableNV, + EShLangRayGen, + EShLangAnyHit, + EShLangClosestHit, + EShLangMiss, + EShLangIntersect, + EShLangCallable, }; return de::getSizedArrayElement(stageMap, type); }