Add new tests verifying cull-mask works as per spec.
authorDominik Witczak <dominik.witczak@amd.com>
Fri, 7 Aug 2020 07:37:09 +0000 (09:37 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Wed, 12 Aug 2020 18:34:19 +0000 (14:34 -0400)
New tests:
dEQP-VK.ray_tracing_pipeline.misc.cullmask_AABB
dEQP-VK.ray_tracing_pipeline.misc.cullmask_tri

Components: Vulkan

VK-GL-CTS issue: 2470

Change-Id: I0dd5a5f9b86b8ad6a9de5ea00b51d98c2c81eb3c

android/cts/master/vk-master-2020-03-01.txt
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/ray_tracing/vktRayTracingMiscTests.cpp
external/vulkancts/mustpass/master/vk-default.txt

index bbe4018..aa364cd 100644 (file)
@@ -292259,6 +292259,8 @@ dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serializatio
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.top_acceleration_structure.aabbs
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.bottom_acceleration_structure.triangles
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.bottom_acceleration_structure.aabbs
+dEQP-VK.ray_tracing_pipeline.misc.cullmask_AABB
+dEQP-VK.ray_tracing_pipeline.misc.cullmask_tri
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TL1BL1G_AABB
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TL1BLnG_AABB
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TLnBL1G_AABB
index d7480a4..2d9229a 100644 (file)
@@ -702452,6 +702452,8 @@ dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serializatio
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.top_acceleration_structure.aabbs
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.bottom_acceleration_structure.triangles
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.bottom_acceleration_structure.aabbs
+dEQP-VK.ray_tracing_pipeline.misc.cullmask_AABB
+dEQP-VK.ray_tracing_pipeline.misc.cullmask_tri
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TL1BL1G_AABB
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TL1BLnG_AABB
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TLnBL1G_AABB
index 957b52a..9e5b630 100644 (file)
@@ -68,6 +68,7 @@ enum class ShaderGroups
 
 enum class TestType
 {
+       CULL_MASK,
        NO_DUPLICATE_ANY_HIT
 };
 
@@ -95,8 +96,6 @@ struct CaseDef
        TestType                                        type;
        GeometryType                            geometryType;
        AccelerationStructureLayout     asLayout;
-
-       deUint32 nRaysToTrace;
 };
 
 /* Helper global functions */
@@ -138,6 +137,34 @@ static const char* getSuffixForGeometryType(const GeometryType& type)
        return result;
 }
 
+/* Instances and primitives in acceleration structures can have additional information assigned.
+ *
+ * By overriding functions of interest in this class, tests can further customize ASes generated by AS providers.
+ */
+class ASPropertyProvider
+{
+public:
+       virtual ~ASPropertyProvider()
+       {
+               /* Stub */
+       }
+
+       virtual deUint8 getCullMask(const deUint32& nBL, const deUint32& nInstance) const
+       {
+               DE_UNREF(nBL);
+               DE_UNREF(nInstance);
+
+               return 0;
+       }
+
+       virtual deUint32 getInstanceCustomIndex(const deUint32& nBL, const deUint32& nInstance) const
+       {
+               DE_UNREF(nBL);
+               DE_UNREF(nInstance);
+               return 0;
+       }
+};
+
 /* Acceleration structure data providers.
  *
  * These are expected to be reused across different test cases.
@@ -153,9 +180,21 @@ public:
        virtual std::unique_ptr<TopLevelAccelerationStructure>  createTLAS(             Context&                                                        context,
                                                                                                                                                        const AccelerationStructureLayout&      asLayout,
                                                                                                                                                        VkCommandBuffer                                         cmdBuffer,
-                                                                                                                                                       const VkGeometryFlagsKHR&                       bottomLevelGeometryFlags)       const = 0;
-       virtual deUint32                                                                                getNPrimitives()                                                                                                                                const = 0;
+                                                                                                                                                       const VkGeometryFlagsKHR&                       bottomLevelGeometryFlags,
+                                                                                                                                                       const ASPropertyProvider*                       optAsPropertyProviderPtr        = nullptr)      const = 0;
+       virtual deUint32                                                                                getNPrimitives()                                                                                                                                                        const = 0;
+
+};
+
+class IGridASFeedback
+{
+public:
+       virtual ~IGridASFeedback()
+       {
+               /* Stub */
+       }
 
+       virtual void onCullMaskAssignedToCell(const tcu::UVec3& cellLocation, const deUint8& cullMaskAssigned) = 0;
 };
 
 /* A 3D grid built of primitives. Size and distribution of the geometry can be configured at creation time. */
@@ -167,7 +206,8 @@ public:
                                        const tcu::UVec3&                       gridSizeXYZ,
                                        const tcu::Vec3&                        gridInterCellDeltaXYZ,
                                        const GeometryType&                     geometryType)
-               :m_geometryType                 (geometryType),
+               :m_gridASFeedbackPtr    (nullptr),
+                m_geometryType                 (geometryType),
                 m_gridCellSizeXYZ              (gridCellSizeXYZ),
                 m_gridInterCellDeltaXYZ(gridInterCellDeltaXYZ),
                 m_gridSizeXYZ                  (gridSizeXYZ),
@@ -198,27 +238,103 @@ public:
                        }
                        else
                        {
-                               /* Cell == Plane that spans from top-left-front corner to bottom-right-back corner of the cell */
+                               /* Cell == Six triangles forming a cube
+                                *
+                                * Lower-case characters: vertices with Z == Z2
+                                * Upper-case characters: vertices with Z == Z1
+
+
+                                               g                               h
+
+
+                                   C              D
+
+
+
+                                               e                               f
+
+                                       A              B
+
+
+                                */
                                const auto A = tcu::Vec3(       cellX1Y1Z1.x(),
                                                                                        cellX1Y1Z1.y(),
                                                                                        cellX1Y1Z1.z() );
                                const auto B = tcu::Vec3(       cellX2Y2Z2.x(),
-                                                                                       cellX2Y2Z2.y(),
-                                                                                       cellX2Y2Z2.z() );
+                                                                                       cellX1Y1Z1.y(),
+                                                                                       cellX1Y1Z1.z() );
                                const auto C = tcu::Vec3(       cellX1Y1Z1.x(),
                                                                                        cellX2Y2Z2.y(),
                                                                                        cellX1Y1Z1.z() );
                                const auto D = tcu::Vec3(       cellX2Y2Z2.x(),
+                                                                                       cellX2Y2Z2.y(),
+                                                                                       cellX1Y1Z1.z() );
+                               const auto E = tcu::Vec3(       cellX1Y1Z1.x(),
+                                                                                       cellX1Y1Z1.y(),
+                                                                                       cellX2Y2Z2.z() );
+                               const auto F = tcu::Vec3(       cellX2Y2Z2.x(),
                                                                                        cellX1Y1Z1.y(),
                                                                                        cellX2Y2Z2.z() );
+                               const auto G = tcu::Vec3(       cellX1Y1Z1.x(),
+                                                                                       cellX2Y2Z2.y(),
+                                                                                       cellX2Y2Z2.z() );
+                               const auto H = tcu::Vec3(       cellX2Y2Z2.x(),
+                                                                                       cellX2Y2Z2.y(),
+                                                                                       cellX2Y2Z2.z() );
 
+                               // Z = Z1 face
                                m_vertexVec.push_back(A);
                                m_vertexVec.push_back(C);
+                               m_vertexVec.push_back(D);
+
+                               m_vertexVec.push_back(D);
                                m_vertexVec.push_back(B);
+                               m_vertexVec.push_back(A);
+
+                               // Z = Z2 face
+                               m_vertexVec.push_back(E);
+                               m_vertexVec.push_back(H);
+                               m_vertexVec.push_back(G);
 
+                               m_vertexVec.push_back(H);
+                               m_vertexVec.push_back(F);
+                               m_vertexVec.push_back(E);
+
+                               // X = X0 face
                                m_vertexVec.push_back(A);
+                               m_vertexVec.push_back(C);
+                               m_vertexVec.push_back(G);
+
+                               m_vertexVec.push_back(G);
+                               m_vertexVec.push_back(E);
+                               m_vertexVec.push_back(A);
+
+                               // X = X1 face
+                               m_vertexVec.push_back(B);
+                               m_vertexVec.push_back(D);
+                               m_vertexVec.push_back(H);
+
+                               m_vertexVec.push_back(H);
+                               m_vertexVec.push_back(F);
                                m_vertexVec.push_back(B);
+
+                               // Y = Y0 face
+                               m_vertexVec.push_back(C);
                                m_vertexVec.push_back(D);
+                               m_vertexVec.push_back(H);
+
+                               m_vertexVec.push_back(H);
+                               m_vertexVec.push_back(G);
+                               m_vertexVec.push_back(C);
+
+                               // Y = y1 face
+                               m_vertexVec.push_back(A);
+                               m_vertexVec.push_back(B);
+                               m_vertexVec.push_back(E);
+
+                               m_vertexVec.push_back(B);
+                               m_vertexVec.push_back(F);
+                               m_vertexVec.push_back(E);
                        }
                }
        }
@@ -226,21 +342,28 @@ public:
        std::unique_ptr<TopLevelAccelerationStructure> createTLAS(      Context&                                                        context,
                                                                                                                                const AccelerationStructureLayout&      asLayout,
                                                                                                                                VkCommandBuffer                                         cmdBuffer,
-                                                                                                                               const VkGeometryFlagsKHR&                       bottomLevelGeometryFlags) const
+                                                                                                                               const VkGeometryFlagsKHR&                       bottomLevelGeometryFlags,
+                                                                                                                               const ASPropertyProvider*                       optASPropertyProviderPtr        = nullptr) const final
        {
                Allocator&                                                                              allocator                               = context.getDefaultAllocator           ();
                const DeviceInterface&                                                  deviceInterface                 = context.getDeviceInterface            ();
                const VkDevice                                                                  deviceVk                                = context.getDevice                                     ();
+               const auto                                                                              nCells                                  = m_gridSizeXYZ.x() * m_gridSizeXYZ.y() * m_gridSizeXYZ.z();
                std::unique_ptr<TopLevelAccelerationStructure>  resultPtr;
                de::MovePtr<TopLevelAccelerationStructure>              tlPtr                                   = makeTopLevelAccelerationStructure ();
 
                const auto      nVerticesPerPrimitive   = (m_geometryType == GeometryType::AABB)        ? 2u
-                                                                                                                                                                               : 3u;
+                                                                                                                                                                               : 12u /* tris */  * 3 /* verts */;
 
                switch (asLayout)
                {
                        case AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY:
                        {
+                               const auto cullMask                             = (optASPropertyProviderPtr) != nullptr ? optASPropertyProviderPtr->getCullMask(0, 0)
+                                                                                                                                                                               : static_cast<deUint8>(0xFF);
+                               const auto instanceCustomIndex  = (optASPropertyProviderPtr) != nullptr ? optASPropertyProviderPtr->getInstanceCustomIndex(0, 0)
+                                                                                                                                                                               : 0;
+
                                tlPtr->setInstanceCount(1);
 
                                {
@@ -256,7 +379,25 @@ public:
                                                                                        cmdBuffer,
                                                                                        allocator);
 
-                                       tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ) );
+                                       tlPtr->addInstance(     de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ),
+                                                                               identityMatrix3x4,
+                                                                               instanceCustomIndex,
+                                                                               cullMask);
+                               }
+
+                               if (m_gridASFeedbackPtr != nullptr)
+                               {
+                                       for (auto       nCell = 0u;
+                                                               nCell < nCells;
+                                                               nCell++)
+                                       {
+                                               const auto cellX = (((nCell)                                                                                            % m_gridSizeXYZ.x() ));
+                                               const auto cellY = (((nCell / m_gridSizeXYZ.x() )                                                       % m_gridSizeXYZ.y() ));
+                                               const auto cellZ = (((nCell / m_gridSizeXYZ.x() )       / m_gridSizeXYZ.y() )   % m_gridSizeXYZ.z() );
+
+                                               m_gridASFeedbackPtr->onCullMaskAssignedToCell(  tcu::UVec3(cellX, cellY, cellZ),
+                                                                                                                                               cullMask);
+                                       }
                                }
 
                                break;
@@ -264,6 +405,11 @@ public:
 
                        case AccelerationStructureLayout::ONE_TL_ONE_BL_MANY_GEOMETRIES:
                        {
+                               const auto      cullMask                        = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getCullMask(0, 0)
+                                                                                                                                                                               : static_cast<deUint8>(0xFF);
+                               const auto      instanceCustomIndex     = (optASPropertyProviderPtr) != nullptr ? optASPropertyProviderPtr->getInstanceCustomIndex(0, 0)
+                                                                                                                                                                               : 0;
+
                                DE_ASSERT( (m_vertexVec.size() % nVerticesPerPrimitive) == 0);
 
                                tlPtr->setInstanceCount(1);
@@ -293,7 +439,25 @@ public:
                                                                                        cmdBuffer,
                                                                                        allocator);
 
-                                       tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ) );
+                                       tlPtr->addInstance(     de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ),
+                                                                               identityMatrix3x4,
+                                                                               instanceCustomIndex,
+                                                                               cullMask);
+                               }
+
+                               if (m_gridASFeedbackPtr != nullptr)
+                               {
+                                       for (auto       nCell = 0u;
+                                                               nCell < nCells;
+                                                               nCell++)
+                                       {
+                                               const auto cellX = (((nCell)                                                                                            % m_gridSizeXYZ.x() ));
+                                               const auto cellY = (((nCell / m_gridSizeXYZ.x() )                                                       % m_gridSizeXYZ.y() ));
+                                               const auto cellZ = (((nCell / m_gridSizeXYZ.x() )       / m_gridSizeXYZ.y() )   % m_gridSizeXYZ.z() );
+
+                                               m_gridASFeedbackPtr->onCullMaskAssignedToCell(  tcu::UVec3(cellX, cellY, cellZ),
+                                                                                                                                               cullMask);
+                                       }
                                }
 
                                break;
@@ -303,14 +467,18 @@ public:
                        {
                                DE_ASSERT( (m_vertexVec.size() % nVerticesPerPrimitive) == 0);
 
-                               const auto nInstances = m_vertexVec.size() / nVerticesPerPrimitive;
+                               const auto      nInstances      = m_vertexVec.size() / nVerticesPerPrimitive;
 
                                tlPtr->setInstanceCount(nInstances);
 
                                for (deUint32 nInstance = 0; nInstance < nInstances; nInstance++)
                                {
                                        de::MovePtr<BottomLevelAccelerationStructure>   blPtr                                           = makeBottomLevelAccelerationStructure();
+                                       const auto                                                                              cullMask                                        = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getCullMask(0, nInstance)
+                                                                                                                                                                                                                                                                               : static_cast<deUint8>(0xFF);
                                        std::vector<tcu::Vec3>                                                  currentInstanceVertexVec;
+                                       const auto                                                                              instanceCustomIndex                     = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getInstanceCustomIndex(0, nInstance)
+                                                                                                                                                                                                                                                                               : 0;
 
                                        for (deUint32 nVertex = 0; nVertex < nVerticesPerPrimitive; ++nVertex)
                                        {
@@ -327,7 +495,21 @@ public:
                                                                                        cmdBuffer,
                                                                                        allocator);
 
-                                       tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ) );
+                                       tlPtr->addInstance(     de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ),
+                                                                               identityMatrix3x4,
+                                                                               instanceCustomIndex,
+                                                                               cullMask);
+
+
+                                       if (m_gridASFeedbackPtr != nullptr)
+                                       {
+                                               const auto cellX = (((nInstance)                                                                                                % m_gridSizeXYZ.x() ));
+                                               const auto cellY = (((nInstance / m_gridSizeXYZ.x() )                                                   % m_gridSizeXYZ.y() ));
+                                               const auto cellZ = (((nInstance / m_gridSizeXYZ.x() )   / m_gridSizeXYZ.y() )   % m_gridSizeXYZ.z() );
+
+                                               m_gridASFeedbackPtr->onCullMaskAssignedToCell(  tcu::UVec3(cellX, cellY, cellZ),
+                                                                                                                                               cullMask);
+                                       }
                                }
 
                                break;
@@ -335,9 +517,9 @@ public:
 
                        case AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES:
                        {
-                               const auto nPrimitivesDefined   = static_cast<deUint32>(m_vertexVec.size() / nVerticesPerPrimitive);
-                               const auto nPrimitivesPerBLAS   = 4;
-                               const auto nBottomLevelASes             = nPrimitivesDefined / nPrimitivesPerBLAS;
+                               const auto      nPrimitivesDefined      = static_cast<deUint32>(m_vertexVec.size() / nVerticesPerPrimitive);
+                               const auto      nPrimitivesPerBLAS      = 4;
+                               const auto      nBottomLevelASes        = nPrimitivesDefined / nPrimitivesPerBLAS;
 
                                DE_ASSERT( (m_vertexVec.size() % nVerticesPerPrimitive)                                                 == 0);
                                DE_ASSERT( (nPrimitivesDefined % (nPrimitivesPerBLAS * nVerticesPerPrimitive))  == 0);
@@ -346,7 +528,11 @@ public:
 
                                for (deUint32 nBottomLevelAS = 0; nBottomLevelAS < nBottomLevelASes; nBottomLevelAS++)
                                {
-                                       de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
+                                       de::MovePtr<BottomLevelAccelerationStructure>   blPtr                           = makeBottomLevelAccelerationStructure();
+                                       const auto                                                                              cullMask                        = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getCullMask(nBottomLevelAS, 0)
+                                                                                                                                                                                                                                                               : static_cast<deUint8>(0xFF);
+                                       const auto                                                                              instanceCustomIndex     = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getInstanceCustomIndex(nBottomLevelAS, 0)
+                                                                                                                                                                                                                                                               : 0;
 
                                        blPtr->setGeometryCount(nPrimitivesPerBLAS);
 
@@ -368,7 +554,23 @@ public:
                                                                                        deviceVk,
                                                                                        cmdBuffer,
                                                                                        allocator);
-                                       tlPtr->addInstance(             de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ) );
+                                       tlPtr->addInstance(             de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release() ),
+                                                                                       identityMatrix3x4,
+                                                                                       instanceCustomIndex,
+                                                                                       cullMask);
+
+                                       if (m_gridASFeedbackPtr != nullptr)
+                                       {
+                                               for (deUint32 cellIndex = nPrimitivesPerBLAS * nBottomLevelAS; cellIndex < nPrimitivesPerBLAS * (nBottomLevelAS + 1); cellIndex++)
+                                               {
+                                                       const auto cellX = (((cellIndex)                                                                                                % m_gridSizeXYZ.x() ));
+                                                       const auto cellY = (((cellIndex / m_gridSizeXYZ.x() )                                                   % m_gridSizeXYZ.y() ));
+                                                       const auto cellZ = (((cellIndex / m_gridSizeXYZ.x() )   / m_gridSizeXYZ.y() )   % m_gridSizeXYZ.z() );
+
+                                                       m_gridASFeedbackPtr->onCullMaskAssignedToCell(  tcu::UVec3(cellX, cellY, cellZ),
+                                                                                                                                                       cullMask);
+                                               }
+                                       }
                                }
 
                                break;
@@ -394,7 +596,13 @@ public:
                return m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
        }
 
+       void setGridASFeedback(IGridASFeedback* feedbackPtr)
+       {
+               m_gridASFeedbackPtr = feedbackPtr;
+       }
+
 private:
+       IGridASFeedback*       m_gridASFeedbackPtr;
        std::vector<tcu::Vec3> m_vertexVec;
 
        const GeometryType      m_geometryType;
@@ -419,18 +627,336 @@ public:
        virtual deUint32                                getResultBufferSize                     ()                                                                              const = 0;
        virtual void                                    initPrograms                            (SourceCollections& programCollection)  const = 0;
        virtual bool                                    verifyResultBuffer                      (const void*            inBufferPtr)            const = 0;
+
+       virtual const ASPropertyProvider* getASPropertyProviderPtr() const
+       {
+               return nullptr;
+       }
+};
+
+class CullMaskTest :   public TestBase,
+                                               public ASPropertyProvider
+{
+public:
+       CullMaskTest()
+               :m_nMaxHitsToRegister                   (256),
+                m_nRaysPerInvocation                   (4),
+                m_lastCustomInstanceIndexUsed  (0),
+                m_nCullMasksUsed                               (1)
+       {
+               /* Stub */
+       }
+
+       ~CullMaskTest()
+       {
+               /* Stub */
+       }
+
+       const ASPropertyProvider* getASPropertyProviderPtr() const final
+       {
+               return dynamic_cast<const ASPropertyProvider*>(this);
+       }
+
+       VkGeometryFlagBitsKHR getBottomLevelGeometryFlags() const final
+       {
+               return VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR;
+       }
+
+       deUint8 getCullMask(const deUint32& nBL, const deUint32& nInstance) const final
+       {
+               DE_UNREF(nBL);
+               DE_UNREF(nInstance);
+
+               deUint8 result = (m_nCullMasksUsed++) & 0xFF;
+
+               DE_ASSERT(result != 0);
+               return result;
+       }
+
+       deUint32 getInstanceCustomIndex(const deUint32& nBL, const deUint32& nInstance) const final
+       {
+               DE_UNREF(nBL);
+               DE_UNREF(nInstance);
+
+               /* NOTE: The formula below generates a sequence of unique large values. */
+               deUint32 result = (m_lastCustomInstanceIndexUsed * 7 + 153325) & ((1 << 24) - 1);
+
+               if (m_instanceCustomIndexVec.size() <= nInstance)
+               {
+                       m_instanceCustomIndexVec.resize(nInstance + 1);
+               }
+
+               m_instanceCustomIndexVec                [nInstance] = result;
+               m_lastCustomInstanceIndexUsed                           = result;
+
+               return result;
+       }
+
+       tcu::UVec3 getDispatchSize() const final
+       {
+               //< 3*5*17 == 255, which coincidentally is the maximum cull mask value the spec permits.
+               //<
+               //< This global WG size is excessively large if m_nRaysPerInvocation > 1 but the raygen shader has
+               //< a guard condition check that drops extraneous invocations.
+               return tcu::UVec3(3, 5, 17);
+       }
+
+       deUint32 getResultBufferSize() const final
+       {
+               return static_cast<deUint32>((1 + m_nMaxHitsToRegister * 2) * sizeof(deUint32) );
+       }
+
+       void initPrograms(SourceCollections& programCollection) const final
+       {
+               const vk::ShaderBuildOptions    buildOptions(   programCollection.usedVulkanVersion,
+                                                                                                               vk::SPIRV_VERSION_1_4,
+                                                                                                               0u,             /* flags        */
+                                                                                                               true);  /* allowSpirv14 */
+
+               const char* hitPropsDefinition =
+                       "struct HitProps\n"
+                       "{\n"
+                       "    uint rayIndex;\n"
+                       "    uint instanceCustomIndex;\n"
+                       "};\n";
+
+               {
+                       std::stringstream css;
+
+                       css <<
+                               "#version 460 core\n"
+                               "\n"
+                               "#extension GL_EXT_ray_tracing : require\n"
+                               "\n"
+                               "hitAttributeEXT vec3 dummyAttribute;\n"
+                               "\n"
+                               + de::toString(hitPropsDefinition) +
+                               "\n"
+                               "layout(location = 0) rayPayloadInEXT      uint   nRay;\n"
+                               "layout(set      = 0, binding = 0, std430) buffer result\n"
+                               "{\n"
+                               "    uint     nHitsRegistered;\n"
+                               "    uint     nMissesRegistered;\n"
+                               "    HitProps hits[];\n"
+                               "};\n"
+                               "\n"
+                               "void main()\n"
+                               "{\n"
+                               "    uint nHit = atomicAdd(nHitsRegistered, 1);\n"
+                               "\n"
+                               "    if (nHit < " + de::toString(m_nMaxHitsToRegister) + ")\n"
+                               "    {\n"
+                               "        hits[nHit].rayIndex            = nRay;\n"
+                               "        hits[nHit].instanceCustomIndex = gl_InstanceCustomIndexEXT;\n"
+                               "    }\n"
+                               "}\n";
+
+                       programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str() ) << buildOptions;
+               }
+
+               {
+                       std::stringstream css;
+
+                       css <<
+                               "#version 460 core\n"
+                               "\n"
+                               "#extension GL_EXT_ray_tracing : require\n"
+                               "\n"
+                               "hitAttributeEXT vec3 hitAttribute;\n"
+                               "\n"
+                               "void main()\n"
+                               "{\n"
+                               "    reportIntersectionEXT(0.95f, 0);\n"
+                               "}\n";
+
+                       programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str() ) << buildOptions;
+               }
+
+               {
+                       std::stringstream css;
+
+                       css <<
+                               "#version 460 core\n"
+                               "\n"
+                               "#extension GL_EXT_ray_tracing : require\n"
+                               "\n"
+                               + de::toString(hitPropsDefinition) +
+                               "\n"
+                               "layout(set      = 0, binding = 0, std430) buffer result\n"
+                               "{\n"
+                               "    uint     nHitsRegistered;\n"
+                               "    uint     nMissesRegistered;\n"
+                               "    HitProps hits[];\n"
+                               "};\n"
+                               "\n"
+                               "layout(location = 0) rayPayloadInEXT uint rayIndex;\n"
+                               "\n"
+                               "void main()\n"
+                               "{\n"
+                               "    atomicAdd(nMissesRegistered, 1);\n"
+                               "}\n";
+
+                       programCollection.glslSources.add("miss") << glu::MissSource(css.str() ) << buildOptions;
+               }
+
+               {
+                       std::stringstream css;
+
+                       css <<
+                               "#version 460 core\n"
+                               "\n"
+                               "#extension GL_EXT_ray_tracing : require\n"
+                               "\n"
+                               "layout(location = 0)              rayPayloadEXT uint               rayIndex;\n"
+                               "layout(set      = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
+                               "\n"
+                               "void main()\n"
+                               "{\n"
+                               "    const uint nRaysPerInvocation = " + de::toString(m_nRaysPerInvocation) + ";\n"
+                               "\n"
+                               "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
+                               "    uint  rayFlags     = 0;\n"
+                               "    float tmin         = 0.001;\n"
+                               "    float tmax         = 9.0;\n"
+                               "\n"
+                               "    if (nInvocation >= 256 / nRaysPerInvocation)\n"
+                               "    {\n"
+                               "        return;\n"
+                               "    }\n"
+                               "\n"
+                               "    for (uint nRay = 0; nRay < nRaysPerInvocation; ++nRay)\n"
+                               "    {\n"
+                               "        uint  cullMask     = 1 + nInvocation * nRaysPerInvocation + nRay;\n"
+                               "        uint  nCell        = nInvocation * nRaysPerInvocation + nRay;\n"
+                               "        uvec3 cellXYZ      = uvec3(nCell % gl_LaunchSizeEXT.x, (nCell / gl_LaunchSizeEXT.x) % gl_LaunchSizeEXT.y, (nCell / gl_LaunchSizeEXT.x / gl_LaunchSizeEXT.y) % gl_LaunchSizeEXT.z);\n"
+                               "        vec3  cellStartXYZ = vec3(cellXYZ) * vec3(2.0);\n"
+                               "        vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
+                               "        vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
+                               "        vec3  origin       = target - vec3(1, 1, 1);\n"
+                               "        vec3  direct       = normalize(target - origin);\n"
+                               "\n"
+                               "        if (nCell < 255)\n"
+                               "        {\n"
+                               "            rayIndex = nCell;"
+                               "\n"
+                               "            traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
+                               "        }\n"
+                               "    }\n"
+                               "}\n";
+
+                       programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str() ) << buildOptions;
+               }
+       }
+
+       bool verifyResultBuffer (const void* resultDataPtr) const final
+       {
+               const deUint32* resultU32Ptr    = reinterpret_cast<const deUint32*>(resultDataPtr);
+               const auto              nHitsReported   = *resultU32Ptr;
+               const auto              nMissesReported = *(resultU32Ptr + 1);
+               bool                    result                  = true;
+
+               // For each traced ray:
+               //
+               // 1. Exactly one ahit invocation per ray should be reported.
+               // 2. All hits reported for a ray R should point to a primitive with a valid custom instance index
+               // 3. The reported custom instance indices must be valid.
+               std::map<deUint32, std::vector<deUint32> > customInstanceIndexToRayIndexVecMap;
+               std::map<deUint32, std::vector<deUint32> > rayIndexToCustomInstanceIndexVecMap;
+
+               typedef struct
+               {
+                       deUint32 rayIndex;
+                       deUint32 customInstanceHit;
+               } HitProperties;
+
+               if (nHitsReported != 0xFF)
+               {
+                       result = false;
+
+                       goto end;
+               }
+
+               if (nMissesReported != 0)
+               {
+                       result = false;
+
+                       goto end;
+               }
+
+               for (deUint32 nHit = 0; nHit < nHitsReported; ++nHit)
+               {
+                       const HitProperties* hitPropsPtr = reinterpret_cast<const HitProperties*>(resultU32Ptr + 2 /* preamble ints */ + nHit * 2 /* ints per HitProperties item */);
+
+                       customInstanceIndexToRayIndexVecMap[hitPropsPtr->customInstanceHit].push_back(hitPropsPtr->rayIndex);
+                       rayIndexToCustomInstanceIndexVecMap[hitPropsPtr->rayIndex].push_back         (hitPropsPtr->customInstanceHit);
+               }
+
+               if (static_cast<deUint32>(customInstanceIndexToRayIndexVecMap.size()) != nHitsReported)
+               {
+                       /* Invalid number of unique custom instance indices reported. */
+                       result = false;
+
+                       goto end;
+               }
+
+               if (static_cast<deUint32>(rayIndexToCustomInstanceIndexVecMap.size()) != nHitsReported)
+               {
+                       /* Invalid ray indices reported by ahit invocations */
+                       result = false;
+
+                       goto end;
+               }
+
+               for (const auto& currentItem : customInstanceIndexToRayIndexVecMap)
+               {
+                       if (currentItem.second.size() != 1)
+                       {
+                               /* More than one ray associated with the same custom instance index */
+                               result = false;
+
+                               goto end;
+                       }
+
+                       if (currentItem.second.at(0) > 255)
+                       {
+                               /* Invalid ray index associated with the instance index */
+                               result = false;
+
+                               goto end;
+                       }
+
+                       if (std::find(  m_instanceCustomIndexVec.begin  (),
+                                                       m_instanceCustomIndexVec.end    (),
+                                                       currentItem.first)                                      == m_instanceCustomIndexVec.end() )
+                       {
+                               /* Invalid custom instance index reported for the ray */
+                               result = false;
+
+                               goto end;
+                       }
+               }
+
+               end:
+                       return result;
+       }
+
+private:
+       const deUint32  m_nMaxHitsToRegister;
+       const deUint32  m_nRaysPerInvocation;
+
+       mutable std::vector<deUint32>   m_instanceCustomIndexVec;
+       mutable deUint32                                m_lastCustomInstanceIndexUsed;
+       mutable deUint32                                m_nCullMasksUsed;
 };
 
 class NoDuplicateAnyHitTest : public TestBase
 {
 public:
-       NoDuplicateAnyHitTest(  const deUint32& nRaysToTrace,
-                                                       const deUint32& nTotalPrimitives)
-               :m_nRaysToTrace         (nRaysToTrace),
+       NoDuplicateAnyHitTest(const deUint32& nTotalPrimitives)
+               :m_nRaysToTrace         (32),
                 m_nTotalPrimitives     (nTotalPrimitives)
        {
-               DE_ASSERT(nRaysToTrace          != 0);
-               DE_ASSERT(nTotalPrimitives      != 0);
+               DE_ASSERT(nTotalPrimitives != 0);
        }
 
        ~NoDuplicateAnyHitTest()
@@ -828,7 +1354,8 @@ de::MovePtr<BufferWithMemory> RayTracingMiscTestInstance::runTest(void)
                tlPtr = m_asProviderPtr->createTLAS(m_context,
                                                                                        m_data.asLayout,
                                                                                        *cmdBufferPtr,
-                                                                                       m_testPtr->getBottomLevelGeometryFlags() );
+                                                                                       m_testPtr->getBottomLevelGeometryFlags(),
+                                                                                       m_testPtr->getASPropertyProviderPtr   ());
 
                deviceInterface.cmdFillBuffer(  *cmdBufferPtr,
                                                                                **resultBufferPtr,
@@ -1007,6 +1534,19 @@ RayTracingTestCase::RayTracingTestCase (tcu::TestContext&        context,
 {
        switch (m_data.type)
        {
+               case TestType::CULL_MASK:
+               {
+                       m_asProviderPtr.reset(
+                               new GridASProvider(     tcu::Vec3       (0,             0,              0),             /* gridStartXYZ          */
+                                                                       tcu::Vec3       (1,             1,              1),             /* gridCellSizeXYZ       */
+                                                                       tcu::UVec3      (3,             5,              17),    /* gridSizeXYZ           */
+                                                                       tcu::Vec3       (2.0f,  2.0f,   2.0f),  /* gridInterCellDeltaXYZ */
+                                                                       data.geometryType)
+                       );
+
+                       break;
+               }
+
                case TestType::NO_DUPLICATE_ANY_HIT:
                {
                        m_asProviderPtr.reset(
@@ -1056,13 +1596,25 @@ void RayTracingTestCase::initPrograms(SourceCollections& programCollection)     cons
 {
        switch (m_data.type)
        {
+               case TestType::CULL_MASK:
+               {
+                       DE_ASSERT(m_asProviderPtr != nullptr);
+
+                       m_testPtr.reset(
+                               new CullMaskTest()
+                       );
+
+                       m_testPtr->initPrograms(programCollection);
+
+                       break;
+               }
+
                case TestType::NO_DUPLICATE_ANY_HIT:
                {
                        DE_ASSERT(m_asProviderPtr != nullptr);
 
                        m_testPtr.reset(
-                               new NoDuplicateAnyHitTest(      m_data.nRaysToTrace,
-                                                                                       m_asProviderPtr->getNPrimitives() )
+                               new NoDuplicateAnyHitTest(m_asProviderPtr->getNPrimitives() )
                        );
 
                        m_testPtr->initPrograms(programCollection);
@@ -1083,13 +1635,24 @@ TestInstance* RayTracingTestCase::createInstance (Context& context) const
 {
        switch (m_data.type)
        {
+               case TestType::CULL_MASK:
+               {
+                       if (m_testPtr == nullptr)
+                       {
+                               m_testPtr.reset(
+                                       new CullMaskTest()
+                               );
+                       }
+
+                       break;
+               }
+
                case TestType::NO_DUPLICATE_ANY_HIT:
                {
                        if (m_testPtr == nullptr)
                        {
                                m_testPtr.reset(
-                                       new NoDuplicateAnyHitTest(      m_data.nRaysToTrace,
-                                                                                               m_asProviderPtr->getNPrimitives() )
+                                       new NoDuplicateAnyHitTest(m_asProviderPtr->getNPrimitives() )
                                );
                        }
 
@@ -1125,6 +1688,18 @@ tcu::TestCaseGroup*      createMiscTests (tcu::TestContext& testCtx)
 
        for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT; currentGeometryType = static_cast<GeometryType>(static_cast<deUint32>(currentGeometryType) + 1) )
        {
+               const std::string newTestCaseName = "cullmask_" + de::toString(getSuffixForGeometryType(currentGeometryType) );
+
+               auto newTestCasePtr = new RayTracingTestCase(   testCtx,
+                                                                                                               newTestCaseName.data(),
+                                                                                                               "Verifies cull mask works as specified",
+                                                                                                               CaseDef{TestType::CULL_MASK, currentGeometryType, AccelerationStructureLayout::ONE_TL_MANY_BLS_ONE_GEOMETRY});
+
+               miscGroupPtr->addChild(newTestCasePtr);
+       }
+
+       for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT; currentGeometryType = static_cast<GeometryType>(static_cast<deUint32>(currentGeometryType) + 1) )
+       {
                for (auto currentASLayout = AccelerationStructureLayout::FIRST; currentASLayout != AccelerationStructureLayout::COUNT; currentASLayout = static_cast<AccelerationStructureLayout>(static_cast<deUint32>(currentASLayout) + 1) )
                {
                        const std::string newTestCaseName = "NO_DUPLICATE_ANY_HIT_" + de::toString(getSuffixForASLayout(currentASLayout) ) + "_" + de::toString(getSuffixForGeometryType(currentGeometryType) );
@@ -1132,7 +1707,7 @@ tcu::TestCaseGroup*       createMiscTests (tcu::TestContext& testCtx)
                        auto newTestCasePtr = new RayTracingTestCase(   testCtx,
                                                                                                                        newTestCaseName.data(),
                                                                                                                        "Verifies the NO_DUPLICATE_ANY_HIT flag is adhered to when tracing rays",
-                                                                                                                       CaseDef{TestType::NO_DUPLICATE_ANY_HIT, GeometryType::AABB, currentASLayout, 32});
+                                                                                                                       CaseDef{TestType::NO_DUPLICATE_ANY_HIT, GeometryType::AABB, currentASLayout});
 
                        miscGroupPtr->addChild(newTestCasePtr);
                }
index c68ea02..00020ba 100644 (file)
@@ -704662,6 +704662,8 @@ dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serializatio
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.top_acceleration_structure.aabbs
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.bottom_acceleration_structure.triangles
 dEQP-VK.ray_tracing_pipeline.capture_replay.acceleration_structures.serialization.gpu_built.bottom_acceleration_structure.aabbs
+dEQP-VK.ray_tracing_pipeline.misc.cullmask_AABB
+dEQP-VK.ray_tracing_pipeline.misc.cullmask_tri
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TL1BL1G_AABB
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TL1BLnG_AABB
 dEQP-VK.ray_tracing_pipeline.misc.NO_DUPLICATE_ANY_HIT_1TLnBL1G_AABB