diff --git a/tools/clang/lib/AST/HlslTypes.cpp b/tools/clang/lib/AST/HlslTypes.cpp index 6edbb3b862..eeed7fe8bf 100644 --- a/tools/clang/lib/AST/HlslTypes.cpp +++ b/tools/clang/lib/AST/HlslTypes.cpp @@ -753,17 +753,7 @@ clang::RecordDecl *GetRecordDeclFromNodeObjectType(clang::QualType ObjectTy) { } bool IsHLSLRayQueryType(clang::QualType type) { - type = type.getCanonicalType(); - if (const RecordType *RT = dyn_cast(type)) { - if (const ClassTemplateSpecializationDecl *templateDecl = - dyn_cast( - RT->getAsCXXRecordDecl())) { - StringRef name = templateDecl->getName(); - if (name == "RayQuery") - return true; - } - } - return false; + return nullptr != getAttr(type); } #ifdef ENABLE_SPIRV_CODEGEN diff --git a/tools/clang/lib/SPIRV/AstTypeProbe.cpp b/tools/clang/lib/SPIRV/AstTypeProbe.cpp index c933a82c16..a871bd3577 100644 --- a/tools/clang/lib/SPIRV/AstTypeProbe.cpp +++ b/tools/clang/lib/SPIRV/AstTypeProbe.cpp @@ -1141,12 +1141,13 @@ bool isOpaqueType(QualType type) { if (name == "RaytracingAccelerationStructure") return true; - if (name == "RayQuery") - return true; - if (name == "SubpassInput") return true; } + + if (hlsl::IsHLSLRayQueryType(type)) + return true; + return false; } diff --git a/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp b/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp index 4c06cd4113..b330d40d85 100644 --- a/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp +++ b/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp @@ -965,7 +965,7 @@ LowerTypeVisitor::lowerResourceType(QualType type, SpirvLayoutRule rule, return spvContext.getAccelerationStructureTypeNV(); } - if (name == "RayQuery") + if (hlsl::IsHLSLRayQueryType(type)) return spvContext.getRayQueryTypeKHR(); if (name == "StructuredBuffer" || name == "RWStructuredBuffer" || diff --git a/tools/clang/test/CodeGenSPIRV/type.rayquery.user-defined-shadow.hlsl b/tools/clang/test/CodeGenSPIRV/type.rayquery.user-defined-shadow.hlsl new file mode 100644 index 0000000000..95530d3b85 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/type.rayquery.user-defined-shadow.hlsl @@ -0,0 +1,36 @@ +// RUN: %dxc -T cs_6_6 -E MainRayGenShader -fcgl -spirv %s | FileCheck %s --implicit-check-not=OpTypeRayQueryKHR + +// A user-defined struct named "RayQuery" that shadows the reserved intrinsic +// name must be lowered as an ordinary struct, not as the opaque ray query +// type. Previously this crashed the SPIR-V backend. +// See https://github.com/microsoft/DirectXShaderCompiler/issues/8601 + +namespace UnifiedRT { +struct RayQuery { + float4 foo; +}; +} // namespace UnifiedRT + +// The shadowing struct is lowered to an ordinary struct with a float4 field, +// and the local variable uses that struct type in the Function storage class. +// CHECK: %RayQuery = OpTypeStruct %v4float +// CHECK: %_ptr_Function_RayQuery = OpTypePointer Function %RayQuery +// CHECK: %rayQuery = OpVariable %_ptr_Function_RayQuery Function + +// It must not be lowered to the opaque ray query type. The absence of +// OpTypeRayQueryKHR anywhere in the module is checked by the +// --implicit-check-not on the FileCheck invocation above. + +StructuredBuffer _UnifiedRT_DispatchDims; + +[numthreads(128, 1, 1)] +void MainRayGenShader(in uint3 gidx : SV_DispatchThreadID, + in uint lidx : SV_GroupIndex) { + if (gidx.x >= _UnifiedRT_DispatchDims[0] || + gidx.y >= _UnifiedRT_DispatchDims[1] || + gidx.z >= _UnifiedRT_DispatchDims[2]) + return; + + UnifiedRT::RayQuery rayQuery; + rayQuery.foo = float4(1.0, 1.0, 1.0, 1.0); +} diff --git a/tools/clang/test/CodeGenSPIRV/type.rayquery.user-defined-shadow.template.hlsl b/tools/clang/test/CodeGenSPIRV/type.rayquery.user-defined-shadow.template.hlsl new file mode 100644 index 0000000000..d1023e856c --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/type.rayquery.user-defined-shadow.template.hlsl @@ -0,0 +1,34 @@ +// RUN: %dxc -T cs_6_6 -E MainRayGenShader -HV 2021 -fcgl -spirv %s | FileCheck %s --implicit-check-not=OpTypeRayQueryKHR + +// A user-defined class template named "RayQuery" that shadows the reserved +// intrinsic name must be lowered as an ordinary struct, not as the opaque ray +// query type. The intrinsic is itself a class template, so detecting it by +// name and specialization kind alone also misclassifies this case. +// See https://github.com/microsoft/DirectXShaderCompiler/issues/8601 + +namespace UnifiedRT { +template struct RayQuery { + T foo; +}; +} // namespace UnifiedRT + +// The shadowing template instance is lowered to an ordinary struct with a +// float4 field, and the local variable uses that struct type in the Function +// storage class. +// CHECK: %RayQuery = OpTypeStruct %v4float +// CHECK: %_ptr_Function_RayQuery = OpTypePointer Function %RayQuery +// CHECK: %rayQuery = OpVariable %_ptr_Function_RayQuery Function + +StructuredBuffer _UnifiedRT_DispatchDims; + +[numthreads(128, 1, 1)] +void MainRayGenShader(in uint3 gidx : SV_DispatchThreadID, + in uint lidx : SV_GroupIndex) { + if (gidx.x >= _UnifiedRT_DispatchDims[0] || + gidx.y >= _UnifiedRT_DispatchDims[1] || + gidx.z >= _UnifiedRT_DispatchDims[2]) + return; + + UnifiedRT::RayQuery rayQuery; + rayQuery.foo = float4(1.0, 1.0, 1.0, 1.0); +}