--- /dev/null
+/*-------------------------------------------------------------------------
+ * 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 <vector>
+#include <string>
+#include <thread>
+
+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<RaytracedGeometryBase> makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType)
+{
+ switch (vertexFormat)
+ {
+ case VK_FORMAT_R32G32_SFLOAT:
+ switch (indexType)
+ {
+ case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<tcu::Vec2, deUint16>(geometryType));
+ case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<tcu::Vec2, deUint32>(geometryType));
+ case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<tcu::Vec2, EmptyIndex>(geometryType));
+ default: TCU_THROW(InternalError, "Wrong index type");
+ };
+ case VK_FORMAT_R32G32B32_SFLOAT:
+ switch (indexType)
+ {
+ case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<tcu::Vec3, deUint16>(geometryType));
+ case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<tcu::Vec3, deUint32>(geometryType));
+ case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<tcu::Vec3, EmptyIndex>(geometryType));
+ default: TCU_THROW(InternalError, "Wrong index type");
+ };
+ case VK_FORMAT_R16G16_SFLOAT:
+ switch (indexType)
+ {
+ case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec2_16, deUint16>(geometryType));
+ case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec2_16, deUint32>(geometryType));
+ case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec2_16, EmptyIndex>(geometryType));
+ default: TCU_THROW(InternalError, "Wrong index type");
+ };
+ case VK_FORMAT_R16G16B16A16_SFLOAT:
+ switch (indexType)
+ {
+ case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec4_16, deUint16>(geometryType));
+ case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec4_16, deUint32>(geometryType));
+ case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec4_16, EmptyIndex>(geometryType));
+ default: TCU_THROW(InternalError, "Wrong index type");
+ };
+ case VK_FORMAT_R16G16_SNORM:
+ switch (indexType)
+ {
+ case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec2_16SNorm, deUint16>(geometryType));
+ case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec2_16SNorm, deUint32>(geometryType));
+ case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec2_16SNorm, EmptyIndex>(geometryType));
+ default: TCU_THROW(InternalError, "Wrong index type");
+ };
+ case VK_FORMAT_R16G16B16A16_SNORM:
+ switch (indexType)
+ {
+ case VK_INDEX_TYPE_UINT16: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec4_16SNorm, deUint16>(geometryType));
+ case VK_INDEX_TYPE_UINT32: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec4_16SNorm, deUint32>(geometryType));
+ case VK_INDEX_TYPE_NONE_KHR: return de::SharedPtr<RaytracedGeometryBase>(new RaytracedGeometry<Vec4_16SNorm, EmptyIndex>(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<BufferWithMemory>(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<tcu::Vec3>& 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<tcu::Vec3> 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<RaytracedGeometryBase>& raytracedGeometry)
+{
+ m_geometriesData.push_back(raytracedGeometry);
+}
+
+void BottomLevelAccelerationStructure::addGeometry (const std::vector<tcu::Vec3>& 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<RaytracedGeometryBase> 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<de::SharedPtr<RaytracedGeometryBase>>& 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<de::SharedPtr<RaytracedGeometryBase>>& geometriesData,
+ BufferWithMemory* vertexBuffer)
+{
+ const Allocation& geometryAlloc = vertexBuffer->getAllocation();
+ deUint8* bufferStart = static_cast<deUint8*>(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<de::SharedPtr<RaytracedGeometryBase>>& 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<de::SharedPtr<RaytracedGeometryBase>>& geometriesData,
+ BufferWithMemory* indexBuffer)
+{
+ const Allocation& indexAlloc = indexBuffer->getAllocation();
+ deUint8* bufferStart = static_cast<deUint8*>(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<BufferWithMemory> m_vertexBuffer;
+ de::MovePtr<BufferWithMemory> m_indexBuffer;
+ de::MovePtr<Allocation> m_accelerationStructureAlloc;
+ de::MovePtr<BufferWithMemory> m_scratchBuffer;
+ Move<VkAccelerationStructureKHR> m_accelerationStructureKHR;
+ VkBuffer m_indirectBuffer;
+ VkDeviceSize m_indirectBufferOffset;
+ deUint32 m_indirectBufferStride;
+};
+
+deUint32 BottomLevelAccelerationStructureKHR::getRequiredAllocationCount (void)
+{
+ /*
+ de::MovePtr<BufferWithMemory> m_geometryBuffer; // but only when m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR
+ de::MovePtr<Allocation> m_accelerationStructureAlloc;
+ de::MovePtr<BufferWithMemory> 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<VkAccelerationStructureCreateGeometryTypeInfoKHR> accelerationStructureCreateGeometryTypeInfosKHR(m_geometriesData.size());
+
+ for (size_t geometryNdx = 0; geometryNdx < m_geometriesData.size(); ++geometryNdx)
+ {
+ de::SharedPtr<RaytracedGeometryBase>& 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<deUint32>(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<BufferWithMemory>(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<BufferWithMemory>(createVertexBuffer(vk, device, allocator, m_geometriesData));
+ m_indexBuffer = de::MovePtr<BufferWithMemory>(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<VkAccelerationStructureGeometryKHR> accelerationStructureGeometriesKHR (m_geometriesData.size());
+ std::vector<VkAccelerationStructureGeometryKHR*> accelerationStructureGeometriesKHRPointers (m_geometriesData.size());
+ std::vector<VkAccelerationStructureBuildOffsetInfoKHR> accelerationStructureBuildOffsetInfoKHR (m_geometriesData.size());
+ VkDeviceSize vertexBufferOffset = 0, indexBufferOffset = 0;
+
+ for (size_t geometryNdx = 0; geometryNdx < m_geometriesData.size(); ++geometryNdx)
+ {
+ de::SharedPtr<RaytracedGeometryBase>& 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<deUint32>(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<BottomLevelAccelerationStructure> makeBottomLevelAccelerationStructure ()
+{
+ return de::MovePtr<BottomLevelAccelerationStructure>(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<BottomLevelAccelerationStructure> 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<de::SharedPtr<BottomLevelAccelerationStructure> > bottomLevelInstances,
+ std::vector<InstanceData> 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<de::SharedPtr<BottomLevelAccelerationStructure> > bottomLevelInstances,
+ std::vector<InstanceData> 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<deUint8*>(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<BufferWithMemory> m_instanceBuffer;
+ de::MovePtr<BufferWithMemory> m_instanceAddressBuffer;
+ de::MovePtr<Allocation> m_accelerationStructureAlloc;
+ de::MovePtr<BufferWithMemory> m_scratchBuffer;
+ Move<VkAccelerationStructureKHR> m_accelerationStructureKHR;
+ VkBuffer m_indirectBuffer;
+ VkDeviceSize m_indirectBufferOffset;
+ deUint32 m_indirectBufferStride;
+};
+
+deUint32 TopLevelAccelerationStructureKHR::getRequiredAllocationCount (void)
+{
+ /*
+ de::MovePtr<BufferWithMemory> m_instanceBuffer;
+ de::MovePtr<Allocation> m_accelerationStructureAlloc;
+ de::MovePtr<BufferWithMemory> 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<deUint32>(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<BufferWithMemory>(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<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
+ }
+
+ if(!m_bottomLevelInstances.empty())
+ m_instanceBuffer = de::MovePtr<BufferWithMemory>(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<deUint8*>(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<deUint8*>(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<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ()
+{
+ return de::MovePtr<TopLevelAccelerationStructure>(new TopLevelAccelerationStructureKHR);
+}
+
+bool queryAccelerationStructureSizeKHR (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkCommandBuffer cmdBuffer,
+ const std::vector<VkAccelerationStructureKHR>& accelerationStructureHandles,
+ VkAccelerationStructureBuildTypeKHR buildType,
+ const VkQueryPool queryPool,
+ VkQueryType queryType,
+ deUint32 firstQuery,
+ std::vector<VkDeviceSize>& 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<VkAccelerationStructureKHR>& accelerationStructureHandles,
+ VkAccelerationStructureBuildTypeKHR buildType,
+ const VkQueryPool queryPool,
+ VkQueryType queryType,
+ deUint32 firstQuery,
+ std::vector<VkDeviceSize>& 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<VkShaderModule> 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<de::MovePtr<RayTracingPipeline>> pipelineLibrary)
+{
+ m_pipelineLibraries.push_back(pipelineLibrary);
+}
+
+Move<VkPipeline> RayTracingPipeline::createPipelineKHR (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout,
+ const std::vector<de::SharedPtr<Move<VkPipeline>>>& 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<VkPipeline> 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<VkDeferredOperationKHR> deferredOperation = (m_deferredOperation ? createDeferredOperationKHR(vk, device) : Move<VkDeferredOperationKHR>());
+ 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<VkPipeline> pipeline (check<VkPipeline>(object), Deleter<VkPipeline>(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<VkPipeline> RayTracingPipeline::createPipeline (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout,
+ const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries)
+{
+ return createPipelineKHR(vk, device, pipelineLayout, pipelineLibraries);
+}
+
+std::vector<de::SharedPtr<Move<VkPipeline>>> 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<de::SharedPtr<Move<VkPipeline>>> 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<BufferWithMemory> 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<BufferWithMemory> sbtBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, sbtCreateInfo, sbtMemRequirements));
+ vk::Allocation& sbtAlloc = sbtBuffer->getAllocation();
+
+ // collect shader group handles
+ std::vector<deUint8> 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<RayTracingProperties> makeRayTracingProperties (const InstanceInterface& vki,
+ const VkPhysicalDevice physicalDevice)
+{
+ return de::MovePtr<RayTracingProperties>(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
--- /dev/null
+#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 <vector>
+
+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<typename T>
+inline de::SharedPtr<Move<T>> makeVkSharedPtr(Move<T> move)
+{
+ return de::SharedPtr<Move<T>>(new Move<T>(move));
+}
+
+template<typename T>
+inline de::SharedPtr<de::MovePtr<T> > makeVkSharedPtr(de::MovePtr<T> movePtr)
+{
+ return de::SharedPtr<de::MovePtr<T> >(new de::MovePtr<T>(movePtr));
+}
+
+template<typename T>
+inline const T* dataOrNullPtr(const std::vector<T>& v)
+{
+ return (v.empty() ? DE_NULL : v.data());
+}
+
+template<typename T>
+inline T* dataOrNullPtr(std::vector<T>& 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 <typename T>
+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<T>::min();
+ deInt64 maxVal = std::numeric_limits<T>::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<deInt16>(src * (float)range);
+ return de::clamp<deInt16>(intVal, -range, range);
+}
+
+typedef tcu::Vector<deFloat16, 2> Vec2_16;
+typedef tcu::Vector<deFloat16, 4> Vec4_16;
+typedef tcu::Vector<deInt16, 2> Vec2_16SNorm;
+typedef tcu::Vector<deInt16, 4> Vec4_16SNorm;
+
+template<typename V> VkFormat vertexFormatFromType () { TCU_THROW(TestError, "Unknown VkFormat"); }
+template<> inline VkFormat vertexFormatFromType<tcu::Vec2> () { return VK_FORMAT_R32G32_SFLOAT; }
+template<> inline VkFormat vertexFormatFromType<tcu::Vec3> () { return VK_FORMAT_R32G32B32_SFLOAT; }
+template<> inline VkFormat vertexFormatFromType<Vec2_16> () { return VK_FORMAT_R16G16_SFLOAT; }
+template<> inline VkFormat vertexFormatFromType<Vec4_16> () { return VK_FORMAT_R16G16B16A16_SFLOAT; }
+template<> inline VkFormat vertexFormatFromType<Vec2_16SNorm> () { return VK_FORMAT_R16G16_SNORM; }
+template<> inline VkFormat vertexFormatFromType<Vec4_16SNorm> () { return VK_FORMAT_R16G16B16A16_SNORM; }
+
+struct EmptyIndex {};
+template<typename I> VkIndexType indexTypeFromType () { TCU_THROW(TestError, "Unknown VkIndexType"); }
+template<> inline VkIndexType indexTypeFromType<deUint16> () { return VK_INDEX_TYPE_UINT16; }
+template<> inline VkIndexType indexTypeFromType<deUint32> () { return VK_INDEX_TYPE_UINT32; }
+template<> inline VkIndexType indexTypeFromType<EmptyIndex> () { return VK_INDEX_TYPE_NONE_KHR; }
+
+template<typename V> V convertFloatTo (const tcu::Vec3& vertex) { DE_UNREF(vertex); TCU_THROW(TestError, "Unknown data format"); }
+template<> inline tcu::Vec2 convertFloatTo<tcu::Vec2> (const tcu::Vec3& vertex) { return tcu::Vec2(vertex.x(), vertex.y()); }
+template<> inline tcu::Vec3 convertFloatTo<tcu::Vec3> (const tcu::Vec3& vertex) { return vertex; }
+template<> inline Vec2_16 convertFloatTo<Vec2_16> (const tcu::Vec3& vertex) { return Vec2_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y())); }
+template<> inline Vec4_16 convertFloatTo<Vec4_16> (const tcu::Vec3& vertex) { return Vec4_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y()), deFloat32To16(vertex.z()), deFloat32To16(0.0f)); }
+template<> inline Vec2_16SNorm convertFloatTo<Vec2_16SNorm> (const tcu::Vec3& vertex) { return Vec2_16SNorm(deFloat32ToSNorm16(vertex.x()), deFloat32ToSNorm16(vertex.y())); }
+template<> inline Vec4_16SNorm convertFloatTo<Vec4_16SNorm> (const tcu::Vec3& vertex) { return Vec4_16SNorm(deFloat32ToSNorm16(vertex.x()), deFloat32ToSNorm16(vertex.y()), deFloat32ToSNorm16(vertex.z()), deFloat32ToSNorm16(0.0f)); }
+
+template<typename V> V convertIndexTo (deUint32 index) { DE_UNREF(index); TCU_THROW(TestError, "Unknown index format"); }
+template<> inline EmptyIndex convertIndexTo<EmptyIndex> (deUint32 index) { DE_UNREF(index); TCU_THROW(TestError, "Cannot add empty index"); }
+template<> inline deUint16 convertIndexTo<deUint16> (deUint32 index) { return static_cast<deUint16>(index); }
+template<> inline deUint32 convertIndexTo<deUint32> (deUint32 index) { return index; }
+
+template<typename V, typename I>
+class RaytracedGeometry : public RaytracedGeometryBase
+{
+public:
+ RaytracedGeometry () = delete;
+ RaytracedGeometry (const RaytracedGeometry& geometry) = delete;
+ RaytracedGeometry (VkGeometryTypeKHR geometryType);
+ RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices = std::vector<I>());
+
+ 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<V> m_vertices;
+ std::vector<I> m_indices;
+};
+
+template<typename V, typename I>
+RaytracedGeometry<V, I>::RaytracedGeometry (VkGeometryTypeKHR geometryType)
+ : RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
+{
+}
+
+template<typename V, typename I>
+RaytracedGeometry<V,I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices)
+ : RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
+ , m_vertices(vertices)
+ , m_indices(indices)
+{
+}
+
+template<typename V, typename I>
+deUint32 RaytracedGeometry<V,I>::getVertexCount (void) const
+{
+ return static_cast<deUint32>( isTrianglesType() ? m_vertices.size() : 0);
+}
+
+template<typename V, typename I>
+const deUint8* RaytracedGeometry<V, I>::getVertexPointer (void) const
+{
+ return reinterpret_cast<const deUint8*>(m_vertices.empty() ? DE_NULL : m_vertices.data());
+}
+
+template<typename V, typename I>
+VkDeviceSize RaytracedGeometry<V,I>::getVertexStride (void) const
+{
+ return static_cast<VkDeviceSize>(sizeof(V));
+}
+
+template<typename V, typename I>
+VkDeviceSize RaytracedGeometry<V, I>::getAABBStride (void) const
+{
+ return static_cast<VkDeviceSize>(2 * sizeof(V));
+}
+
+template<typename V, typename I>
+size_t RaytracedGeometry<V, I>::getVertexByteSize (void) const
+{
+ return static_cast<size_t>(m_vertices.size() * sizeof(V));
+}
+
+template<typename V, typename I>
+deUint32 RaytracedGeometry<V, I>::getIndexCount (void) const
+{
+ return static_cast<deUint32>(isTrianglesType() ? m_indices.size() : 0);
+}
+
+template<typename V, typename I>
+const deUint8* RaytracedGeometry<V, I>::getIndexPointer (void) const
+{
+ return reinterpret_cast<const deUint8*>(m_indices.empty() ? DE_NULL : m_indices.data());
+}
+
+template<typename V, typename I>
+VkDeviceSize RaytracedGeometry<V, I>::getIndexStride (void) const
+{
+ return static_cast<VkDeviceSize>(sizeof(I));
+}
+
+template<typename V, typename I>
+size_t RaytracedGeometry<V, I>::getIndexByteSize (void) const
+{
+ return static_cast<size_t>(m_indices.size() * sizeof(I));
+}
+
+template<typename V, typename I>
+deUint32 RaytracedGeometry<V,I>::getPrimitiveCount (void) const
+{
+ return static_cast<deUint32>(isTrianglesType() ? (usesIndices() ? m_indices.size() / 3 : m_vertices.size() / 3) : (m_vertices.size() / 2));
+}
+
+template<typename V, typename I>
+void RaytracedGeometry<V, I>::addVertex (const tcu::Vec3& vertex)
+{
+ m_vertices.push_back(convertFloatTo<V>(vertex));
+}
+
+template<typename V, typename I>
+void RaytracedGeometry<V, I>::addIndex (const deUint32& index)
+{
+ m_indices.push_back(convertIndexTo<I>(index));
+}
+
+de::SharedPtr<RaytracedGeometryBase> 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<BufferWithMemory> m_buffer;
+
+};
+
+class BottomLevelAccelerationStructure
+{
+public:
+ static deUint32 getRequiredAllocationCount (void);
+
+ BottomLevelAccelerationStructure ();
+ BottomLevelAccelerationStructure (const BottomLevelAccelerationStructure& other) = delete;
+ virtual ~BottomLevelAccelerationStructure ();
+
+ virtual void setGeometryData (const std::vector<tcu::Vec3>& 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<RaytracedGeometryBase>& raytracedGeometry);
+ virtual void addGeometry (const std::vector<tcu::Vec3>& 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<de::SharedPtr<RaytracedGeometryBase>> m_geometriesData;
+};
+
+de::MovePtr<BottomLevelAccelerationStructure> 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<BottomLevelAccelerationStructure> 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<de::SharedPtr<BottomLevelAccelerationStructure> > m_bottomLevelInstances;
+ std::vector<InstanceData> m_instanceData;
+};
+
+de::MovePtr<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ();
+
+bool queryAccelerationStructureSize (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkCommandBuffer cmdBuffer,
+ const std::vector<VkAccelerationStructureKHR>& accelerationStructureHandles,
+ VkAccelerationStructureBuildTypeKHR buildType,
+ const VkQueryPool queryPool,
+ VkQueryType queryType,
+ deUint32 firstQuery,
+ std::vector<VkDeviceSize>& results);
+
+class RayTracingPipeline
+{
+public:
+ RayTracingPipeline ();
+ ~RayTracingPipeline ();
+
+ void addShader (VkShaderStageFlagBits shaderStage,
+ Move<VkShaderModule> shaderModule,
+ deUint32 group);
+ void addLibrary (de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipelineLibrary);
+ Move<VkPipeline> createPipeline (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout,
+ const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries = std::vector<de::SharedPtr<Move<VkPipeline>>>());
+ std::vector<de::SharedPtr<Move<VkPipeline>>> createPipelineWithLibraries (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout);
+ de::MovePtr<BufferWithMemory> 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<VkPipeline> createPipelineKHR (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout,
+ const std::vector<de::SharedPtr<Move<VkPipeline>>>& pipelineLibraries);
+
+ std::vector<de::SharedPtr<Move<VkShaderModule> > > m_shadersModules;
+ std::vector<de::SharedPtr<de::MovePtr<RayTracingPipeline>>> m_pipelineLibraries;
+ std::vector<VkPipelineShaderStageCreateInfo> m_shaderCreateInfos;
+ std::vector<VkRayTracingShaderGroupCreateInfoKHR> 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<RayTracingProperties> 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