From 8e5754036c2e8d29f60580891b24f9b476508f06 Mon Sep 17 00:00:00 2001 From: Boris Zanin Date: Wed, 27 May 2020 14:54:20 +0200 Subject: [PATCH] Watertightness tests for VK_KHR_ray_query Performs watertightness tests for VK_KHR_ray_query. Add tests: * dEQP-VK.ray_query.watertightness.* Components: Vulkan VK-GL-CTS issue: 2380 Change-Id: I48ff5360d3fa348057175e6811f4281fb80f73b7 --- AndroidGen.mk | 1 + android/cts/master/vk-master-2020-03-01.txt | 36 + android/cts/master/vk-master.txt | 36 + .../framework/vulkan/vkRayTracingUtil.cpp | 4 +- .../modules/vulkan/ray_query/CMakeLists.txt | 2 + .../modules/vulkan/ray_query/vktRayQueryTests.cpp | 3 +- .../ray_query/vktRayQueryWatertightnessTests.cpp | 2349 ++++++++++++++++++++ .../ray_query/vktRayQueryWatertightnessTests.hpp | 39 + external/vulkancts/mustpass/master/vk-default.txt | 36 + 9 files changed, 2504 insertions(+), 2 deletions(-) create mode 100644 external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.cpp create mode 100644 external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.hpp diff --git a/AndroidGen.mk b/AndroidGen.mk index 16dc260..a8716af 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -267,6 +267,7 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/ray_query/vktRayQueryBuiltinTests.cpp \ external/vulkancts/modules/vulkan/ray_query/vktRayQueryTests.cpp \ external/vulkancts/modules/vulkan/ray_query/vktRayQueryTraversalControlTests.cpp \ + external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.cpp \ external/vulkancts/modules/vulkan/ray_tracing/vktRayTracingAccelerationStructuresTests.cpp \ external/vulkancts/modules/vulkan/ray_tracing/vktRayTracingBuildIndirectTests.cpp \ external/vulkancts/modules/vulkan/ray_tracing/vktRayTracingBuildLargeTests.cpp \ diff --git a/android/cts/master/vk-master-2020-03-01.txt b/android/cts/master/vk-master-2020-03-01.txt index c74d419..542a96e 100644 --- a/android/cts/master/vk-master-2020-03-01.txt +++ b/android/cts/master/vk-master-2020-03-01.txt @@ -243725,3 +243725,39 @@ dEQP-VK.ray_query.advanced.null_as.sect.triangles dEQP-VK.ray_query.advanced.null_as.sect.aabbs dEQP-VK.ray_query.advanced.null_as.call.triangles dEQP-VK.ray_query.advanced.null_as.call.aabbs +dEQP-VK.ray_query.watertightness.nomiss.vert.triangles +dEQP-VK.ray_query.watertightness.nomiss.vert.aabbs +dEQP-VK.ray_query.watertightness.nomiss.tesc.triangles +dEQP-VK.ray_query.watertightness.nomiss.tesc.aabbs +dEQP-VK.ray_query.watertightness.nomiss.tese.triangles +dEQP-VK.ray_query.watertightness.nomiss.tese.aabbs +dEQP-VK.ray_query.watertightness.nomiss.geom.triangles +dEQP-VK.ray_query.watertightness.nomiss.geom.aabbs +dEQP-VK.ray_query.watertightness.nomiss.frag.triangles +dEQP-VK.ray_query.watertightness.nomiss.frag.aabbs +dEQP-VK.ray_query.watertightness.nomiss.comp.triangles +dEQP-VK.ray_query.watertightness.nomiss.comp.aabbs +dEQP-VK.ray_query.watertightness.nomiss.rgen.triangles +dEQP-VK.ray_query.watertightness.nomiss.rgen.aabbs +dEQP-VK.ray_query.watertightness.nomiss.ahit.triangles +dEQP-VK.ray_query.watertightness.nomiss.ahit.aabbs +dEQP-VK.ray_query.watertightness.nomiss.chit.triangles +dEQP-VK.ray_query.watertightness.nomiss.chit.aabbs +dEQP-VK.ray_query.watertightness.nomiss.miss.triangles +dEQP-VK.ray_query.watertightness.nomiss.miss.aabbs +dEQP-VK.ray_query.watertightness.nomiss.sect.triangles +dEQP-VK.ray_query.watertightness.nomiss.sect.aabbs +dEQP-VK.ray_query.watertightness.nomiss.call.triangles +dEQP-VK.ray_query.watertightness.nomiss.call.aabbs +dEQP-VK.ray_query.watertightness.singlehit.vert.triangles +dEQP-VK.ray_query.watertightness.singlehit.tesc.triangles +dEQP-VK.ray_query.watertightness.singlehit.tese.triangles +dEQP-VK.ray_query.watertightness.singlehit.geom.triangles +dEQP-VK.ray_query.watertightness.singlehit.frag.triangles +dEQP-VK.ray_query.watertightness.singlehit.comp.triangles +dEQP-VK.ray_query.watertightness.singlehit.rgen.triangles +dEQP-VK.ray_query.watertightness.singlehit.ahit.triangles +dEQP-VK.ray_query.watertightness.singlehit.chit.triangles +dEQP-VK.ray_query.watertightness.singlehit.miss.triangles +dEQP-VK.ray_query.watertightness.singlehit.sect.triangles +dEQP-VK.ray_query.watertightness.singlehit.call.triangles diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 6e0bf45..6b2e62c 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -639881,3 +639881,39 @@ dEQP-VK.ray_query.advanced.null_as.sect.triangles dEQP-VK.ray_query.advanced.null_as.sect.aabbs dEQP-VK.ray_query.advanced.null_as.call.triangles dEQP-VK.ray_query.advanced.null_as.call.aabbs +dEQP-VK.ray_query.watertightness.nomiss.vert.triangles +dEQP-VK.ray_query.watertightness.nomiss.vert.aabbs +dEQP-VK.ray_query.watertightness.nomiss.tesc.triangles +dEQP-VK.ray_query.watertightness.nomiss.tesc.aabbs +dEQP-VK.ray_query.watertightness.nomiss.tese.triangles +dEQP-VK.ray_query.watertightness.nomiss.tese.aabbs +dEQP-VK.ray_query.watertightness.nomiss.geom.triangles +dEQP-VK.ray_query.watertightness.nomiss.geom.aabbs +dEQP-VK.ray_query.watertightness.nomiss.frag.triangles +dEQP-VK.ray_query.watertightness.nomiss.frag.aabbs +dEQP-VK.ray_query.watertightness.nomiss.comp.triangles +dEQP-VK.ray_query.watertightness.nomiss.comp.aabbs +dEQP-VK.ray_query.watertightness.nomiss.rgen.triangles +dEQP-VK.ray_query.watertightness.nomiss.rgen.aabbs +dEQP-VK.ray_query.watertightness.nomiss.ahit.triangles +dEQP-VK.ray_query.watertightness.nomiss.ahit.aabbs +dEQP-VK.ray_query.watertightness.nomiss.chit.triangles +dEQP-VK.ray_query.watertightness.nomiss.chit.aabbs +dEQP-VK.ray_query.watertightness.nomiss.miss.triangles +dEQP-VK.ray_query.watertightness.nomiss.miss.aabbs +dEQP-VK.ray_query.watertightness.nomiss.sect.triangles +dEQP-VK.ray_query.watertightness.nomiss.sect.aabbs +dEQP-VK.ray_query.watertightness.nomiss.call.triangles +dEQP-VK.ray_query.watertightness.nomiss.call.aabbs +dEQP-VK.ray_query.watertightness.singlehit.vert.triangles +dEQP-VK.ray_query.watertightness.singlehit.tesc.triangles +dEQP-VK.ray_query.watertightness.singlehit.tese.triangles +dEQP-VK.ray_query.watertightness.singlehit.geom.triangles +dEQP-VK.ray_query.watertightness.singlehit.frag.triangles +dEQP-VK.ray_query.watertightness.singlehit.comp.triangles +dEQP-VK.ray_query.watertightness.singlehit.rgen.triangles +dEQP-VK.ray_query.watertightness.singlehit.ahit.triangles +dEQP-VK.ray_query.watertightness.singlehit.chit.triangles +dEQP-VK.ray_query.watertightness.singlehit.miss.triangles +dEQP-VK.ray_query.watertightness.singlehit.sect.triangles +dEQP-VK.ray_query.watertightness.singlehit.call.triangles diff --git a/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp b/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp index 471ca65..89e2abf 100644 --- a/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp +++ b/external/vulkancts/framework/vulkan/vkRayTracingUtil.cpp @@ -142,7 +142,9 @@ VkDeviceAddress getBufferDeviceAddress ( const DeviceInterface& vk, const VkBuffer buffer, VkDeviceSize offset ) { - DE_ASSERT(buffer != DE_NULL); + + if (buffer == DE_NULL) + return 0; VkBufferDeviceAddressInfo deviceAddressInfo { diff --git a/external/vulkancts/modules/vulkan/ray_query/CMakeLists.txt b/external/vulkancts/modules/vulkan/ray_query/CMakeLists.txt index a0ebfc3..f6cbf0f 100644 --- a/external/vulkancts/modules/vulkan/ray_query/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/ray_query/CMakeLists.txt @@ -9,6 +9,8 @@ set(DEQP_VK_RAY_QUERY_SRCS vktRayQueryTraversalControlTests.hpp vktRayQueryAccelerationStructuresTests.cpp vktRayQueryAccelerationStructuresTests.hpp + vktRayQueryWatertightnessTests.cpp + vktRayQueryWatertightnessTests.hpp ) set(DEQP_VK_RAY_QUERY_LIBS diff --git a/external/vulkancts/modules/vulkan/ray_query/vktRayQueryTests.cpp b/external/vulkancts/modules/vulkan/ray_query/vktRayQueryTests.cpp index 75ccc8a..1bf98d6 100644 --- a/external/vulkancts/modules/vulkan/ray_query/vktRayQueryTests.cpp +++ b/external/vulkancts/modules/vulkan/ray_query/vktRayQueryTests.cpp @@ -22,10 +22,10 @@ *//*--------------------------------------------------------------------*/ #include "vktRayQueryTests.hpp" - #include "vktRayQueryBuiltinTests.hpp" #include "vktRayQueryTraversalControlTests.hpp" #include "vktRayQueryAccelerationStructuresTests.hpp" +#include "vktRayQueryWatertightnessTests.hpp" #include "deUniquePtr.hpp" @@ -44,6 +44,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx) group->addChild(createTraversalControlTests(testCtx)); group->addChild(createAccelerationStructuresTests(testCtx)); group->addChild(createAdvancedTests(testCtx)); + group->addChild(createWatertightnessTests(testCtx)); return group.release(); } diff --git a/external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.cpp b/external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.cpp new file mode 100644 index 0000000..027213b --- /dev/null +++ b/external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.cpp @@ -0,0 +1,2349 @@ +/*------------------------------------------------------------------------ + * 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 Query Builtin tests + *//*--------------------------------------------------------------------*/ + +#include "vktRayQueryWatertightnessTests.hpp" + +#include "vkDefs.hpp" + +#include "vktTestCase.hpp" +#include "vktTestGroupUtil.hpp" +#include "vkCmdUtil.hpp" +#include "vkObjUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkBarrierUtil.hpp" +#include "vkBufferWithMemory.hpp" +#include "vkImageWithMemory.hpp" +#include "vkTypeUtil.hpp" +#include "vkImageUtil.hpp" +#include "deRandom.hpp" +#include "tcuTexture.hpp" +#include "tcuTextureUtil.hpp" +#include "tcuTestLog.hpp" +#include "tcuImageCompare.hpp" +#include "tcuCommandLine.hpp" + +#include "vkRayTracingUtil.hpp" + +namespace vkt +{ +namespace RayQuery +{ +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; + +enum TestType +{ + TEST_TYPE_NO_MISS = 0, + TEST_TYPE_SINGLE_HIT, +}; + +enum GeomType +{ + GEOM_TYPE_TRIANGLES, + GEOM_TYPE_AABBS, + GEOM_TYPE_LAST, +}; + +const deUint32 TEST_WIDTH = 256u; +const deUint32 TEST_HEIGHT = 256u; +const float MIN_AABB_SIDE_LENGTH = 1e-6f; +const float MIN_TRIANGLE_EDGE_LENGTH = 1.0f / float(10 * TEST_WIDTH * TEST_HEIGHT); +const float MIN_TRIANGLE_AREA_SIZE = 1.0f / float(10 * TEST_WIDTH * TEST_HEIGHT); + +struct TestParams; + +typedef void (*CheckSupportFunc)(Context& context, const TestParams& testParams); +typedef void (*InitProgramsFunc)(SourceCollections& programCollection, const TestParams& testParams); +typedef const std::string (*ShaderBodyTextFunc)(const TestParams& testParams); + +class PipelineConfiguration +{ +public: + PipelineConfiguration () {}; + virtual ~PipelineConfiguration () {}; + + virtual void initConfiguration (Context& context, + TestParams& testParams) = 0; + virtual void fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer commandBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) = 0; +}; + +class TestConfiguration +{ +public: + TestConfiguration () + : m_bottomAccelerationStructures () + , m_topAccelerationStructure () + , m_expected () + { + } + virtual ~TestConfiguration () + { + } + + virtual const VkAccelerationStructureKHR* initAccelerationStructures (Context& context, + TestParams& testParams, + VkCommandBuffer cmdBuffer) = 0; + virtual bool verify (BufferWithMemory* resultBuffer, + Context& context, + TestParams& testParams) = 0; + +protected: + std::vector> m_bottomAccelerationStructures; + de::SharedPtr m_topAccelerationStructure; + std::vector m_expected; +}; + +struct TestParams +{ + deUint32 width; + deUint32 height; + deUint32 depth; + deUint32 randomSeed; + TestType testType; + VkShaderStageFlagBits stage; + GeomType geomType; + deUint32 squaresGroupCount; + deUint32 geometriesGroupCount; + deUint32 instancesGroupCount; + VkFormat format; + CheckSupportFunc pipelineCheckSupport; + InitProgramsFunc pipelineInitPrograms; + ShaderBodyTextFunc testConfigShaderBodyText; +}; + +deUint32 getShaderGroupHandleSize (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice) +{ + de::MovePtr rayTracingPropertiesKHR; + + rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice); + + return rayTracingPropertiesKHR->getShaderGroupHandleSize(); +} + +deUint32 getShaderGroupBaseAlignment (const InstanceInterface& vki, + const VkPhysicalDevice physicalDevice) +{ + de::MovePtr rayTracingPropertiesKHR; + + rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice); + + return rayTracingPropertiesKHR->getShaderGroupBaseAlignment(); +} + +VkBuffer getVkBuffer (const de::MovePtr& buffer) +{ + VkBuffer result = (buffer.get() == DE_NULL) ? DE_NULL : buffer->get(); + + return result; +} + +VkStridedDeviceAddressRegionKHR makeStridedDeviceAddressRegion (const DeviceInterface& vkd, const VkDevice device, VkBuffer buffer, VkDeviceSize size) +{ + const VkDeviceSize sizeFixed = ((buffer == DE_NULL) ? 0ull : size); + + return makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, buffer, 0), 0, sizeFixed); +} + +VkImageCreateInfo makeImageCreateInfo (VkFormat format, + deUint32 width, + deUint32 height, + deUint32 depth, + VkImageType imageType = VK_IMAGE_TYPE_3D, + VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) +{ + const VkImageCreateInfo imageCreateInfo = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageCreateFlags)0u, // VkImageCreateFlags flags; + imageType, // VkImageType imageType; + format, // VkFormat format; + makeExtent3D(width, height, depth), // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usageFlags, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; + }; + + return imageCreateInfo; +} + +Move makeComputePipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const VkShaderModule shaderModule) +{ + const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; + shaderModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + const VkComputePipelineCreateInfo pipelineCreateInfo = + { + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineCreateFlags flags; + pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage; + pipelineLayout, // VkPipelineLayout layout; + DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + + return createComputePipeline(vk, device, DE_NULL , &pipelineCreateInfo); +} + +static const std::string getMissPassthrough (void) +{ + const std::string missPassthrough = + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n" + "\n" + "void main()\n" + "{\n" + "}\n"; + + return missPassthrough; +} + +static const std::string getHitPassthrough (void) +{ + const std::string hitPassthrough = + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "hitAttributeEXT vec3 attribs;\n" + "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n" + "\n" + "void main()\n" + "{\n" + "}\n"; + + return hitPassthrough; +} + +static const std::string getGraphicsPassthrough (void) +{ + std::ostringstream src; + + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "\n" + << "void main(void)\n" + << "{\n" + << "}\n"; + + return src.str(); +} + +static const std::string getVertexPassthrough (void) +{ + std::ostringstream src; + + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_position;\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_Position = in_position;\n" + << "}\n"; + + return src.str(); +} + +static inline tcu::Vec2 mixVec2 (const tcu::Vec2& a, const tcu::Vec2& b, const float alpha) +{ + const tcu::Vec2 result = a * alpha + b * (1.0f - alpha); + + return result; +} + +static inline tcu::Vec2 mixCoordsVec2 (const tcu::Vec2& a, const tcu::Vec2& b, const float alpha, const float beta) +{ + const tcu::Vec2 result = tcu::Vec2(deFloatMix(a.x(), b.x(), alpha), deFloatMix(a.y(), b.y(), beta)); + + return result; +} + +inline float triangleEdgeLength (const tcu::Vec2& vertexA, const tcu::Vec2& vertexB) +{ + const float abx = vertexA.x() - vertexB.x(); + const float aby = vertexA.y() - vertexB.y(); + const float abq = abx * abx + aby * aby; + const float ab = deFloatSqrt(abq); + + return ab; +} + +inline float triangleArea (const float edgeALen, const float edgeBLen, const float edgeCLen) +{ + const float s = (edgeALen + edgeBLen + edgeCLen) / 2.0f; + const float q = s * (s - edgeALen) * (s - edgeBLen) * (s - edgeCLen); + + if (q <= 0.0f) + return 0.0f; + + return deFloatSqrt(q); +} + +class GraphicsConfiguration : public PipelineConfiguration +{ +public: + static void checkSupport (Context& context, + const TestParams& testParams); + static void initPrograms (SourceCollections& programCollection, + const TestParams& testParams); + + GraphicsConfiguration (); + virtual ~GraphicsConfiguration () {}; + + void initVertexBuffer (Context& context, + TestParams& testParams); + Move makeGraphicsPipeline (Context& context, + TestParams& testParams); + virtual void initConfiguration (Context& context, + TestParams& testParams) override; + virtual void fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer commandBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) override; + +private: + Move m_descriptorSetLayout; + Move m_descriptorPool; + Move m_descriptorSet; + + VkFormat m_framebufferFormat; + Move m_framebufferImage; + de::MovePtr m_framebufferImageAlloc; + Move m_framebufferAttachment; + + Move m_vertShaderModule; + Move m_geomShaderModule; + Move m_tescShaderModule; + Move m_teseShaderModule; + Move m_fragShaderModule; + + Move m_renderPass; + Move m_framebuffer; + Move m_pipelineLayout; + Move m_pipeline; + + deUint32 m_vertexCount; + Move m_vertexBuffer; + de::MovePtr m_vertexBufferAlloc; +}; + +GraphicsConfiguration::GraphicsConfiguration() + : PipelineConfiguration () + , m_descriptorSetLayout () + , m_descriptorPool () + , m_descriptorSet () + , m_framebufferFormat (VK_FORMAT_R8G8B8A8_UNORM) + , m_framebufferImage () + , m_framebufferImageAlloc () + , m_framebufferAttachment () + , m_vertShaderModule () + , m_geomShaderModule () + , m_tescShaderModule () + , m_teseShaderModule () + , m_fragShaderModule () + , m_renderPass () + , m_framebuffer () + , m_pipelineLayout () + , m_pipeline () + , m_vertexCount (0) + , m_vertexBuffer () + , m_vertexBufferAlloc () +{ +} + +void GraphicsConfiguration::checkSupport (Context& context, + const TestParams& testParams) +{ + switch (testParams.stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + break; + + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + { + context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER); + + break; + } + + case VK_SHADER_STAGE_GEOMETRY_BIT: + { + context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER); + + break; + } + + case VK_SHADER_STAGE_FRAGMENT_BIT: + break; + + default: + TCU_THROW(InternalError, "Unknown stage"); + } +} + +void GraphicsConfiguration::initPrograms (SourceCollections& programCollection, + const TestParams& testParams) +{ + const std::string testShaderBody = testParams.testConfigShaderBodyText(testParams); + + switch (testParams.stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + { + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_ray_query : require\n" + << "#extension GL_EXT_ray_tracing : require\n" + << "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + << "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + << "\n" + << "void testFunc(ivec3 pos, ivec3 size)\n" + << "{\n" + << testShaderBody + << "}\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " const int posId = int(gl_VertexIndex / 3);\n" + << " const int vertId = int(gl_VertexIndex % 3);\n" + << " const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n" + << " const ivec3 pos = ivec3(posId % size.x, posId / size.x, 0);\n" + << "\n" + << " if (vertId == 0)\n" + << " {\n" + << " testFunc(pos, size);\n" + << " }\n" + << "}\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); + } + + programCollection.glslSources.add("frag") << glu::FragmentSource(getGraphicsPassthrough()); + + break; + } + + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + { + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_position;\n" + << "out gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "};\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_Position = in_position;\n" + << "}\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); + } + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_tessellation_shader : require\n" + << "#extension GL_EXT_ray_query : require\n" + << "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + << "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + << "in gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "} gl_in[];\n" + << "layout(vertices = 4) out;\n" + << "out gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "} gl_out[];\n" + << "\n" + << "void testFunc(ivec3 pos, ivec3 size)\n" + << "{\n" + << testShaderBody + << "}\n" + << "\n" + << "void main(void)\n" + << "{\n" + << "\n" + << " if (gl_InvocationID == 0)\n" + << " {\n" + << " const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n" + << " for (int y = 0; y < size.y; y++)\n" + << " for (int x = 0; x < size.x; x++)\n" + << " {\n" + << " const ivec3 pos = ivec3(x, y, 0);\n" + << " testFunc(pos, size);\n" + << " }\n" + << " }\n" + << "\n" + << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" + << " gl_TessLevelInner[0] = 1;\n" + << " gl_TessLevelInner[1] = 1;\n" + << " gl_TessLevelOuter[gl_InvocationID] = 1;\n" + << "}\n"; + + programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); + } + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_tessellation_shader : require\n" + << "layout(quads, equal_spacing, ccw) in;\n" + << "in gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "} gl_in[];\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_Position = gl_in[0].gl_Position;\n" + << "}\n"; + + programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); + } + + break; + } + + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + { + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_position;\n" + << "out gl_PerVertex" + << "{\n" + << " vec4 gl_Position;\n" + << "};\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_Position = in_position;\n" + << "}\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); + } + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_tessellation_shader : require\n" + << "in gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "} gl_in[];\n" + << "layout(vertices = 4) out;\n" + << "out gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "} gl_out[];\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" + << " gl_TessLevelInner[0] = 1;\n" + << " gl_TessLevelInner[1] = 1;\n" + << " gl_TessLevelOuter[gl_InvocationID] = 1;\n" + << "}\n"; + + programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); + } + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_tessellation_shader : require\n" + << "#extension GL_EXT_ray_query : require\n" + << "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + << "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + << "layout(quads, equal_spacing, ccw) in;\n" + << "in gl_PerVertex\n" + << "{\n" + << " vec4 gl_Position;\n" + << "} gl_in[];\n" + << "\n" + << "void testFunc(ivec3 pos, ivec3 size)\n" + << "{\n" + << testShaderBody + << "}\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n" + << "\n" + << " if (gl_PrimitiveID == 0)\n" + << " {\n" + << " const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n" + << " for (int y = 0; y < size.y; y++)\n" + << " for (int x = 0; x < size.x; x++)\n" + << " {\n" + << " const ivec3 pos = ivec3(x, y, 0);\n" + << " testFunc(pos, size);\n" + << " }\n" + << " }\n" + << "\n" + << " gl_Position = gl_in[0].gl_Position;\n" + << "}\n"; + + programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); + } + + break; + } + + case VK_SHADER_STAGE_GEOMETRY_BIT: + { + programCollection.glslSources.add("vert") << glu::VertexSource(getVertexPassthrough()); + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_ray_query : require\n" + << "layout(triangles) in;\n" + << "layout(points, max_vertices = 1) out;\n" + << "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + << "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + << "\n" + << "void testFunc(ivec3 pos, ivec3 size)\n" + << "{\n" + << testShaderBody + << "}\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " const int posId = int(gl_PrimitiveIDIn);\n" + << " const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n" + << " const ivec3 pos = ivec3(posId % size.x, posId / size.x, 0);\n" + << "\n" + << " testFunc(pos, size);\n" + << "}\n"; + + programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()); + } + + break; + } + + case VK_SHADER_STAGE_FRAGMENT_BIT: + { + programCollection.glslSources.add("vert") << glu::VertexSource(getVertexPassthrough()); + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n" + << "#extension GL_EXT_ray_query : require\n" + << "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + << "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + << "\n" + << "void testFunc(ivec3 pos, ivec3 size)\n" + << "{\n" + << testShaderBody + << "}\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n" + << " const ivec3 pos = ivec3(int(gl_FragCoord.x - 0.5f), int(gl_FragCoord.y - 0.5f), 0);\n" + << "\n" + << " testFunc(pos, size);\n" + << "}\n"; + + programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); + } + + break; + } + + default: + TCU_THROW(InternalError, "Unknown stage"); + } +} + +void GraphicsConfiguration::initVertexBuffer (Context& context, + TestParams& testParams) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const deUint32 width = testParams.width; + const deUint32 height = testParams.height; + Allocator& allocator = context.getDefaultAllocator(); + std::vector vertices; + + switch (testParams.stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + { + const float z = 0.0f; + const float w = 1.0f; + + vertices.reserve(3 * height * width); + + for (deUint32 y = 0; y < height; ++y) + for (deUint32 x = 0; x < width; ++x) + { + const float x0 = float(x + 0) / float(width); + const float y0 = float(y + 0) / float(height); + const float x1 = float(x + 1) / float(width); + const float y1 = float(y + 1) / float(height); + const float xm = (x0 + x1) / 2.0f; + const float ym = (y0 + y1) / 2.0f; + + vertices.push_back(tcu::Vec4(x0, y0, z, w)); + vertices.push_back(tcu::Vec4(xm, y1, z, w)); + vertices.push_back(tcu::Vec4(x1, ym, z, w)); + } + + break; + } + + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + { + const float z = 0.0f; + const float w = 1.0f; + const tcu::Vec4 a = tcu::Vec4(-1.0f, -1.0f, z, w); + const tcu::Vec4 b = tcu::Vec4(+1.0f, -1.0f, z, w); + const tcu::Vec4 c = tcu::Vec4(+1.0f, +1.0f, z, w); + const tcu::Vec4 d = tcu::Vec4(-1.0f, +1.0f, z, w); + + vertices.push_back(a); + vertices.push_back(b); + vertices.push_back(c); + vertices.push_back(d); + + break; + } + + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + { + const float z = 0.0f; + const float w = 1.0f; + const tcu::Vec4 a = tcu::Vec4(-1.0f, -1.0f, z, w); + const tcu::Vec4 b = tcu::Vec4(+1.0f, -1.0f, z, w); + const tcu::Vec4 c = tcu::Vec4(+1.0f, +1.0f, z, w); + const tcu::Vec4 d = tcu::Vec4(-1.0f, +1.0f, z, w); + + vertices.push_back(a); + vertices.push_back(b); + vertices.push_back(c); + vertices.push_back(d); + + break; + } + + case VK_SHADER_STAGE_GEOMETRY_BIT: + { + const float z = 0.0f; + const float w = 1.0f; + + vertices.reserve(3 * height * width); + + for (deUint32 y = 0; y < height; ++y) + for (deUint32 x = 0; x < width; ++x) + { + const float x0 = float(x + 0) / float(width); + const float y0 = float(y + 0) / float(height); + const float x1 = float(x + 1) / float(width); + const float y1 = float(y + 1) / float(height); + const float xm = (x0 + x1) / 2.0f; + const float ym = (y0 + y1) / 2.0f; + + vertices.push_back(tcu::Vec4(x0, y0, z, w)); + vertices.push_back(tcu::Vec4(xm, y1, z, w)); + vertices.push_back(tcu::Vec4(x1, ym, z, w)); + } + + break; + } + + case VK_SHADER_STAGE_FRAGMENT_BIT: + { + const float z = 1.0f; + const float w = 1.0f; + const tcu::Vec4 a = tcu::Vec4(-1.0f, -1.0f, z, w); + const tcu::Vec4 b = tcu::Vec4(+1.0f, -1.0f, z, w); + const tcu::Vec4 c = tcu::Vec4(-1.0f, +1.0f, z, w); + const tcu::Vec4 d = tcu::Vec4(+1.0f, +1.0f, z, w); + + vertices.push_back(a); + vertices.push_back(b); + vertices.push_back(c); + + vertices.push_back(b); + vertices.push_back(c); + vertices.push_back(d); + + break; + } + + default: + TCU_THROW(InternalError, "Unknown stage"); + + } + + // Initialize vertex buffer + { + const VkDeviceSize vertexBufferSize = sizeof(vertices[0][0]) * vertices[0].SIZE * vertices.size(); + const VkBufferCreateInfo vertexBufferCreateInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + + m_vertexCount = static_cast(vertices.size()); + m_vertexBuffer = createBuffer(vkd, device, &vertexBufferCreateInfo); + m_vertexBufferAlloc = bindBuffer(vkd, device, allocator, *m_vertexBuffer, vk::MemoryRequirement::HostVisible); + + deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), (size_t)vertexBufferSize); + flushAlloc(vkd, device, *m_vertexBufferAlloc); + } +} + +Move GraphicsConfiguration::makeGraphicsPipeline (Context& context, + TestParams& testParams) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const bool tessStageTest = (testParams.stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || testParams.stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); + const VkPrimitiveTopology topology = tessStageTest ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + const deUint32 patchControlPoints = tessStageTest ? 4 : 0; + const std::vector viewports (1, makeViewport(testParams.width, testParams.height)); + const std::vector scissors (1, makeRect2D(testParams.width, testParams.height)); + + return vk::makeGraphicsPipeline (vkd, + device, + *m_pipelineLayout, + *m_vertShaderModule, + *m_tescShaderModule, + *m_teseShaderModule, + *m_geomShaderModule, + *m_fragShaderModule, + *m_renderPass, + viewports, + scissors, + topology, + 0, + patchControlPoints); +} + +void GraphicsConfiguration::initConfiguration (Context& context, + TestParams& testParams) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + Allocator& allocator = context.getDefaultAllocator(); + vk::BinaryCollection& collection = context.getBinaryCollection(); + VkShaderStageFlags shaders = static_cast(0); + deUint32 shaderCount = 0; + + if (collection.contains("vert")) shaders |= VK_SHADER_STAGE_VERTEX_BIT; + if (collection.contains("geom")) shaders |= VK_SHADER_STAGE_GEOMETRY_BIT; + if (collection.contains("tesc")) shaders |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + if (collection.contains("tese")) shaders |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + if (collection.contains("frag")) shaders |= VK_SHADER_STAGE_FRAGMENT_BIT; + + for (BinaryCollection::Iterator it = collection.begin(); it != collection.end(); ++it) + shaderCount++; + + if (shaderCount != (deUint32)dePop32(shaders)) + TCU_THROW(InternalError, "Unused shaders detected in the collection"); + + if (0 != (shaders & VK_SHADER_STAGE_VERTEX_BIT)) m_vertShaderModule = createShaderModule(vkd, device, collection.get("vert"), 0); + if (0 != (shaders & VK_SHADER_STAGE_GEOMETRY_BIT)) m_geomShaderModule = createShaderModule(vkd, device, collection.get("geom"), 0); + if (0 != (shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)) m_tescShaderModule = createShaderModule(vkd, device, collection.get("tesc"), 0); + if (0 != (shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) m_teseShaderModule = createShaderModule(vkd, device, collection.get("tese"), 0); + if (0 != (shaders & VK_SHADER_STAGE_FRAGMENT_BIT)) m_fragShaderModule = createShaderModule(vkd, device, collection.get("frag"), 0); + + m_descriptorSetLayout = DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_ALL_GRAPHICS) + .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL_GRAPHICS) + .build(vkd, device); + m_descriptorPool = DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) + .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + m_descriptorSet = makeDescriptorSet (vkd, device, *m_descriptorPool, *m_descriptorSetLayout); + m_framebufferImage = makeImage (vkd, device, makeImageCreateInfo(m_framebufferFormat, testParams.width, testParams.height, 1u, VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)); + m_framebufferImageAlloc = bindImage (vkd, device, allocator, *m_framebufferImage, MemoryRequirement::Any); + m_framebufferAttachment = makeImageView (vkd, device, *m_framebufferImage, VK_IMAGE_VIEW_TYPE_2D, m_framebufferFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); + m_renderPass = makeRenderPass (vkd, device, m_framebufferFormat); + m_framebuffer = makeFramebuffer (vkd, device, *m_renderPass, *m_framebufferAttachment, testParams.width, testParams.height); + m_pipelineLayout = makePipelineLayout (vkd, device, m_descriptorSetLayout.get()); + m_pipeline = makeGraphicsPipeline (context, testParams); + + initVertexBuffer(context, testParams); +} + +void GraphicsConfiguration::fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer cmdBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const VkDeviceSize vertexBufferOffset = 0; + const VkWriteDescriptorSetAccelerationStructureKHR rayQueryAccelerationStructureWriteDescriptorSet = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + 1u, // deUint32 accelerationStructureCount; + rayQueryTopAccelerationStructurePtr, // const VkAccelerationStructureKHR* pAccelerationStructures; + }; + + DescriptorSetUpdateBuilder() + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo) + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet) + .update(vkd, device); + + vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL); + vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); + vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset); + + beginRenderPass(vkd, cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, testParams.width, testParams.height), tcu::UVec4()); + + vkd.cmdDraw(cmdBuffer, m_vertexCount, 1u, 0u, 0u); + + endRenderPass(vkd, cmdBuffer); +} + +class ComputeConfiguration : public PipelineConfiguration +{ +public: + ComputeConfiguration (); + virtual ~ComputeConfiguration () {}; + + static void checkSupport (Context& context, + const TestParams& testParams); + static void initPrograms (SourceCollections& programCollection, + const TestParams& testParams); + + virtual void initConfiguration (Context& context, + TestParams& testParams) override; + virtual void fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer commandBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) override; + +protected: + Move m_descriptorSetLayout; + Move m_descriptorPool; + Move m_descriptorSet; + Move m_pipelineLayout; + + Move m_shaderModule; + + Move m_pipeline; +}; + +ComputeConfiguration::ComputeConfiguration () + : PipelineConfiguration () + , m_descriptorSetLayout () + , m_descriptorPool () + , m_descriptorSet () + , m_pipelineLayout () + + , m_shaderModule () + + , m_pipeline () +{ +} + +void ComputeConfiguration::checkSupport (Context& context, + const TestParams& testParams) +{ + DE_UNREF(context); + DE_UNREF(testParams); +} + +void ComputeConfiguration::initPrograms (SourceCollections& programCollection, + const TestParams& testParams) +{ + const std::string testShaderBody = testParams.testConfigShaderBodyText(testParams); + const std::string testBody = + " ivec3 pos = ivec3(gl_WorkGroupID);\n" + " ivec3 size = ivec3(gl_NumWorkGroups);\n" + + testShaderBody; + + switch (testParams.stage) + { + case VK_SHADER_STAGE_COMPUTE_BIT: + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_query : require\n" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + "}\n"; + + programCollection.glslSources.add("comp") << glu::ComputeSource(updateRayTracingGLSL(css.str())); + + break; + } + + default: + TCU_THROW(InternalError, "Unknown stage"); + } +} + +void ComputeConfiguration::initConfiguration (Context& context, + TestParams& testParams) +{ + DE_UNREF(testParams); + + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + vk::BinaryCollection& collection = context.getBinaryCollection(); + + m_descriptorSetLayout = DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) + .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_COMPUTE_BIT) + .build(vkd, device); + m_descriptorPool = DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) + .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + m_descriptorSet = makeDescriptorSet(vkd, device, *m_descriptorPool, *m_descriptorSetLayout); + m_pipelineLayout = makePipelineLayout(vkd, device, m_descriptorSetLayout.get()); + m_shaderModule = createShaderModule(vkd, device, collection.get("comp"), 0); + m_pipeline = makeComputePipeline(vkd, device, *m_pipelineLayout, *m_shaderModule); +} + +void ComputeConfiguration::fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer cmdBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const VkWriteDescriptorSetAccelerationStructureKHR rayQueryAccelerationStructureWriteDescriptorSet = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + 1u, // deUint32 accelerationStructureCount; + rayQueryTopAccelerationStructurePtr, // const VkAccelerationStructureKHR* pAccelerationStructures; + }; + + DescriptorSetUpdateBuilder() + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo) + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet) + .update(vkd, device); + + vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL); + + vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline.get()); + + vkd.cmdDispatch(cmdBuffer, testParams.width, testParams.height, 1); +} + +class RayTracingConfiguration : public PipelineConfiguration +{ +public: + RayTracingConfiguration (); + virtual ~RayTracingConfiguration () {}; + + static void checkSupport (Context& context, + const TestParams& testParams); + static void initPrograms (SourceCollections& programCollection, + const TestParams& testParams); + + virtual void initConfiguration (Context& context, + TestParams& testParams) override; + virtual void fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer commandBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) override; + +protected: + de::MovePtr createShaderBindingTable (const InstanceInterface& vki, + const DeviceInterface& vkd, + const VkDevice device, + const VkPhysicalDevice physicalDevice, + const VkPipeline pipeline, + Allocator& allocator, + de::MovePtr& rayTracingPipeline, + const deUint32 group); + +protected: + deUint32 m_shaders; + deUint32 m_raygenShaderGroup; + deUint32 m_missShaderGroup; + deUint32 m_hitShaderGroup; + deUint32 m_callableShaderGroup; + deUint32 m_shaderGroupCount; + + Move m_descriptorSetLayout; + Move m_descriptorPool; + Move m_descriptorSet; + Move m_pipelineLayout; + + de::MovePtr m_rayTracingPipeline; + Move m_pipeline; + + de::MovePtr m_raygenShaderBindingTable; + de::MovePtr m_hitShaderBindingTable; + de::MovePtr m_missShaderBindingTable; + de::MovePtr m_callableShaderBindingTable; + + VkStridedDeviceAddressRegionKHR m_raygenShaderBindingTableRegion; + VkStridedDeviceAddressRegionKHR m_missShaderBindingTableRegion; + VkStridedDeviceAddressRegionKHR m_hitShaderBindingTableRegion; + VkStridedDeviceAddressRegionKHR m_callableShaderBindingTableRegion; + + de::SharedPtr m_bottomLevelAccelerationStructure; + de::SharedPtr m_topLevelAccelerationStructure; +}; + +RayTracingConfiguration::RayTracingConfiguration() + : m_shaders (0) + , m_raygenShaderGroup (~0u) + , m_missShaderGroup (~0u) + , m_hitShaderGroup (~0u) + , m_callableShaderGroup (~0u) + , m_shaderGroupCount (0) + + , m_descriptorSetLayout () + , m_descriptorPool () + , m_descriptorSet () + , m_pipelineLayout () + + , m_rayTracingPipeline () + , m_pipeline () + + , m_raygenShaderBindingTable () + , m_hitShaderBindingTable () + , m_missShaderBindingTable () + , m_callableShaderBindingTable () + + , m_raygenShaderBindingTableRegion () + , m_missShaderBindingTableRegion () + , m_hitShaderBindingTableRegion () + , m_callableShaderBindingTableRegion () + + , m_bottomLevelAccelerationStructure () + , m_topLevelAccelerationStructure () +{ +} + +void RayTracingConfiguration::checkSupport (Context& context, + const TestParams& testParams) +{ + DE_UNREF(testParams); + + const VkPhysicalDeviceRayTracingFeaturesKHR& rayTracingFeaturesKHR = context.getRayTracingFeatures(); + + if (rayTracingFeaturesKHR.rayTracing == DE_FALSE) + TCU_THROW(NotSupportedError, "Requires rayTracingFeaturesKHR.rayTracing"); +} + +void RayTracingConfiguration::initPrograms (SourceCollections& programCollection, + const TestParams& testParams) +{ + const std::string testShaderBody = testParams.testConfigShaderBodyText(testParams); + const std::string testBody = + " ivec3 pos = ivec3(gl_LaunchIDEXT);\n" + " ivec3 size = ivec3(gl_LaunchSizeEXT);\n" + + testShaderBody; + + switch (testParams.stage) + { + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + "}\n"; + + programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())); + + break; + } + + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + { + programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())); + + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "hitAttributeEXT vec3 attribs;\n" + "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + "}\n"; + + programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())); + } + + programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())); + + break; + } + + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + { + programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())); + + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n" + "hitAttributeEXT vec3 attribs;\n" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + "}\n"; + + programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())); + } + + programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())); + + break; + } + + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + { + programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())); + + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "hitAttributeEXT vec3 hitAttribute;\n" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + " hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n" + " reportIntersectionEXT(1.0f, 0);\n" + "}\n"; + + programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())); + } + + programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())); + + break; + } + + case VK_SHADER_STAGE_MISS_BIT_KHR: + { + programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())); + + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + "}\n"; + + programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())); + } + + programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())); + + break; + } + + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + { + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "layout(location = 0) callableDataEXT float dummy;" + "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n" + "\n" + "void main()\n" + "{\n" + " executeCallableEXT(0, 0);\n" + "}\n"; + + programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())); + } + + { + std::stringstream css; + css << + "#version 460 core\n" + "#extension GL_EXT_ray_tracing : require\n" + "#extension GL_EXT_ray_query : require\n" + "layout(location = 0) callableDataInEXT float dummy;" + "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n" + "layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n" + "\n" + "void main()\n" + "{\n" + << testBody << + "}\n"; + + programCollection.glslSources.add("call") << glu::CallableSource(updateRayTracingGLSL(css.str())); + } + + programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())); + programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())); + + break; + } + + default: + TCU_THROW(InternalError, "Unknown stage"); + } +} + +de::MovePtr RayTracingConfiguration::createShaderBindingTable (const InstanceInterface& vki, + const DeviceInterface& vkd, + const VkDevice device, + const VkPhysicalDevice physicalDevice, + const VkPipeline pipeline, + Allocator& allocator, + de::MovePtr& rayTracingPipeline, + const deUint32 group) +{ + de::MovePtr shaderBindingTable; + + if (group < m_shaderGroupCount) + { + const deUint32 shaderGroupHandleSize = getShaderGroupHandleSize(vki, physicalDevice); + const deUint32 shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice); + + shaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, 1u); + } + + return shaderBindingTable; +} + +void RayTracingConfiguration::initConfiguration (Context& context, + TestParams& testParams) +{ + DE_UNREF(testParams); + + const InstanceInterface& vki = context.getInstanceInterface(); + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); + vk::BinaryCollection& collection = context.getBinaryCollection(); + Allocator& allocator = context.getDefaultAllocator(); + const deUint32 shaderGroupHandleSize = getShaderGroupHandleSize(vki, physicalDevice); + const VkShaderStageFlags hitStages = VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR; + deUint32 shaderCount = 0; + + m_shaderGroupCount = 0; + + if (collection.contains("rgen")) m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR; + if (collection.contains("ahit")) m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR; + if (collection.contains("chit")) m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + if (collection.contains("miss")) m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR; + if (collection.contains("sect")) m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR; + if (collection.contains("call")) m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR; + + for (BinaryCollection::Iterator it = collection.begin(); it != collection.end(); ++it) + shaderCount++; + + if (shaderCount != (deUint32)dePop32(m_shaders)) + TCU_THROW(InternalError, "Unused shaders detected in the collection"); + + if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR)) + m_raygenShaderGroup = m_shaderGroupCount++; + + if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR)) + m_missShaderGroup = m_shaderGroupCount++; + + if (0 != (m_shaders & hitStages)) + m_hitShaderGroup = m_shaderGroupCount++; + + if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR)) + m_callableShaderGroup = m_shaderGroupCount++; + + m_rayTracingPipeline = de::newMovePtr(); + + m_descriptorSetLayout = DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES) + .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES) + .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES) + .build(vkd, device); + m_descriptorPool = DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) + .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) + .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + m_descriptorSet = makeDescriptorSet(vkd, device, *m_descriptorPool, *m_descriptorSetLayout); + + if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR)) m_rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR , createShaderModule(vkd, device, collection.get("rgen"), 0), m_raygenShaderGroup); + if (0 != (m_shaders & VK_SHADER_STAGE_ANY_HIT_BIT_KHR)) m_rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR , createShaderModule(vkd, device, collection.get("ahit"), 0), m_hitShaderGroup); + if (0 != (m_shaders & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)) m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR , createShaderModule(vkd, device, collection.get("chit"), 0), m_hitShaderGroup); + if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR)) m_rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR , createShaderModule(vkd, device, collection.get("miss"), 0), m_missShaderGroup); + if (0 != (m_shaders & VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) m_rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR , createShaderModule(vkd, device, collection.get("sect"), 0), m_hitShaderGroup); + if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR)) m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR , createShaderModule(vkd, device, collection.get("call"), 0), m_callableShaderGroup); + + m_pipelineLayout = makePipelineLayout(vkd, device, m_descriptorSetLayout.get()); + m_pipeline = m_rayTracingPipeline->createPipeline(vkd, device, *m_pipelineLayout); + + m_raygenShaderBindingTable = createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_raygenShaderGroup); + m_missShaderBindingTable = createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_missShaderGroup); + m_hitShaderBindingTable = createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_hitShaderGroup); + m_callableShaderBindingTable = createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_callableShaderGroup); + + m_raygenShaderBindingTableRegion = makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_raygenShaderBindingTable), shaderGroupHandleSize); + m_missShaderBindingTableRegion = makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_missShaderBindingTable), shaderGroupHandleSize); + m_hitShaderBindingTableRegion = makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_hitShaderBindingTable), shaderGroupHandleSize); + m_callableShaderBindingTableRegion = makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_callableShaderBindingTable), shaderGroupHandleSize); +} + +void RayTracingConfiguration::fillCommandBuffer (Context& context, + TestParams& testParams, + VkCommandBuffer commandBuffer, + const VkAccelerationStructureKHR* rayQueryTopAccelerationStructurePtr, + const VkDescriptorImageInfo& resultImageInfo) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + Allocator& allocator = context.getDefaultAllocator(); + de::MovePtr bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure(); + de::MovePtr topLevelAccelerationStructure = makeTopLevelAccelerationStructure(); + + m_bottomLevelAccelerationStructure = de::SharedPtr(bottomLevelAccelerationStructure.release()); + m_bottomLevelAccelerationStructure->setDefaultGeometryData(testParams.stage); + m_bottomLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator); + + m_topLevelAccelerationStructure = de::SharedPtr(topLevelAccelerationStructure.release()); + m_topLevelAccelerationStructure->setInstanceCount(1); + m_topLevelAccelerationStructure->addInstance(m_bottomLevelAccelerationStructure); + m_topLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator); + + const TopLevelAccelerationStructure* topLevelAccelerationStructurePtr = m_topLevelAccelerationStructure.get(); + const VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + 1u, // deUint32 accelerationStructureCount; + topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures; + }; + const VkWriteDescriptorSetAccelerationStructureKHR rayQueryAccelerationStructureWriteDescriptorSet = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType; + DE_NULL, // const void* pNext; + 1u, // deUint32 accelerationStructureCount; + rayQueryTopAccelerationStructurePtr, // const VkAccelerationStructureKHR* pAccelerationStructures; + }; + + DescriptorSetUpdateBuilder() + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo) + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet) + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet) + .update(vkd, device); + + vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL); + + vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, m_pipeline.get()); + + cmdTraceRays(vkd, + commandBuffer, + &m_raygenShaderBindingTableRegion, + &m_missShaderBindingTableRegion, + &m_hitShaderBindingTableRegion, + &m_callableShaderBindingTableRegion, + testParams.width, testParams.height, 1); +} + + +const std::string getShaderBodyText (const TestParams& testParams) +{ + if (testParams.geomType == GEOM_TYPE_AABBS) + { + const std::string result = + " uint rayFlags = 0;\n" + " uint cullMask = 0xFF;\n" + " float tmin = 0.0;\n" + " float tmax = 9.0;\n" + " vec3 origin = vec3((float(pos.x) + 0.5f) / float(size.x), (float(pos.y) + 0.5f) / float(size.y), 0.0);\n" + " vec3 direct = vec3(0.0, 0.0, -1.0);\n" + " uint count = 0;\n" + " rayQueryEXT rayQuery;\n" + "\n" + " rayQueryInitializeEXT(rayQuery, rayQueryTopLevelAccelerationStructure, rayFlags, cullMask, origin, tmin, direct, tmax);\n" + "\n" + " while(rayQueryProceedEXT(rayQuery))\n" + " {\n" + " if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCandidateIntersectionAABBEXT)\n" + " {\n" + " rayQueryGenerateIntersectionEXT(rayQuery, 0.5f);\n" + " count++;\n" + " }\n" + " }\n" + " imageStore(result, pos, ivec4(count, 0, 0, 0));\n" + "\n"; + + return result; + } + else if (testParams.geomType == GEOM_TYPE_TRIANGLES) + { + const std::string result = + " uint rayFlags = gl_RayFlagsNoOpaqueEXT;\n" + " uint cullMask = 0xFF;\n" + " float tmin = 0.0;\n" + " float tmax = 9.0;\n" + " vec3 origin = vec3((float(pos.x) + 0.5f) / float(size.x), (float(pos.y) + 0.5f) / float(size.y), 0.0);\n" + " vec3 direct = vec3(0.0, 0.0, -1.0);\n" + " uint count = 0;\n" + " rayQueryEXT rayQuery;\n" + "\n" + " rayQueryInitializeEXT(rayQuery, rayQueryTopLevelAccelerationStructure, rayFlags, cullMask, origin, tmin, direct, tmax);\n" + "\n" + " while(rayQueryProceedEXT(rayQuery))\n" + " {\n" + " if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCandidateIntersectionTriangleEXT)\n" + " {\n" + " rayQueryConfirmIntersectionEXT(rayQuery);\n" + " count++;\n" + " }\n" + " }\n" + " imageStore(result, pos, ivec4(count, 0, 0, 0));\n" + "\n"; + + return result; + } + else + { + TCU_THROW(InternalError, "Unknown geometry type"); + } +} + + +class TestConfigurationNoMiss : public TestConfiguration +{ +public: + virtual const VkAccelerationStructureKHR* initAccelerationStructures (Context& context, + TestParams& testParams, + VkCommandBuffer cmdBuffer) override; + + virtual bool verify (BufferWithMemory* resultBuffer, + Context& context, + TestParams& testParams) override; +private: + deUint32 chooseAABB (de::Random& rng, + const std::vector& vertices, + const std::vector& aabbs); + deUint32 chooseTriangle (de::Random& rng, + const std::vector& vertices, + const std::vector& triangles); +}; + +deUint32 TestConfigurationNoMiss::chooseAABB (de::Random& rng, + const std::vector& vertices, + const std::vector& aabbs) +{ + while (true) + { + const deUint32 n = (deUint32)rng.getInt(0, (deUint32)aabbs.size() - 1); + const tcu::UVec2& t = aabbs[n]; + const tcu::Vec2& a = vertices[t.x()]; + const tcu::Vec2& b = vertices[t.y()]; + + if (deFloatAbs(a.x() - b.x()) < MIN_AABB_SIDE_LENGTH || deFloatAbs(a.y() - b.y()) < MIN_AABB_SIDE_LENGTH) + continue; + + return n; + } +} + +deUint32 TestConfigurationNoMiss::chooseTriangle (de::Random& rng, + const std::vector& vertices, + const std::vector& triangles) +{ + while (true) + { + const deUint32 n = (deUint32)rng.getInt(0, (deUint32)triangles.size() - 1); + const tcu::UVec3& t = triangles[n]; + const tcu::Vec2& a = vertices[t.x()]; + const tcu::Vec2& b = vertices[t.y()]; + const tcu::Vec2& c = vertices[t.z()]; + const float ab = triangleEdgeLength(a, b); + const float bc = triangleEdgeLength(b, c); + const float ca = triangleEdgeLength(c, a); + + if (ab < MIN_TRIANGLE_EDGE_LENGTH || bc < MIN_TRIANGLE_EDGE_LENGTH || ca < MIN_TRIANGLE_EDGE_LENGTH || triangleArea(ab, bc, ca) < MIN_TRIANGLE_AREA_SIZE) + continue; + + return n; + } +} + +const VkAccelerationStructureKHR* TestConfigurationNoMiss::initAccelerationStructures (Context& context, + TestParams& testParams, + VkCommandBuffer cmdBuffer) +{ + const DeviceInterface& vkd = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + Allocator& allocator = context.getDefaultAllocator(); + const tcu::Vec2 centerPixelCenter = tcu::Vec2(0.5f - 0.5f / float(testParams.width), 0.5f - 0.5f / float(testParams.height)); + de::MovePtr rayQueryBottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure(); + de::MovePtr rayQueryTopLevelAccelerationStructure = makeTopLevelAccelerationStructure(); + de::Random rng (testParams.randomSeed); + std::vector geometryData; + + if (testParams.geomType == GEOM_TYPE_AABBS) + { + std::vector aabbs; + std::vector vertices; + + vertices.reserve(2u * testParams.squaresGroupCount); + aabbs.reserve(testParams.squaresGroupCount); + + { + // a---g---+ + // | | | + // e---d---h + // | | | + // +---f---b + // + // a-d, d-b, e-f, g-h + + const tcu::Vec2 d = centerPixelCenter; + const tcu::Vec2 a = tcu::Vec2(0.0f, 0.0f); + const tcu::Vec2 b = tcu::Vec2(1.0f, 1.0f); + const tcu::Vec2 e = tcu::Vec2(a.x(), d.y()); + const tcu::Vec2 f = tcu::Vec2(d.x(), b.y()); + const tcu::Vec2 g = tcu::Vec2(d.x(), a.y()); + const tcu::Vec2 h = tcu::Vec2(b.x(), d.y()); + const deUint32 A = 0; + const deUint32 B = 1; + const deUint32 D = 2; + const deUint32 E = 3; + const deUint32 F = 4; + const deUint32 G = 5; + const deUint32 H = 6; + + vertices.push_back(a); + vertices.push_back(b); + vertices.push_back(d); + vertices.push_back(e); + vertices.push_back(f); + vertices.push_back(g); + vertices.push_back(h); + + aabbs.push_back(tcu::UVec2(A, D)); + aabbs.push_back(tcu::UVec2(D, B)); + aabbs.push_back(tcu::UVec2(E, F)); + aabbs.push_back(tcu::UVec2(G, H)); + } + + while (aabbs.size() < testParams.squaresGroupCount) + { + // a-------+ a---g---+ + // | | | | | + // | | -> e---d---h + // | | | | | + // +-------b +---f---b + // + // a-b -> a-d, d-b, e-f, g-h + + const deUint32 n = chooseAABB(rng, vertices, aabbs); + tcu::UVec2& t = aabbs[n]; + const tcu::Vec2& a = vertices[t.x()]; + const tcu::Vec2& b = vertices[t.y()]; + const float alfa = rng.getFloat(0.2f, 0.8f); + const float beta = rng.getFloat(0.2f, 0.8f); + const tcu::Vec2 d = mixCoordsVec2(a, b, alfa, beta); + const tcu::Vec2 e = tcu::Vec2(a.x(), d.y()); + const tcu::Vec2 f = tcu::Vec2(d.x(), b.y()); + const tcu::Vec2 g = tcu::Vec2(d.x(), a.y()); + const tcu::Vec2 h = tcu::Vec2(b.x(), d.y()); + const deUint32 B = t.y(); + const deUint32 D = (deUint32)vertices.size(); + const deUint32 E = D + 1; + const deUint32 F = D + 2; + const deUint32 G = D + 3; + const deUint32 H = D + 4; + + if (d.x() <= a.x() || d.x() >= b.x() || d.y() <= a.y() || d.y() >= b.y()) + continue; + + vertices.push_back(d); + vertices.push_back(e); + vertices.push_back(f); + vertices.push_back(g); + vertices.push_back(h); + + t.y() = D; + aabbs.push_back(tcu::UVec2(D, B)); + aabbs.push_back(tcu::UVec2(E, F)); + aabbs.push_back(tcu::UVec2(G, H)); + } + + geometryData.reserve(2u * aabbs.size()); + + for (size_t i = 0; i < aabbs.size(); ++i) + { + const tcu::Vec2& a = vertices[aabbs[i].x()]; + const tcu::Vec2& b = vertices[aabbs[i].y()]; + const float az = -rng.getFloat(0.1f, 0.5f); + const float bz = az + 0.01f; + const tcu::Vec3 A = tcu::Vec3(a.x(), a.y(), az); + const tcu::Vec3 B = tcu::Vec3(b.x(), b.y(), bz); + + geometryData.push_back(A); + geometryData.push_back(B); + } + } + else if (testParams.geomType == GEOM_TYPE_TRIANGLES) + { + std::vector triangles; + std::vector vertices; + std::vector verticesZ; + + vertices.reserve(3u * testParams.squaresGroupCount); + triangles.reserve(testParams.squaresGroupCount); + + { + // Initial triangle set: aeb, bec, cef, fei, ieh, heg, ged, dea + // e - is not math middle, but centrum of one of the pixels + // a---b---c + // | \ | / | + // d---e---f + // | / | \ | + // g---h---i + + const tcu::Vec2 e = centerPixelCenter; + const tcu::Vec2 a = tcu::Vec2( 0.0f, 0.0f); + const tcu::Vec2 i = tcu::Vec2( 1.0f, 1.0f); + const tcu::Vec2 c = tcu::Vec2(i.x(), a.y()); + const tcu::Vec2 g = tcu::Vec2(a.x(), i.y()); + const tcu::Vec2 b = tcu::Vec2(e.x(), a.y()); + const tcu::Vec2 d = tcu::Vec2(a.x(), e.y()); + const tcu::Vec2 f = tcu::Vec2(i.x(), e.y()); + const tcu::Vec2 h = tcu::Vec2(e.x(), i.y()); + const deUint32 A = 0; + const deUint32 B = 1; + const deUint32 C = 2; + const deUint32 D = 3; + const deUint32 E = 4; + const deUint32 F = 5; + const deUint32 G = 6; + const deUint32 H = 7; + const deUint32 I = 8; + + vertices.push_back(a); + vertices.push_back(b); + vertices.push_back(c); + vertices.push_back(d); + vertices.push_back(e); + vertices.push_back(f); + vertices.push_back(g); + vertices.push_back(h); + vertices.push_back(i); + + triangles.push_back(tcu::UVec3(A, E, B)); + triangles.push_back(tcu::UVec3(B, E, C)); + triangles.push_back(tcu::UVec3(C, E, F)); + triangles.push_back(tcu::UVec3(F, E, I)); + triangles.push_back(tcu::UVec3(I, E, H)); + triangles.push_back(tcu::UVec3(H, E, G)); + triangles.push_back(tcu::UVec3(G, E, D)); + triangles.push_back(tcu::UVec3(D, E, A)); + } + + while (triangles.size() < testParams.squaresGroupCount) + { + const deUint32 n = chooseTriangle(rng, vertices, triangles); + tcu::UVec3& t = triangles[n]; + const tcu::Vec2& a = vertices[t.x()]; + const tcu::Vec2& b = vertices[t.y()]; + const tcu::Vec2& c = vertices[t.z()]; + const float alfa = rng.getFloat(0.2f, 0.8f); + const float beta = rng.getFloat(0.2f, 0.8f); + const tcu::Vec2 d = mixVec2(mixVec2(a, b, alfa), c, beta); + const deUint32& p = t.x(); + const deUint32& q = t.y(); + deUint32& r = t.z(); + const deUint32 R = (deUint32)vertices.size(); + + vertices.push_back(d); + + triangles.push_back(tcu::UVec3(q, r, R)); + triangles.push_back(tcu::UVec3(p, r, R)); + r = R; + } + + verticesZ.reserve(vertices.size()); + for (size_t i = 0; i < vertices.size(); ++i) + verticesZ.push_back(-rng.getFloat(0.01f, 0.99f)); + + geometryData.reserve(3u * triangles.size()); + + for (size_t i = 0; i < triangles.size(); ++i) + { + const deUint32 a = triangles[i].x(); + const deUint32 b = triangles[i].y(); + const deUint32 c = triangles[i].z(); + + geometryData.push_back(tcu::Vec3(vertices[a].x(), vertices[a].y(), verticesZ[a])); + geometryData.push_back(tcu::Vec3(vertices[b].x(), vertices[b].y(), verticesZ[b])); + geometryData.push_back(tcu::Vec3(vertices[c].x(), vertices[c].y(), verticesZ[c])); + } + } + else + { + TCU_THROW(InternalError, "Unknown geometry type"); + } + + rayQueryBottomLevelAccelerationStructure->setGeometryCount(1u); + rayQueryBottomLevelAccelerationStructure->addGeometry(geometryData, testParams.geomType == GEOM_TYPE_TRIANGLES); + rayQueryBottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator); + m_bottomAccelerationStructures.push_back(de::SharedPtr(rayQueryBottomLevelAccelerationStructure.release())); + m_topAccelerationStructure = de::SharedPtr(rayQueryTopLevelAccelerationStructure.release()); + m_topAccelerationStructure->addInstance(m_bottomAccelerationStructures.back()); + m_topAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator); + + return m_topAccelerationStructure.get()->getPtr(); +} + +bool TestConfigurationNoMiss::verify (BufferWithMemory* resultBuffer, + Context& context, + TestParams& testParams) +{ + tcu::TestLog& log = context.getTestContext().getLog(); + const deUint32 width = testParams.width; + const deUint32 height = testParams.height; + const deInt32* resultPtr = (deInt32*)resultBuffer->getAllocation().getHostPtr(); + deUint32 failures = 0; + deUint32 pos = 0; + + for (deUint32 y = 0; y < height; ++y) + for (deUint32 x = 0; x < width; ++x) + { + if (resultPtr[pos] <= 0) + failures++; + + pos++; + } + + if (failures != 0) + { + std::stringstream css; + + pos = 0; + + for (deUint32 y = 0; y < height; ++y) + { + for (deUint32 x = 0; x < width; ++x) + { + if (resultPtr[pos] <= 0) + css << std::setw(3) << resultPtr[pos] << ","; + else + css << "___,"; + + pos++; + } + + css << std::endl; + } + + log << tcu::TestLog::Message << "Retrieved:" << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage; + } + + return (failures == 0); +} + + +class TestConfigurationSingleHit : public TestConfigurationNoMiss +{ +public: + virtual bool verify (BufferWithMemory* resultBuffer, + Context& context, + TestParams& testParams) override; +}; + +bool TestConfigurationSingleHit::verify (BufferWithMemory* resultBuffer, + Context& context, + TestParams& testParams) +{ + tcu::TestLog& log = context.getTestContext().getLog(); + const deUint32 width = testParams.width; + const deUint32 height = testParams.height; + const deInt32* resultPtr = (deInt32*)resultBuffer->getAllocation().getHostPtr(); + const deInt32 expectedValue = 1; + deUint32 failures = 0; + deUint32 pos = 0; + + for (deUint32 y = 0; y < height; ++y) + for (deUint32 x = 0; x < width; ++x) + { + if (resultPtr[pos] != expectedValue) + failures++; + + pos++; + } + + if (failures != 0) + { + std::stringstream css; + + pos = 0; + + for (deUint32 y = 0; y < height; ++y) + { + for (deUint32 x = 0; x < width; ++x) + { + if (resultPtr[pos] != expectedValue) + css << std::setw(3) << resultPtr[pos] << ","; + else + css << "___,"; + + pos++; + } + + css << std::endl; + } + + log << tcu::TestLog::Message << "Retrieved:" << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage; + } + + return (failures == 0); +} + + +class RayQueryBuiltinTestInstance : public TestInstance +{ +public: + RayQueryBuiltinTestInstance (Context& context, const TestParams& data); + virtual ~RayQueryBuiltinTestInstance (void); + tcu::TestStatus iterate (void); + +private: + TestParams m_data; + de::MovePtr m_testConfig; + de::MovePtr m_pipelineConfig; +}; + +RayQueryBuiltinTestInstance::RayQueryBuiltinTestInstance (Context& context, const TestParams& data) + : vkt::TestInstance (context) + , m_data (data) +{ + switch (m_data.testType) + { + case TEST_TYPE_NO_MISS: m_testConfig = de::MovePtr(new TestConfigurationNoMiss()); break; + case TEST_TYPE_SINGLE_HIT: m_testConfig = de::MovePtr(new TestConfigurationSingleHit()); break; + default: TCU_THROW(InternalError, "Unknown test type"); + } + + switch (m_data.stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + case VK_SHADER_STAGE_GEOMETRY_BIT: + case VK_SHADER_STAGE_FRAGMENT_BIT: + { + m_pipelineConfig = de::MovePtr(new GraphicsConfiguration()); + break; + } + + case VK_SHADER_STAGE_COMPUTE_BIT: + { + m_pipelineConfig = de::MovePtr(new ComputeConfiguration()); + break; + } + + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + case VK_SHADER_STAGE_MISS_BIT_KHR: + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + { + m_pipelineConfig = de::MovePtr(new RayTracingConfiguration()); + break; + } + + default: + TCU_THROW(InternalError, "Unknown shader stage"); + } +} + +RayQueryBuiltinTestInstance::~RayQueryBuiltinTestInstance (void) +{ +} + +tcu::TestStatus RayQueryBuiltinTestInstance::iterate (void) +{ + const DeviceInterface& vkd = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + const VkQueue queue = m_context.getUniversalQueue(); + Allocator& allocator = m_context.getDefaultAllocator(); + const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); + + const deUint32 width = m_data.width; + const deUint32 height = m_data.height; + const deUint32 depth = m_data.depth; + const VkPipelineStageFlags pipelineStageFlags = ALL_RAY_TRACING_STAGES; + const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.format, width, height, depth); + const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); + const de::MovePtr image = de::MovePtr(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any)); + const Move imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, m_data.format, imageSubresourceRange); + + const deUint32 pixelSize = mapVkFormat(m_data.format).getPixelSize(); + const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(width * height * depth * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); + const VkImageSubresourceLayers resultBufferImageSubresourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u); + const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy(makeExtent3D(width, height, depth), resultBufferImageSubresourceLayers); + de::MovePtr resultBuffer = de::MovePtr(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible)); + + const VkDescriptorImageInfo resultImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL); + + const Move cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex); + const Move cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); + const VkAccelerationStructureKHR* topAccelerationStructurePtr = DE_NULL; + + m_pipelineConfig->initConfiguration(m_context, m_data); + + 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); + const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u); + const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange); + const VkMemoryBarrier postTestMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); + + cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier); + vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange); + cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineStageFlags, &postImageBarrier); + + topAccelerationStructurePtr = m_testConfig->initAccelerationStructures(m_context, m_data, *cmdBuffer); + + m_pipelineConfig->fillCommandBuffer(m_context, m_data, *cmdBuffer, topAccelerationStructurePtr, resultImageInfo); + + cmdPipelineMemoryBarrier(vkd, *cmdBuffer, pipelineStageFlags, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTestMemoryBarrier); + + vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion); + } + endCommandBuffer(vkd, *cmdBuffer); + + submitCommandsAndWait(vkd, device, queue, cmdBuffer.get()); + + invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE); + + if (m_testConfig->verify(resultBuffer.get(), m_context, m_data)) + return tcu::TestStatus::pass("Pass"); + else + return tcu::TestStatus::fail("Fail"); +} + +class RayQueryBuiltinTestCase : public TestCase +{ + public: + RayQueryBuiltinTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data); + ~RayQueryBuiltinTestCase (void); + + virtual void checkSupport (Context& context) const; + virtual void initPrograms (SourceCollections& programCollection) const; + virtual TestInstance* createInstance (Context& context) const; + +private: + TestParams m_data; +}; + +RayQueryBuiltinTestCase::RayQueryBuiltinTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data) + : vkt::TestCase (context, name, desc) + , m_data (data) +{ +} + +RayQueryBuiltinTestCase::~RayQueryBuiltinTestCase (void) +{ +} + +void RayQueryBuiltinTestCase::checkSupport (Context& context) const +{ + context.requireDeviceFunctionality(getRayTracingExtensionUsed()); + + const VkPhysicalDeviceRayTracingFeaturesKHR& rayTracingFeaturesKHR = context.getRayTracingFeatures(); + + if (rayTracingFeaturesKHR.rayQuery == DE_FALSE) + TCU_THROW(NotSupportedError, "Requires rayTracingFeaturesKHR.rayQuery"); + + m_data.pipelineCheckSupport(context, m_data); +} + +TestInstance* RayQueryBuiltinTestCase::createInstance (Context& context) const +{ + return new RayQueryBuiltinTestInstance(context, m_data); +} + +void RayQueryBuiltinTestCase::initPrograms (SourceCollections& programCollection) const +{ + m_data.pipelineInitPrograms(programCollection, m_data); +} + +static inline CheckSupportFunc getPipelineCheckSupport (const VkShaderStageFlagBits stage) +{ + switch (stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + case VK_SHADER_STAGE_GEOMETRY_BIT: + case VK_SHADER_STAGE_FRAGMENT_BIT: + return GraphicsConfiguration::checkSupport; + + case VK_SHADER_STAGE_COMPUTE_BIT: + return ComputeConfiguration::checkSupport; + + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + case VK_SHADER_STAGE_MISS_BIT_KHR: + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + return RayTracingConfiguration::checkSupport; + + default: + TCU_THROW(InternalError, "Unknown shader stage"); + } +} + +static inline InitProgramsFunc getPipelineInitPrograms (const VkShaderStageFlagBits stage) +{ + switch (stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + case VK_SHADER_STAGE_GEOMETRY_BIT: + case VK_SHADER_STAGE_FRAGMENT_BIT: + return GraphicsConfiguration::initPrograms; + + case VK_SHADER_STAGE_COMPUTE_BIT: + return ComputeConfiguration::initPrograms; + + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + case VK_SHADER_STAGE_MISS_BIT_KHR: + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + return RayTracingConfiguration::initPrograms; + + default: + TCU_THROW(InternalError, "Unknown shader stage"); + } +} + +static inline ShaderBodyTextFunc getShaderBodyTextFunc (const TestType testType) +{ + switch (testType) + { + case TEST_TYPE_NO_MISS: return getShaderBodyText; break; + case TEST_TYPE_SINGLE_HIT: return getShaderBodyText; break; + default: TCU_THROW(InternalError, "Unknown test type"); + } +} + +} // anonymous + +tcu::TestCaseGroup* createWatertightnessTests (tcu::TestContext& testCtx) +{ + const deUint32 seed = (deUint32)(testCtx.getCommandLine().getBaseSeed()); + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "watertightness", "Tests watertightness of ray query")); + + const struct PipelineStages + { + VkShaderStageFlagBits stage; + const char* name; + } + pipelineStages[] = + { + { VK_SHADER_STAGE_VERTEX_BIT, "vert" }, + { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc" }, + { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese" }, + { VK_SHADER_STAGE_GEOMETRY_BIT, "geom" }, + { VK_SHADER_STAGE_FRAGMENT_BIT, "frag" }, + { VK_SHADER_STAGE_COMPUTE_BIT, "comp" }, + { VK_SHADER_STAGE_RAYGEN_BIT_KHR, "rgen" }, + { VK_SHADER_STAGE_ANY_HIT_BIT_KHR, "ahit" }, + { VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, "chit" }, + { VK_SHADER_STAGE_MISS_BIT_KHR, "miss" }, + { VK_SHADER_STAGE_INTERSECTION_BIT_KHR, "sect" }, + { VK_SHADER_STAGE_CALLABLE_BIT_KHR, "call" }, + }; + const struct TestTypes + { + TestType testType; + const char* name; + } + testTypes[] = + { + { TEST_TYPE_NO_MISS, "nomiss" }, + { TEST_TYPE_SINGLE_HIT, "singlehit" }, + }; + const struct GeomTypes + { + GeomType geomType; + const char* name; + } + geomTypes[] = + { + { GEOM_TYPE_TRIANGLES, "triangles" }, + { GEOM_TYPE_AABBS, "aabbs" }, + }; + + for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx) + { + de::MovePtr testTypeGroup (new tcu::TestCaseGroup(group->getTestContext(), testTypes[testTypeNdx].name, "")); + const TestType testType = testTypes[testTypeNdx].testType; + const ShaderBodyTextFunc shaderBodyTextFunc = getShaderBodyTextFunc(testType); + const deUint32 imageDepth = 1; + + for (size_t pipelineStageNdx = 0; pipelineStageNdx < DE_LENGTH_OF_ARRAY(pipelineStages); ++pipelineStageNdx) + { + de::MovePtr sourceTypeGroup (new tcu::TestCaseGroup(group->getTestContext(), pipelineStages[pipelineStageNdx].name, "")); + const VkShaderStageFlagBits stage = pipelineStages[pipelineStageNdx].stage; + const CheckSupportFunc pipelineCheckSupport = getPipelineCheckSupport(stage); + const InitProgramsFunc pipelineInitPrograms = getPipelineInitPrograms(stage); + const deUint32 instancesGroupCount = 1; + const deUint32 geometriesGroupCount = 1; + const deUint32 squaresGroupCount = (TEST_WIDTH * TEST_HEIGHT) / geometriesGroupCount / instancesGroupCount; + + DE_ASSERT(instancesGroupCount * geometriesGroupCount * squaresGroupCount == TEST_WIDTH * TEST_HEIGHT); + + for (size_t geomTypeNdx = 0; geomTypeNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypeNdx) + { + const GeomType geomType = geomTypes[geomTypeNdx].geomType; + const TestParams testParams = + { + TEST_WIDTH, // deUint32 width; + TEST_HEIGHT, // deUint32 height; + imageDepth, // deUint32 depth; + seed, // deUint32 randomSeed; + testType, // TestType testType; + stage, // VkShaderStageFlagBits stage; + geomType, // GeomType geomType; + squaresGroupCount, // deUint32 squaresGroupCount; + geometriesGroupCount, // deUint32 geometriesGroupCount; + instancesGroupCount, // deUint32 instancesGroupCount; + VK_FORMAT_R32_SINT, // VkFormat format; + pipelineCheckSupport, // CheckSupportFunc pipelineCheckSupport; + pipelineInitPrograms, // InitProgramsFunc pipelineInitPrograms; + shaderBodyTextFunc, // ShaderTestTextFunc testConfigShaderBodyText; + }; + + if (testType == TEST_TYPE_SINGLE_HIT && geomType == GEOM_TYPE_AABBS) + continue; + + sourceTypeGroup->addChild(new RayQueryBuiltinTestCase(group->getTestContext(), geomTypes[geomTypeNdx].name, "", testParams)); + } + + testTypeGroup->addChild(sourceTypeGroup.release()); + } + + group->addChild(testTypeGroup.release()); + } + + return group.release(); +} + +} // RayQuery +} // vkt diff --git a/external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.hpp b/external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.hpp new file mode 100644 index 0000000..c7af644 --- /dev/null +++ b/external/vulkancts/modules/vulkan/ray_query/vktRayQueryWatertightnessTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTRAYQUERYWATERTIGHTNESSTESTS_HPP +#define _VKTRAYQUERYWATERTIGHTNESSTESTS_HPP +/*------------------------------------------------------------------------- + * 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 Query Watertightness tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace RayQuery +{ + +tcu::TestCaseGroup* createWatertightnessTests (tcu::TestContext& testCtx); + +} // RayQuery +} // vkt + +#endif // _VKTRAYQUERYWATERTIGHTNESSTESTS_HPP diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt index 84f4281..2bbef80 100644 --- a/external/vulkancts/mustpass/master/vk-default.txt +++ b/external/vulkancts/mustpass/master/vk-default.txt @@ -642061,3 +642061,39 @@ dEQP-VK.ray_query.advanced.null_as.sect.triangles dEQP-VK.ray_query.advanced.null_as.sect.aabbs dEQP-VK.ray_query.advanced.null_as.call.triangles dEQP-VK.ray_query.advanced.null_as.call.aabbs +dEQP-VK.ray_query.watertightness.nomiss.vert.triangles +dEQP-VK.ray_query.watertightness.nomiss.vert.aabbs +dEQP-VK.ray_query.watertightness.nomiss.tesc.triangles +dEQP-VK.ray_query.watertightness.nomiss.tesc.aabbs +dEQP-VK.ray_query.watertightness.nomiss.tese.triangles +dEQP-VK.ray_query.watertightness.nomiss.tese.aabbs +dEQP-VK.ray_query.watertightness.nomiss.geom.triangles +dEQP-VK.ray_query.watertightness.nomiss.geom.aabbs +dEQP-VK.ray_query.watertightness.nomiss.frag.triangles +dEQP-VK.ray_query.watertightness.nomiss.frag.aabbs +dEQP-VK.ray_query.watertightness.nomiss.comp.triangles +dEQP-VK.ray_query.watertightness.nomiss.comp.aabbs +dEQP-VK.ray_query.watertightness.nomiss.rgen.triangles +dEQP-VK.ray_query.watertightness.nomiss.rgen.aabbs +dEQP-VK.ray_query.watertightness.nomiss.ahit.triangles +dEQP-VK.ray_query.watertightness.nomiss.ahit.aabbs +dEQP-VK.ray_query.watertightness.nomiss.chit.triangles +dEQP-VK.ray_query.watertightness.nomiss.chit.aabbs +dEQP-VK.ray_query.watertightness.nomiss.miss.triangles +dEQP-VK.ray_query.watertightness.nomiss.miss.aabbs +dEQP-VK.ray_query.watertightness.nomiss.sect.triangles +dEQP-VK.ray_query.watertightness.nomiss.sect.aabbs +dEQP-VK.ray_query.watertightness.nomiss.call.triangles +dEQP-VK.ray_query.watertightness.nomiss.call.aabbs +dEQP-VK.ray_query.watertightness.singlehit.vert.triangles +dEQP-VK.ray_query.watertightness.singlehit.tesc.triangles +dEQP-VK.ray_query.watertightness.singlehit.tese.triangles +dEQP-VK.ray_query.watertightness.singlehit.geom.triangles +dEQP-VK.ray_query.watertightness.singlehit.frag.triangles +dEQP-VK.ray_query.watertightness.singlehit.comp.triangles +dEQP-VK.ray_query.watertightness.singlehit.rgen.triangles +dEQP-VK.ray_query.watertightness.singlehit.ahit.triangles +dEQP-VK.ray_query.watertightness.singlehit.chit.triangles +dEQP-VK.ray_query.watertightness.singlehit.miss.triangles +dEQP-VK.ray_query.watertightness.singlehit.sect.triangles +dEQP-VK.ray_query.watertightness.singlehit.call.triangles -- 2.7.4