| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * 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 Ray Tracing Capture/Replay tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktRayTracingCaptureReplayTests.hpp" |
| |
| #include <set> |
| #include "vkDefs.hpp" |
| |
| #include "vktTestCase.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vktCustomInstancesDevices.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkBarrierUtil.hpp" |
| #include "vkBufferWithMemory.hpp" |
| #include "vkImageWithMemory.hpp" |
| #include "vkTypeUtil.hpp" |
| |
| #include "vkRayTracingUtil.hpp" |
| |
| #include "tcuCommandLine.hpp" |
| |
| namespace vkt |
| { |
| namespace RayTracing |
| { |
| namespace |
| { |
| using namespace vk; |
| using namespace vkt; |
| |
| static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR | |
| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR | |
| VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR; |
| |
| static const uint32_t RTCR_DEFAULT_SIZE = 8u; |
| static const uint32_t RTCR_SHADER_COUNT = 4u; |
| |
| enum SBTReplayTestType |
| { |
| TEST_ACCELERATION_STRUCTURES, |
| TEST_PIPELINE_SINGLE, |
| TEST_PIPELINE_AFTER, |
| TEST_PIPELINE_BEFORE |
| }; |
| |
| enum ASOperationTarget |
| { |
| OT_NONE, |
| OT_TOP_ACCELERATION, |
| OT_BOTTOM_ACCELERATION |
| }; |
| |
| enum ASOperationType |
| { |
| OP_NONE, |
| OP_COPY, |
| OP_COMPACT, |
| OP_SERIALIZE |
| }; |
| |
| enum ASBottomTestType |
| { |
| BTT_TRIANGLES, |
| BTT_AABBS |
| }; |
| |
| enum ASTopTestType |
| { |
| TTT_IDENTICAL_INSTANCES, |
| TTT_DIFFERENT_INSTANCES |
| }; |
| |
| struct TestParams; |
| |
| struct PipelineOutput |
| { |
| Move<VkPipeline> pipeline; |
| de::MovePtr<BufferWithMemory> raygenShaderBindingTable; |
| de::MovePtr<BufferWithMemory> missShaderBindingTable; |
| de::MovePtr<BufferWithMemory> hitShaderBindingTable; |
| Move<VkDescriptorSet> descriptorSet; |
| de::MovePtr<BufferWithMemory> uniformBuffer; |
| |
| VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion; |
| VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion; |
| VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion; |
| VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion; |
| }; |
| |
| struct PipelineData |
| { |
| PipelineData(Allocator &alloc) : allocator(alloc) |
| { |
| } |
| VkDescriptorSetLayout descriptorSetLayout; |
| VkDescriptorPool descriptorPool; |
| VkPipelineLayout pipelineLayout; |
| Allocator &allocator; |
| PipelineOutput pipelines[2]; |
| }; |
| |
| class TestConfiguration |
| { |
| public: |
| virtual ~TestConfiguration() |
| { |
| } |
| |
| virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures( |
| Context &context, TestParams &testParams) = 0; |
| virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure( |
| Context &context, TestParams &testParams, |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) = 0; |
| virtual void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, |
| const DeviceInterface &vkd, const VkDevice device, TestParams &testParams, |
| bool replay) = 0; |
| virtual void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, |
| const DeviceInterface &vkd, const VkDevice device, TestParams &testParams, |
| uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment, |
| PipelineData &pipelineData, bool replay) = 0; |
| virtual bool verifyImage(const std::vector<uint32_t> &captureResults, const std::vector<uint32_t> &replayResults, |
| Context &context, TestParams &testParams) = 0; |
| virtual VkFormat getResultImageFormat() = 0; |
| virtual size_t getResultImageFormatSize() = 0; |
| virtual VkClearValue getClearValue() = 0; |
| }; |
| |
| struct TestParams |
| { |
| SBTReplayTestType testType; // SBT |
| ASOperationTarget operationTarget; // AS |
| ASOperationType operationType; // AS |
| vk::VkAccelerationStructureBuildTypeKHR buildType; // AS |
| ASBottomTestType bottomType; // AS |
| ASTopTestType topType; // AS |
| uint32_t width; |
| uint32_t height; |
| de::SharedPtr<TestConfiguration> testConfiguration; |
| }; |
| |
| uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice) |
| { |
| de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR; |
| |
| rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice); |
| return rayTracingPropertiesKHR->getShaderGroupHandleSize(); |
| } |
| |
| uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice) |
| { |
| de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR; |
| |
| rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice); |
| return rayTracingPropertiesKHR->getShaderGroupBaseAlignment(); |
| } |
| |
| VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format) |
| { |
| const VkImageCreateInfo imageCreateInfo = { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| (VkImageCreateFlags)0u, // VkImageCreateFlags flags; |
| VK_IMAGE_TYPE_3D, // VkImageType imageType; |
| format, // VkFormat format; |
| makeExtent3D(width, height, depth), // VkExtent3D extent; |
| 1u, // uint32_t mipLevels; |
| 1u, // uint32_t arrayLayers; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 0u, // uint32_t queueFamilyIndexCount; |
| nullptr, // const uint32_t* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; |
| }; |
| |
| return imageCreateInfo; |
| } |
| |
| Move<VkQueryPool> makeQueryPool(const DeviceInterface &vk, const VkDevice device, const VkQueryType queryType, |
| uint32_t queryCount) |
| { |
| const VkQueryPoolCreateInfo queryPoolCreateInfo = { |
| VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType |
| nullptr, // pNext |
| (VkQueryPoolCreateFlags)0, // flags |
| queryType, // queryType |
| queryCount, // queryCount |
| 0u, // pipelineStatistics |
| }; |
| return createQueryPool(vk, device, &queryPoolCreateInfo); |
| } |
| |
| VkDeviceAddress getAccelerationStructureDeviceAddress(const DeviceInterface &vk, const VkDevice device, |
| VkAccelerationStructureKHR accelerationStructure) |
| { |
| const VkAccelerationStructureDeviceAddressInfoKHR addressInfo = { |
| VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| accelerationStructure // VkAccelerationStructureKHR accelerationStructure |
| }; |
| return vk.getAccelerationStructureDeviceAddressKHR(device, &addressInfo); |
| } |
| |
| class TestShaderBindingTablesConfiguration : public TestConfiguration |
| { |
| public: |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures( |
| Context &context, TestParams &testParams) override; |
| de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure( |
| Context &context, TestParams &testParams, |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override; |
| void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, |
| const DeviceInterface &vkd, const VkDevice device, TestParams &testParams, |
| bool replay) override; |
| void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, |
| const DeviceInterface &vkd, const VkDevice device, TestParams &testParams, |
| uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment, |
| PipelineData &pipelineData, bool replay) override; |
| bool verifyImage(const std::vector<uint32_t> &captureResults, const std::vector<uint32_t> &replayResults, |
| Context &context, TestParams &testParams) override; |
| VkFormat getResultImageFormat() override; |
| size_t getResultImageFormatSize() override; |
| VkClearValue getClearValue() override; |
| |
| protected: |
| VkDeviceAddress sbtSavedRaygenAddress = 0u; |
| VkDeviceAddress sbtSavedMissAddress = 0u; |
| VkDeviceAddress sbtSavedHitAddress = 0u; |
| }; |
| |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> TestShaderBindingTablesConfiguration:: |
| initBottomAccelerationStructures(Context &context, TestParams &testParams) |
| { |
| DE_UNREF(context); |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result; |
| |
| tcu::Vec3 v0(0.0, 1.0, 0.0); |
| tcu::Vec3 v1(0.0, 0.0, 0.0); |
| tcu::Vec3 v2(1.0, 1.0, 0.0); |
| tcu::Vec3 v3(1.0, 0.0, 0.0); |
| |
| for (uint32_t y = 0; y < testParams.height; ++y) |
| for (uint32_t x = 0; x < testParams.width; ++x) |
| { |
| // let's build a chessboard of geometries |
| if (((x + y) % 2) == 0) |
| continue; |
| tcu::Vec3 xyz((float)x, (float)y, 0.0f); |
| std::vector<tcu::Vec3> geometryData; |
| |
| de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = |
| makeBottomLevelAccelerationStructure(); |
| bottomLevelAccelerationStructure->setGeometryCount(1u); |
| |
| geometryData.push_back(xyz + v0); |
| geometryData.push_back(xyz + v1); |
| geometryData.push_back(xyz + v2); |
| geometryData.push_back(xyz + v2); |
| geometryData.push_back(xyz + v1); |
| geometryData.push_back(xyz + v3); |
| |
| bottomLevelAccelerationStructure->addGeometry(geometryData, true); |
| result.push_back( |
| de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release())); |
| } |
| |
| return result; |
| } |
| |
| de::MovePtr<TopLevelAccelerationStructure> TestShaderBindingTablesConfiguration::initTopAccelerationStructure( |
| Context &context, TestParams &testParams, |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) |
| { |
| DE_UNREF(context); |
| uint32_t instanceCount = testParams.width * testParams.height / 2; |
| |
| de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure(); |
| result->setInstanceCount(instanceCount); |
| |
| uint32_t currentInstanceIndex = 0; |
| VkTransformMatrixKHR identityMatrix = { |
| {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}}}; |
| |
| for (uint32_t y = 0; y < testParams.height; ++y) |
| { |
| uint32_t shaderOffset = y % RTCR_SHADER_COUNT; |
| for (uint32_t x = 0; x < testParams.width; ++x) |
| { |
| if (((x + y) % 2) == 0) |
| continue; |
| result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix, 0, 0xFF, |
| shaderOffset); |
| } |
| } |
| |
| return result; |
| } |
| |
| void TestShaderBindingTablesConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, |
| Context &context, const DeviceInterface &vkd, |
| const VkDevice device, TestParams &testParams, |
| bool replay) |
| { |
| DE_UNREF(testParams); |
| DE_UNREF(replay); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 1); |
| for (uint32_t shaderNdx = 0; shaderNdx < RTCR_SHADER_COUNT; ++shaderNdx) |
| { |
| std::stringstream shaderName; |
| shaderName << "chit" << shaderNdx; |
| rayTracingPipeline->addShader( |
| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get(shaderName.str()), 0), 2 + shaderNdx); |
| } |
| } |
| |
| void TestShaderBindingTablesConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, |
| Context &context, const DeviceInterface &vkd, |
| const VkDevice device, TestParams &testParams, |
| uint32_t shaderGroupHandleSize, |
| uint32_t shaderGroupBaseAlignment, |
| PipelineData &pipelineData, bool replay) |
| { |
| DE_UNREF(context); |
| const VkBufferCreateInfo uniformBufferCreateInfo = |
| makeBufferCreateInfo(sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); |
| |
| if (!replay) // capture phase |
| { |
| pipelineData.pipelines[0].pipeline = |
| rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, |
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u); |
| pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, |
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u); |
| pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, |
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u); |
| pipelineData.pipelines[0].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize); |
| pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| |
| // capture SBT addresses |
| VkBufferDeviceAddressInfo deviceAddressInfo = { |
| VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, //VkStructureType sType; |
| nullptr, //const void* pNext; |
| VK_NULL_HANDLE //VkBuffer buffer; |
| }; |
| deviceAddressInfo.buffer = pipelineData.pipelines[0].raygenShaderBindingTable->get(); |
| sbtSavedRaygenAddress = vkd.getBufferOpaqueCaptureAddress(device, &deviceAddressInfo); |
| deviceAddressInfo.buffer = pipelineData.pipelines[0].missShaderBindingTable->get(); |
| sbtSavedMissAddress = vkd.getBufferOpaqueCaptureAddress(device, &deviceAddressInfo); |
| deviceAddressInfo.buffer = pipelineData.pipelines[0].hitShaderBindingTable->get(); |
| sbtSavedHitAddress = vkd.getBufferOpaqueCaptureAddress(device, &deviceAddressInfo); |
| } |
| else // replay phase |
| { |
| switch (testParams.testType) |
| { |
| case TEST_PIPELINE_SINGLE: |
| pipelineData.pipelines[0].pipeline = |
| rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress); |
| pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress); |
| pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress); |
| pipelineData.pipelines[0].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize); |
| pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| |
| break; |
| case TEST_PIPELINE_AFTER: |
| pipelineData.pipelines[0].pipeline = |
| rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress); |
| pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress); |
| pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress); |
| pipelineData.pipelines[0].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize); |
| pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| |
| pipelineData.pipelines[1].pipeline = |
| rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[1].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, 0u); |
| pipelineData.pipelines[1].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, 0u); |
| pipelineData.pipelines[1].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, 0u); |
| pipelineData.pipelines[1].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[1].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[1].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[1].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[1].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize); |
| pipelineData.pipelines[1].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| |
| break; |
| case TEST_PIPELINE_BEFORE: |
| pipelineData.pipelines[0].pipeline = |
| rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, 0u); |
| pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, 0u); |
| pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, 0u); |
| pipelineData.pipelines[0].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize); |
| pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| |
| pipelineData.pipelines[1].pipeline = |
| rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[1].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress); |
| pipelineData.pipelines[1].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress); |
| pipelineData.pipelines[1].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress); |
| pipelineData.pipelines[1].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[1].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[1].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[1].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[1].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize); |
| pipelineData.pipelines[1].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| break; |
| default: |
| TCU_THROW(InternalError, "Wrong test type"); |
| } |
| } |
| } |
| |
| bool TestShaderBindingTablesConfiguration::verifyImage(const std::vector<uint32_t> &captureResults, |
| const std::vector<uint32_t> &replayResults, Context &context, |
| TestParams &testParams) |
| { |
| DE_UNREF(context); |
| |
| uint32_t pipelineCount = (testParams.testType == TEST_PIPELINE_SINGLE) ? 1u : 2u; |
| uint32_t imageSize = testParams.height * testParams.width; |
| uint32_t failures = 0; |
| |
| // verify results - each test case should generate checkerboard pattern |
| for (uint32_t pipelineNdx = 0; pipelineNdx < pipelineCount; ++pipelineNdx) |
| for (uint32_t pos = 0; pos < imageSize; ++pos) |
| { |
| if (captureResults[pos] != replayResults[pipelineNdx * imageSize + pos]) |
| failures++; |
| } |
| return failures == 0; |
| } |
| |
| VkFormat TestShaderBindingTablesConfiguration::getResultImageFormat() |
| { |
| return VK_FORMAT_R32_UINT; |
| } |
| |
| size_t TestShaderBindingTablesConfiguration::getResultImageFormatSize() |
| { |
| return sizeof(uint32_t); |
| } |
| |
| VkClearValue TestShaderBindingTablesConfiguration::getClearValue() |
| { |
| return makeClearValueColorU32(0xFF, 0u, 0u, 0u); |
| } |
| |
| class TestAccelerationStructuresConfiguration : public TestConfiguration |
| { |
| public: |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures( |
| Context &context, TestParams &testParams) override; |
| de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure( |
| Context &context, TestParams &testParams, |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override; |
| void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, |
| const DeviceInterface &vkd, const VkDevice device, TestParams &testParams, |
| bool replay) override; |
| void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, |
| const DeviceInterface &vkd, const VkDevice device, TestParams &testParams, |
| uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment, |
| PipelineData &pipelineData, bool replay) override; |
| bool verifyImage(const std::vector<uint32_t> &captureResults, const std::vector<uint32_t> &replayResults, |
| Context &context, TestParams &testParams) override; |
| VkFormat getResultImageFormat() override; |
| size_t getResultImageFormatSize() override; |
| VkClearValue getClearValue() override; |
| |
| protected: |
| VkDeviceAddress sbtSavedRaygenAddress = 0u; |
| VkDeviceAddress sbtSavedMissAddress = 0u; |
| VkDeviceAddress sbtSavedHitAddress = 0u; |
| }; |
| |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> TestAccelerationStructuresConfiguration:: |
| initBottomAccelerationStructures(Context &context, TestParams &testParams) |
| { |
| DE_UNREF(context); |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result; |
| |
| tcu::Vec3 v0(0.0, 1.0, 0.0); |
| tcu::Vec3 v1(0.0, 0.0, 0.0); |
| tcu::Vec3 v2(1.0, 1.0, 0.0); |
| tcu::Vec3 v3(1.0, 0.0, 0.0); |
| |
| if (testParams.topType == TTT_DIFFERENT_INSTANCES) |
| { |
| de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = |
| makeBottomLevelAccelerationStructure(); |
| bottomLevelAccelerationStructure->setGeometryCount(1u); |
| de::SharedPtr<RaytracedGeometryBase> geometry; |
| if (testParams.bottomType == BTT_TRIANGLES) |
| { |
| geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, |
| VK_INDEX_TYPE_NONE_KHR); |
| geometry->addVertex(v0); |
| geometry->addVertex(v1); |
| geometry->addVertex(v2); |
| geometry->addVertex(v2); |
| geometry->addVertex(v1); |
| geometry->addVertex(v3); |
| } |
| else // m_data.bottomType == BTT_AABBS |
| { |
| geometry = |
| makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR); |
| geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f)); |
| geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f)); |
| } |
| |
| bottomLevelAccelerationStructure->addGeometry(geometry); |
| result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release())); |
| } |
| else // m_data.topTestType == TTT_IDENTICAL_INSTANCES |
| { |
| // triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data |
| for (uint32_t y = 0; y < testParams.height; ++y) |
| for (uint32_t x = 0; x < testParams.width; ++x) |
| { |
| // let's build a chessboard of geometries |
| if (((x + y) % 2) == 0) |
| continue; |
| tcu::Vec3 xyz((float)x, (float)y, 0.0f); |
| |
| de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = |
| makeBottomLevelAccelerationStructure(); |
| bottomLevelAccelerationStructure->setGeometryCount(1u); |
| |
| de::SharedPtr<RaytracedGeometryBase> geometry; |
| if (testParams.bottomType == BTT_TRIANGLES) |
| { |
| geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, |
| VK_INDEX_TYPE_NONE_KHR); |
| geometry->addVertex(xyz + v0); |
| geometry->addVertex(xyz + v1); |
| geometry->addVertex(xyz + v2); |
| geometry->addVertex(xyz + v2); |
| geometry->addVertex(xyz + v1); |
| geometry->addVertex(xyz + v3); |
| } |
| else // testParams.bottomTestType == BTT_AABBS |
| { |
| geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, |
| VK_INDEX_TYPE_NONE_KHR); |
| geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)); |
| geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f)); |
| } |
| |
| bottomLevelAccelerationStructure->addGeometry(geometry); |
| result.push_back( |
| de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release())); |
| } |
| } |
| |
| return result; |
| } |
| |
| de::MovePtr<TopLevelAccelerationStructure> TestAccelerationStructuresConfiguration::initTopAccelerationStructure( |
| Context &context, TestParams &testParams, |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) |
| { |
| DE_UNREF(context); |
| |
| uint32_t instanceCount = testParams.width * testParams.height / 2; |
| |
| de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure(); |
| result->setInstanceCount(instanceCount); |
| |
| if (testParams.topType == TTT_DIFFERENT_INSTANCES) |
| { |
| |
| for (uint32_t y = 0; y < testParams.height; ++y) |
| for (uint32_t x = 0; x < testParams.width; ++x) |
| { |
| if (((x + y) % 2) == 0) |
| continue; |
| const VkTransformMatrixKHR transformMatrixKHR = {{ |
| // float matrix[3][4]; |
| {1.0f, 0.0f, 0.0f, (float)x}, |
| {0.0f, 1.0f, 0.0f, (float)y}, |
| {0.0f, 0.0f, 1.0f, 0.0f}, |
| }}; |
| result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR); |
| } |
| } |
| else // testParams.topType == TTT_IDENTICAL_INSTANCES |
| { |
| uint32_t currentInstanceIndex = 0; |
| |
| for (uint32_t y = 0; y < testParams.height; ++y) |
| for (uint32_t x = 0; x < testParams.width; ++x) |
| { |
| if (((x + y) % 2) == 0) |
| continue; |
| result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]); |
| } |
| } |
| |
| return result; |
| } |
| |
| void TestAccelerationStructuresConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, |
| Context &context, const DeviceInterface &vkd, |
| const VkDevice device, TestParams &testParams, |
| bool replay) |
| { |
| DE_UNREF(testParams); |
| DE_UNREF(replay); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("chit1"), 0), 1); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("chit1"), 0), 2); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0), 2); |
| rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, |
| createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 3); |
| } |
| |
| void TestAccelerationStructuresConfiguration::initShaderBindingTables( |
| de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, const DeviceInterface &vkd, |
| const VkDevice device, TestParams &testParams, uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment, |
| PipelineData &pipelineData, bool replay) |
| { |
| DE_UNREF(context); |
| DE_UNREF(replay); |
| const VkBufferCreateInfo uniformBufferCreateInfo = |
| makeBufferCreateInfo(sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); |
| |
| pipelineData.pipelines[0].pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout); |
| pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 0, 1); |
| if (testParams.bottomType == BTT_AABBS) |
| pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 2, 1); |
| else // testParams.bottomType == BTT_TRIANGLES |
| pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 1, 1); |
| pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable( |
| vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, |
| shaderGroupBaseAlignment, 3, 1); |
| pipelineData.pipelines[0].descriptorSet = |
| makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout); |
| pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible)); |
| pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR( |
| getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), |
| shaderGroupHandleSize, shaderGroupHandleSize); |
| pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0); |
| } |
| |
| bool TestAccelerationStructuresConfiguration::verifyImage(const std::vector<uint32_t> &captureResults, |
| const std::vector<uint32_t> &replayResults, Context &context, |
| TestParams &testParams) |
| { |
| DE_UNREF(context); |
| |
| uint32_t imageSize = testParams.height * testParams.width; |
| uint32_t failures = 0; |
| |
| // verify results - each test case should generate checkerboard pattern |
| for (uint32_t pos = 0; pos < imageSize; ++pos) |
| { |
| if (captureResults[pos] != replayResults[pos]) |
| failures++; |
| } |
| return failures == 0; |
| } |
| |
| VkFormat TestAccelerationStructuresConfiguration::getResultImageFormat() |
| { |
| return VK_FORMAT_R32_UINT; |
| } |
| |
| size_t TestAccelerationStructuresConfiguration::getResultImageFormatSize() |
| { |
| return sizeof(uint32_t); |
| } |
| |
| VkClearValue TestAccelerationStructuresConfiguration::getClearValue() |
| { |
| return makeClearValueColorU32(0xFF, 0u, 0u, 0u); |
| } |
| |
| class RayTracingCaptureReplayTestCase : public TestCase |
| { |
| public: |
| RayTracingCaptureReplayTestCase(tcu::TestContext &context, const char *name, const TestParams &data); |
| ~RayTracingCaptureReplayTestCase(void); |
| |
| virtual void checkSupport(Context &context) const; |
| virtual void initPrograms(SourceCollections &programCollection) const; |
| virtual TestInstance *createInstance(Context &context) const; |
| |
| private: |
| TestParams m_data; |
| }; |
| |
| class RayTracingCaptureReplayTestInstance : public TestInstance |
| { |
| public: |
| RayTracingCaptureReplayTestInstance(Context &context, const TestParams &data); |
| ~RayTracingCaptureReplayTestInstance(void); |
| tcu::TestStatus iterate(void); |
| |
| protected: |
| std::vector<uint32_t> runTest(bool replay); |
| |
| private: |
| TestParams m_data; |
| std::vector<VkDeviceAddress> buildBLASAddresses; |
| std::vector<VkDeviceAddress> copyBLASAddresses; |
| VkDeviceAddress buildTLASAddress; |
| VkDeviceAddress copyTLASAddress; |
| }; |
| |
| RayTracingCaptureReplayTestCase::RayTracingCaptureReplayTestCase(tcu::TestContext &context, const char *name, |
| const TestParams &data) |
| : vkt::TestCase(context, name) |
| , m_data(data) |
| { |
| } |
| |
| RayTracingCaptureReplayTestCase::~RayTracingCaptureReplayTestCase(void) |
| { |
| } |
| |
| void RayTracingCaptureReplayTestCase::checkSupport(Context &context) const |
| { |
| context.requireDeviceFunctionality("VK_KHR_buffer_device_address"); |
| context.requireDeviceFunctionality("VK_KHR_acceleration_structure"); |
| context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline"); |
| |
| const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR = |
| context.getRayTracingPipelineFeatures(); |
| if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false) |
| TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline"); |
| |
| if (m_data.testType == TEST_PIPELINE_BEFORE && |
| rayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplayMixed == false) |
| TCU_THROW( |
| NotSupportedError, |
| "Requires " |
| "VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplayMixed"); |
| |
| if (m_data.testType != TEST_ACCELERATION_STRUCTURES && |
| rayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplay == false) |
| TCU_THROW( |
| NotSupportedError, |
| "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplay"); |
| |
| const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR = |
| context.getAccelerationStructureFeatures(); |
| if (accelerationStructureFeaturesKHR.accelerationStructure == false) |
| TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires " |
| "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure"); |
| |
| if (m_data.testType == TEST_ACCELERATION_STRUCTURES && |
| accelerationStructureFeaturesKHR.accelerationStructureCaptureReplay == false) |
| TCU_THROW(NotSupportedError, |
| "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureCaptureReplay"); |
| |
| if (m_data.testType == TEST_ACCELERATION_STRUCTURES && |
| m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && |
| accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false) |
| TCU_THROW(NotSupportedError, |
| "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands"); |
| |
| const VkPhysicalDeviceBufferDeviceAddressFeatures &bufferDeviceAddressFeatures = |
| context.getBufferDeviceAddressFeatures(); |
| |
| if (bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay == false) |
| TCU_THROW(NotSupportedError, "Requires bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay"); |
| } |
| |
| void RayTracingCaptureReplayTestCase::initPrograms(SourceCollections &programCollection) const |
| { |
| const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true); |
| { |
| std::stringstream css; |
| css << "#version 460 core\n" |
| "#extension GL_EXT_ray_tracing : require\n" |
| "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n" |
| "layout(set = 0, binding = 0) uniform UniformParams\n" |
| "{\n" |
| " uint targetLayer;\n" |
| "} uniformParams;\n" |
| "layout(r32ui, set = 0, binding = 1) uniform uimage3D result;\n" |
| "layout(set = 0, binding = 2) uniform accelerationStructureEXT topLevelAS;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " float tmin = 0.0;\n" |
| " float tmax = 1.0;\n" |
| " vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n" |
| " vec3 direct = vec3(0.0, 0.0, -1.0);\n" |
| " hitValue = uvec4(0,0,0,0);\n" |
| " traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n" |
| " imageStore(result, ivec3(gl_LaunchIDEXT.xy, uniformParams.targetLayer), hitValue);\n" |
| "}\n"; |
| programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions; |
| } |
| |
| for (uint32_t shaderNdx = 0; shaderNdx < RTCR_SHADER_COUNT; ++shaderNdx) |
| { |
| uint32_t colorValue = 2 * (shaderNdx + 1); |
| std::stringstream css; |
| css << "#version 460 core\n" |
| "#extension GL_EXT_ray_tracing : require\n" |
| "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n" |
| "void main()\n" |
| "{\n" |
| " hitValue = uvec4(" |
| << colorValue |
| << ",0,0,1);\n" |
| "}\n"; |
| std::stringstream shaderName; |
| shaderName << "chit" << shaderNdx; |
| |
| programCollection.glslSources.add(shaderName.str()) |
| << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions; |
| } |
| |
| { |
| std::stringstream css; |
| css << "#version 460 core\n" |
| "#extension GL_EXT_ray_tracing : require\n" |
| "hitAttributeEXT uvec4 hitAttribute;\n" |
| "void main()\n" |
| "{\n" |
| " hitAttribute = uvec4(0,0,0,0);\n" |
| " reportIntersectionEXT(0.5f, 0);\n" |
| "}\n"; |
| |
| programCollection.glslSources.add("isect") |
| << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions; |
| } |
| |
| { |
| std::stringstream css; |
| css << "#version 460 core\n" |
| "#extension GL_EXT_ray_tracing : require\n" |
| "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n" |
| "void main()\n" |
| "{\n" |
| " hitValue = uvec4(1,0,0,1);\n" |
| "}\n"; |
| |
| programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions; |
| } |
| } |
| |
| TestInstance *RayTracingCaptureReplayTestCase::createInstance(Context &context) const |
| { |
| return new RayTracingCaptureReplayTestInstance(context, m_data); |
| } |
| |
| RayTracingCaptureReplayTestInstance::RayTracingCaptureReplayTestInstance(Context &context, const TestParams &data) |
| : vkt::TestInstance(context) |
| , m_data(data) |
| { |
| } |
| |
| RayTracingCaptureReplayTestInstance::~RayTracingCaptureReplayTestInstance(void) |
| { |
| } |
| |
| std::vector<uint32_t> RayTracingCaptureReplayTestInstance::runTest(bool replay) |
| { |
| const auto &vki = m_context.getInstanceInterface(); |
| const auto physicalDevice = m_context.getPhysicalDevice(); |
| const auto &vkd = m_context.getDeviceInterface(); |
| const auto device = m_context.getDevice(); |
| auto allocator = &m_context.getDefaultAllocator(); |
| const auto queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| const auto queue = m_context.getUniversalQueue(); |
| |
| // Create common pipeline layout for all raytracing pipelines |
| const Move<VkDescriptorSetLayout> descriptorSetLayout = |
| DescriptorSetLayoutBuilder() |
| .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ALL_RAY_TRACING_STAGES) |
| .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES) |
| .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES) |
| .build(vkd, device); |
| uint32_t pipelineCount = |
| (!replay || (m_data.testType == TEST_PIPELINE_SINGLE) || (m_data.testType == TEST_ACCELERATION_STRUCTURES)) ? |
| 1u : |
| 2u; |
| const Move<VkDescriptorPool> descriptorPool = |
| DescriptorPoolBuilder() |
| .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pipelineCount) |
| .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, pipelineCount) |
| .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, pipelineCount) |
| .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, pipelineCount); |
| const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get()); |
| |
| // All pipelines will be using the same set of shaders and shader groups. |
| // Single RayTracingPipeline object will be enough to define it |
| de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>(); |
| m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, vkd, device, m_data, replay); |
| |
| // Capture phase ( replay==false ): |
| // - TEST_ACCELERATION_STRUCTURES: |
| // - build/copy/compact/serialize structure, record addresses |
| // - TEST_PIPELINE_SINGLE: |
| // - TEST_PIPELINE_AFTER: |
| // - TEST_PIPELINE_BEFORE: |
| // - single pipeline records addresses and fills test data |
| // Replay phase ( replay==true ): |
| // - TEST_ACCELERATION_STRUCTURES: |
| // - build/copy/compact/serialize structure with addresses captured previously |
| // - TEST_PIPELINE_SINGLE: |
| // - single pipeline with addresses captured previously - writes into first image layer |
| // - TEST_PIPELINE_AFTER: |
| // - first pipeline with addresses captured previously - writes into first image layer |
| // - second pipeline created without captured addresses - writes into second image layer |
| // - TEST_PIPELINE_BEFORE: |
| // - first pipeline created without captured addresses - writes into first image layer |
| // - second pipeline with addresses captured previously - writes into second image layer |
| // |
| // Comparing results in all tests: all layers must be identical to the layer from capture phase |
| |
| PipelineData pipelineData(*allocator); |
| pipelineData.pipelineLayout = *pipelineLayout; |
| pipelineData.descriptorSetLayout = *descriptorSetLayout; |
| pipelineData.descriptorPool = *descriptorPool; |
| const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice); |
| const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice); |
| m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, vkd, device, m_data, |
| shaderGroupHandleSize, shaderGroupBaseAlignment, pipelineData, |
| replay); |
| |
| const VkFormat imageFormat = m_data.testConfiguration->getResultImageFormat(); |
| const VkImageCreateInfo imageCreateInfo = |
| makeImageCreateInfo(m_data.width, m_data.height, pipelineCount, imageFormat); |
| const VkImageSubresourceRange imageSubresourceRange = |
| makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u); |
| const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>( |
| new ImageWithMemory(vkd, device, *allocator, imageCreateInfo, MemoryRequirement::Any)); |
| const Move<VkImageView> imageView = |
| makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange); |
| const VkDescriptorImageInfo descriptorImageInfo = |
| makeDescriptorImageInfo(VK_NULL_HANDLE, *imageView, VK_IMAGE_LAYOUT_GENERAL); |
| |
| const uint32_t pixelCount = m_data.width * m_data.height * pipelineCount; |
| const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo( |
| pixelCount * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| const VkImageSubresourceLayers resultBufferImageSubresourceLayers = |
| makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u); |
| const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy( |
| makeExtent3D(m_data.width, m_data.height, pipelineCount), resultBufferImageSubresourceLayers); |
| de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>( |
| new BufferWithMemory(vkd, device, *allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible)); |
| |
| const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex); |
| const Move<VkCommandBuffer> cmdBuffer = |
| allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures; |
| de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure; |
| std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies; |
| de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy; |
| std::vector<de::SharedPtr<SerialStorage>> bottomSerialized; |
| std::vector<de::SharedPtr<SerialStorage>> topSerialized; |
| Move<VkQueryPool> m_queryPoolCompact; |
| Move<VkQueryPool> m_queryPoolSerial; |
| |
| beginCommandBuffer(vkd, *cmdBuffer, 0u); |
| { |
| const VkImageMemoryBarrier preImageBarrier = |
| makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange); |
| cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, |
| VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier); |
| const VkClearValue clearValue = m_data.testConfiguration->getClearValue(); |
| vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, |
| &imageSubresourceRange); |
| const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier( |
| VK_ACCESS_TRANSFER_WRITE_BIT, |
| VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange); |
| cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, |
| VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier); |
| |
| // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures ) |
| bool bottomCompact = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_COMPACT && |
| m_data.operationTarget == OT_BOTTOM_ACCELERATION; |
| bool bottomSerial = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_SERIALIZE && |
| m_data.operationTarget == OT_BOTTOM_ACCELERATION; |
| bottomLevelAccelerationStructures = |
| m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data); |
| VkBuildAccelerationStructureFlagsKHR allowCompactionFlag = |
| VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; |
| VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0); |
| VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = |
| (bottomCompact ? allowCompactionFlag : emptyCompactionFlag); |
| std::vector<VkAccelerationStructureKHR> accelerationStructureHandles; |
| std::vector<VkDeviceSize> bottomBlasCompactSize; |
| std::vector<VkDeviceSize> bottomBlasSerialSize; |
| |
| for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx) |
| { |
| bottomLevelAccelerationStructures[idx]->setBuildFlags(bottomBuildFlags); |
| bottomLevelAccelerationStructures[idx]->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = |
| (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay) ? buildBLASAddresses[idx] : 0u; |
| if (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay) |
| bottomLevelAccelerationStructures[idx]->setCreateFlags( |
| VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| bottomLevelAccelerationStructures[idx]->createAndBuild(vkd, device, *cmdBuffer, *allocator, deviceAddress); |
| accelerationStructureHandles.push_back(*(bottomLevelAccelerationStructures[idx]->getPtr())); |
| if (m_data.testType == TEST_ACCELERATION_STRUCTURES && !replay) |
| buildBLASAddresses.push_back(getAccelerationStructureDeviceAddress( |
| vkd, device, *(bottomLevelAccelerationStructures[idx]->getPtr()))); |
| } |
| |
| if (m_data.operationType == OP_COMPACT) |
| { |
| uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? |
| uint32_t(bottomLevelAccelerationStructures.size()) : |
| 1u; |
| if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) |
| m_queryPoolCompact = |
| makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount); |
| if (m_data.operationTarget == OT_BOTTOM_ACCELERATION) |
| queryAccelerationStructureSize( |
| vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize); |
| } |
| if (m_data.operationType == OP_SERIALIZE) |
| { |
| uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? |
| uint32_t(bottomLevelAccelerationStructures.size()) : |
| 1u; |
| if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) |
| m_queryPoolSerial = |
| makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount); |
| if (m_data.operationTarget == OT_BOTTOM_ACCELERATION) |
| queryAccelerationStructureSize( |
| vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize); |
| } |
| |
| // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU |
| if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial)) |
| { |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer.get()); |
| |
| if (bottomCompact) |
| VK_CHECK(vkd.getQueryPoolResults( |
| device, *m_queryPoolCompact, 0u, uint32_t(bottomBlasCompactSize.size()), |
| sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(), |
| sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)); |
| if (bottomSerial) |
| VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(bottomBlasSerialSize.size()), |
| sizeof(VkDeviceSize) * bottomBlasSerialSize.size(), |
| bottomBlasSerialSize.data(), sizeof(VkDeviceSize), |
| VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)); |
| |
| vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); |
| beginCommandBuffer(vkd, *cmdBuffer, 0u); |
| } |
| |
| auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures; |
| if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION) |
| { |
| switch (m_data.operationType) |
| { |
| case OP_COPY: |
| { |
| for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx) |
| { |
| de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure(); |
| asCopy->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = replay ? copyBLASAddresses[idx] : 0u; |
| if (replay) |
| asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, |
| bottomLevelAccelerationStructures[idx].get(), 0u, deviceAddress); |
| bottomLevelAccelerationStructureCopies.push_back( |
| de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release())); |
| if (!replay) |
| copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress( |
| vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr()))); |
| } |
| break; |
| } |
| case OP_COMPACT: |
| { |
| for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx) |
| { |
| de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure(); |
| asCopy->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = replay ? copyBLASAddresses[idx] : 0u; |
| if (replay) |
| asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, |
| bottomLevelAccelerationStructures[idx].get(), bottomBlasCompactSize[idx], |
| deviceAddress); |
| bottomLevelAccelerationStructureCopies.push_back( |
| de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release())); |
| if (!replay) |
| copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress( |
| vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr()))); |
| } |
| break; |
| } |
| case OP_SERIALIZE: |
| { |
| for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx) |
| { |
| de::SharedPtr<SerialStorage> storage( |
| new SerialStorage(vkd, device, *allocator, m_data.buildType, bottomBlasSerialSize[idx])); |
| bottomLevelAccelerationStructures[idx]->serialize(vkd, device, *cmdBuffer, storage.get()); |
| bottomSerialized.push_back(storage); |
| |
| if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) |
| { |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer.get()); |
| |
| vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); |
| beginCommandBuffer(vkd, *cmdBuffer, 0u); |
| } |
| |
| de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure(); |
| asCopy->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = replay ? copyBLASAddresses[idx] : 0u; |
| if (replay) |
| asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, *allocator, storage.get(), deviceAddress); |
| bottomLevelAccelerationStructureCopies.push_back( |
| de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release())); |
| if (!replay) |
| copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress( |
| vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr()))); |
| } |
| break; |
| } |
| default: |
| DE_ASSERT(false); |
| } |
| bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies; |
| } |
| |
| // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures ) |
| bool topCompact = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_COMPACT && |
| m_data.operationTarget == OT_TOP_ACCELERATION; |
| bool topSerial = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_SERIALIZE && |
| m_data.operationTarget == OT_TOP_ACCELERATION; |
| VkBuildAccelerationStructureFlagsKHR topBuildFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag); |
| std::vector<VkAccelerationStructureKHR> topLevelStructureHandles; |
| std::vector<VkDeviceSize> topBlasCompactSize; |
| std::vector<VkDeviceSize> topBlasSerialSize; |
| |
| topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure( |
| m_context, m_data, *bottomLevelAccelerationStructuresPtr); |
| topLevelAccelerationStructure->setBuildFlags(topBuildFlags); |
| topLevelAccelerationStructure->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddressBuild = |
| (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay) ? buildTLASAddress : 0u; |
| if (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay) |
| topLevelAccelerationStructure->setCreateFlags( |
| VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, *allocator, deviceAddressBuild); |
| topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr())); |
| if (m_data.testType == TEST_ACCELERATION_STRUCTURES && !replay) |
| buildTLASAddress = |
| getAccelerationStructureDeviceAddress(vkd, device, *(topLevelAccelerationStructure->getPtr())); |
| |
| if (topCompact) |
| queryAccelerationStructureSize( |
| vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize); |
| if (topSerial) |
| queryAccelerationStructureSize( |
| vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize); |
| |
| // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU |
| if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial)) |
| { |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer.get()); |
| |
| if (topCompact) |
| VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, uint32_t(topBlasCompactSize.size()), |
| sizeof(VkDeviceSize) * topBlasCompactSize.size(), |
| topBlasCompactSize.data(), sizeof(VkDeviceSize), |
| VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)); |
| if (topSerial) |
| VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(topBlasSerialSize.size()), |
| sizeof(VkDeviceSize) * topBlasSerialSize.size(), |
| topBlasSerialSize.data(), sizeof(VkDeviceSize), |
| VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)); |
| |
| vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); |
| beginCommandBuffer(vkd, *cmdBuffer, 0u); |
| } |
| |
| const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get(); |
| if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION) |
| { |
| switch (m_data.operationType) |
| { |
| case OP_COPY: |
| { |
| topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure(); |
| topLevelAccelerationStructureCopy->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = replay ? copyTLASAddress : 0u; |
| if (replay) |
| topLevelAccelerationStructureCopy->setCreateFlags( |
| VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| topLevelAccelerationStructureCopy->createAndCopyFrom( |
| vkd, device, *cmdBuffer, *allocator, topLevelAccelerationStructure.get(), 0u, deviceAddress); |
| if (!replay) |
| copyTLASAddress = getAccelerationStructureDeviceAddress( |
| vkd, device, *(topLevelAccelerationStructureCopy->getPtr())); |
| break; |
| } |
| case OP_COMPACT: |
| { |
| topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure(); |
| topLevelAccelerationStructureCopy->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = replay ? copyTLASAddress : 0u; |
| if (replay) |
| topLevelAccelerationStructureCopy->setCreateFlags( |
| VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, |
| topLevelAccelerationStructure.get(), |
| topBlasCompactSize[0], deviceAddress); |
| if (!replay) |
| copyTLASAddress = getAccelerationStructureDeviceAddress( |
| vkd, device, *(topLevelAccelerationStructureCopy->getPtr())); |
| break; |
| } |
| case OP_SERIALIZE: |
| { |
| de::SharedPtr<SerialStorage> storage( |
| new SerialStorage(vkd, device, *allocator, m_data.buildType, topBlasSerialSize[0])); |
| topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get()); |
| topSerialized.push_back(storage); |
| |
| if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) |
| { |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer.get()); |
| |
| vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); |
| beginCommandBuffer(vkd, *cmdBuffer, 0u); |
| } |
| |
| topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure(); |
| topLevelAccelerationStructureCopy->setBuildType(m_data.buildType); |
| VkDeviceAddress deviceAddress = replay ? copyTLASAddress : 0u; |
| if (replay) |
| topLevelAccelerationStructureCopy->setCreateFlags( |
| VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR); |
| topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, *allocator, |
| storage.get(), deviceAddress); |
| if (!replay) |
| copyTLASAddress = getAccelerationStructureDeviceAddress( |
| vkd, device, *(topLevelAccelerationStructureCopy->getPtr())); |
| break; |
| } |
| default: |
| DE_ASSERT(false); |
| } |
| topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get(); |
| } |
| |
| // copy layer index into uniform buffer |
| for (uint32_t i = 0; i < pipelineCount; ++i) |
| { |
| deMemcpy(pipelineData.pipelines[i].uniformBuffer->getAllocation().getHostPtr(), &i, sizeof(uint32_t)); |
| flushMappedMemoryRange(vkd, device, pipelineData.pipelines[i].uniformBuffer->getAllocation().getMemory(), |
| pipelineData.pipelines[i].uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE); |
| } |
| |
| const VkMemoryBarrier preTraceMemoryBarrier = |
| makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); |
| cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, |
| VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier); |
| |
| VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| 1u, // uint32_t accelerationStructureCount; |
| topLevelRayTracedPtr->getPtr() // const VkAccelerationStructureKHR* pAccelerationStructures; |
| }; |
| |
| for (uint32_t i = 0; i < pipelineCount; ++i) |
| { |
| VkDescriptorBufferInfo uniformBufferInfo = |
| makeDescriptorBufferInfo(pipelineData.pipelines[i].uniformBuffer->get(), 0ull, sizeof(uint32_t)); |
| |
| DescriptorSetUpdateBuilder() |
| .writeSingle(*(pipelineData.pipelines[i].descriptorSet), |
| DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, |
| &uniformBufferInfo) |
| .writeSingle(*(pipelineData.pipelines[i].descriptorSet), |
| DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, |
| &descriptorImageInfo) |
| .writeSingle(*(pipelineData.pipelines[i].descriptorSet), |
| DescriptorSetUpdateBuilder::Location::binding(2u), |
| VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet) |
| .update(vkd, device); |
| |
| vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, |
| &(pipelineData.pipelines[i].descriptorSet.get()), 0, nullptr); |
| |
| vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, |
| *(pipelineData.pipelines[i].pipeline)); |
| |
| cmdTraceRays(vkd, *cmdBuffer, &(pipelineData.pipelines[i].raygenShaderBindingTableRegion), |
| &(pipelineData.pipelines[i].missShaderBindingTableRegion), |
| &(pipelineData.pipelines[i].hitShaderBindingTableRegion), |
| &(pipelineData.pipelines[i].callableShaderBindingTableRegion), m_data.width, m_data.height, 1); |
| } |
| |
| const VkMemoryBarrier postTraceMemoryBarrier = |
| makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); |
| const VkMemoryBarrier postCopyMemoryBarrier = |
| makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT); |
| cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, |
| VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier); |
| |
| vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, |
| &resultBufferImageRegion); |
| |
| cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, |
| &postCopyMemoryBarrier); |
| } |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, cmdBuffer.get()); |
| |
| invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), |
| resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(uint32_t)); |
| |
| std::vector<uint32_t> result(pixelCount); |
| deMemcpy(result.data(), resultBuffer->getAllocation().getHostPtr(), pixelCount * sizeof(uint32_t)); |
| return result; |
| } |
| |
| tcu::TestStatus RayTracingCaptureReplayTestInstance::iterate(void) |
| { |
| // run test capturing different elements |
| const std::vector<uint32_t> captureResults = runTest(false); |
| |
| // run test that replays different elements |
| const std::vector<uint32_t> replayResults = runTest(true); |
| |
| if (!m_data.testConfiguration->verifyImage(captureResults, replayResults, m_context, m_data)) |
| return tcu::TestStatus::fail("Fail"); |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| } // namespace |
| |
| void addReplayShaderBindingTablesTests(tcu::TestCaseGroup *group) |
| { |
| struct |
| { |
| SBTReplayTestType testType; |
| const char *name; |
| } testTypes[] = { |
| // Capture-replay scenario with single captured pipeline |
| {TEST_PIPELINE_SINGLE, "pipeline_single"}, |
| // Not captured pipeline created after captured one |
| {TEST_PIPELINE_AFTER, "pipeline_after_captured"}, |
| // Not captured pipeline created before captured one |
| {TEST_PIPELINE_BEFORE, "pipeline_before_captured"}, |
| }; |
| |
| for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx) |
| { |
| TestParams testParams{testTypes[testTypeNdx].testType, |
| OT_NONE, |
| OP_NONE, |
| VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, |
| BTT_TRIANGLES, |
| TTT_IDENTICAL_INSTANCES, |
| RTCR_DEFAULT_SIZE, |
| RTCR_DEFAULT_SIZE, |
| de::SharedPtr<TestConfiguration>(new TestShaderBindingTablesConfiguration())}; |
| group->addChild( |
| new RayTracingCaptureReplayTestCase(group->getTestContext(), testTypes[testTypeNdx].name, testParams)); |
| } |
| } |
| |
| void addReplayAccelerationStruturesTests(tcu::TestCaseGroup *group) |
| { |
| struct |
| { |
| ASOperationType operationType; |
| const char *name; |
| } operationTypes[] = { |
| {OP_NONE, "building"}, |
| {OP_COPY, "copy"}, |
| {OP_COMPACT, "compaction"}, |
| {OP_SERIALIZE, "serialization"}, |
| }; |
| |
| struct |
| { |
| vk::VkAccelerationStructureBuildTypeKHR buildType; |
| const char *name; |
| } buildTypes[] = { |
| {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"}, |
| {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"}, |
| }; |
| |
| struct |
| { |
| ASOperationTarget operationTarget; |
| const char *name; |
| } operationTargets[] = { |
| {OT_TOP_ACCELERATION, "top_acceleration_structure"}, |
| {OT_BOTTOM_ACCELERATION, "bottom_acceleration_structure"}, |
| }; |
| |
| struct |
| { |
| ASBottomTestType testType; |
| const char *name; |
| } bottomTestTypes[] = { |
| {BTT_TRIANGLES, "triangles"}, |
| {BTT_AABBS, "aabbs"}, |
| }; |
| |
| for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> operationTypeGroup( |
| new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name)); |
| |
| for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> buildGroup( |
| new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name)); |
| |
| for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets); |
| ++operationTargetNdx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> operationTargetGroup( |
| new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name)); |
| |
| for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx) |
| { |
| ASTopTestType topTest = |
| (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ? |
| TTT_DIFFERENT_INSTANCES : |
| TTT_IDENTICAL_INSTANCES; |
| |
| TestParams testParams{ |
| TEST_ACCELERATION_STRUCTURES, |
| operationTargets[operationTargetNdx].operationTarget, |
| operationTypes[operationTypeNdx].operationType, |
| buildTypes[buildTypeNdx].buildType, |
| bottomTestTypes[testTypeNdx].testType, |
| topTest, |
| RTCR_DEFAULT_SIZE, |
| RTCR_DEFAULT_SIZE, |
| de::SharedPtr<TestConfiguration>(new TestAccelerationStructuresConfiguration())}; |
| operationTargetGroup->addChild(new RayTracingCaptureReplayTestCase( |
| group->getTestContext(), bottomTestTypes[testTypeNdx].name, testParams)); |
| } |
| buildGroup->addChild(operationTargetGroup.release()); |
| } |
| operationTypeGroup->addChild(buildGroup.release()); |
| } |
| group->addChild(operationTypeGroup.release()); |
| } |
| } |
| |
| tcu::TestCaseGroup *createCaptureReplayTests(tcu::TestContext &testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "capture_replay")); |
| |
| // Test replaying shader binding tables |
| addTestGroup(group.get(), "shader_binding_tables", addReplayShaderBindingTablesTests); |
| // Test replaying acceleration structure |
| addTestGroup(group.get(), "acceleration_structures", addReplayAccelerationStruturesTests); |
| |
| return group.release(); |
| } |
| |
| } // namespace RayTracing |
| |
| } // namespace vkt |