enum class TestType
{
+ CULL_MASK,
NO_DUPLICATE_ANY_HIT
};
TestType type;
GeometryType geometryType;
AccelerationStructureLayout asLayout;
-
- deUint32 nRaysToTrace;
};
/* Helper global functions */
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.
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. */
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),
}
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);
}
}
}
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);
{
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;
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);
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;
{
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)
{
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;
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);
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);
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;
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;
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()
tlPtr = m_asProviderPtr->createTLAS(m_context,
m_data.asLayout,
*cmdBufferPtr,
- m_testPtr->getBottomLevelGeometryFlags() );
+ m_testPtr->getBottomLevelGeometryFlags(),
+ m_testPtr->getASPropertyProviderPtr ());
deviceInterface.cmdFillBuffer( *cmdBufferPtr,
**resultBufferPtr,
{
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(
{
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);
{
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() )
);
}
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) );
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);
}