From 10bff1319a28e8ad2aa0c5aa894ba8ec4c3a2e2b Mon Sep 17 00:00:00 2001 From: Simon Moll Date: Wed, 16 Apr 2025 05:35:25 +0200 Subject: [PATCH 1/7] Fix field names in long vector DICompositeType (#7332) Fix OOB accesses for debug info vector field names for vectors of length >4. --- tools/clang/lib/CodeGen/CGDebugInfo.cpp | 11 ++++++- .../hlsl/types/longvec-field-di.hlsl | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tools/clang/test/CodeGenDXIL/hlsl/types/longvec-field-di.hlsl diff --git a/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/tools/clang/lib/CodeGen/CGDebugInfo.cpp index 206f7d9523..d947887d62 100644 --- a/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1047,8 +1047,17 @@ bool CGDebugInfo::TryCollectHLSLRecordElements(const RecordType *Ty, unsigned VecSize = hlsl::GetHLSLVecSize(QualTy); unsigned ElemSizeInBits = CGM.getContext().getTypeSize(ElemQualTy); unsigned CurrentAlignedOffset = 0; + SmallString<8> FieldNameBuf; for (unsigned ElemIdx = 0; ElemIdx < VecSize; ++ElemIdx) { - StringRef FieldName = StringRef(&"xyzw"[ElemIdx], 1); + StringRef FieldName; + if (VecSize <= 4) { + FieldName = StringRef(&"xyzw"[ElemIdx], 1); + } else { + FieldNameBuf.clear(); + llvm::raw_svector_ostream OS(FieldNameBuf); + OS << 'c' << ElemIdx; + FieldName = OS.str(); + } CurrentAlignedOffset = llvm::RoundUpToAlignment(CurrentAlignedOffset, AlignBits); llvm::DIType *FieldType = diff --git a/tools/clang/test/CodeGenDXIL/hlsl/types/longvec-field-di.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/types/longvec-field-di.hlsl new file mode 100644 index 0000000000..935ec3cc13 --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/hlsl/types/longvec-field-di.hlsl @@ -0,0 +1,33 @@ +// RUN: %dxc -Zi -Qembed_debug -T lib_6_9 %s -DNUM=8 | FileCheck %s --check-prefix=CHECK-LONG +// RUN: %dxc -Zi -Qembed_debug -T lib_6_9 %s -DNUM=4 | FileCheck %s --check-prefix=CHECK-SHORT + +// Test debug info for short and long vector types + +RWByteAddressBuffer buf; + +export vector lv_global_arr_ret() { + vector d = buf.Load >(0); + return d; +} + +// CHECK-LONG: ![[TYDI:[^ ]+]] = !DICompositeType(tag: DW_TAG_class_type, name: "vector", file: !{{[^ ]+}}, size: 256, align: 32, elements: ![[ELEMDI:[^ ]+]], +// CHECK-LONG: ![[ELEMDI]] = !{![[C0:[^ ]+]], ![[C1:[^ ]+]], ![[C2:[^ ]+]], ![[C3:[^ ]+]], ![[C4:[^ ]+]], ![[C5:[^ ]+]], ![[C6:[^ ]+]], ![[C7:[^ ]+]]} +// CHECK-LONG: ![[C0]] = !DIDerivedType(tag: DW_TAG_member, name: "c0", scope: !{{[^ ]+}} file: !{{[^ ]+}}, baseType: ![[BASETY:[^ ]+]], size: 32, align: 32, flags: DIFlagPublic) +// CHECK-LONG: ![[BASETY]] = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) +// CHECK-LONG: ![[C1]] = !DIDerivedType(tag: DW_TAG_member, name: "c1", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 32, flags: DIFlagPublic) +// CHECK-LONG: ![[C2]] = !DIDerivedType(tag: DW_TAG_member, name: "c2", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 64, flags: DIFlagPublic) +// CHECK-LONG: ![[C3]] = !DIDerivedType(tag: DW_TAG_member, name: "c3", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 96, flags: DIFlagPublic) +// CHECK-LONG: ![[C4]] = !DIDerivedType(tag: DW_TAG_member, name: "c4", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 128, flags: DIFlagPublic) +// CHECK-LONG: ![[C5]] = !DIDerivedType(tag: DW_TAG_member, name: "c5", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 160, flags: DIFlagPublic) +// CHECK-LONG: ![[C6]] = !DIDerivedType(tag: DW_TAG_member, name: "c6", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 192, flags: DIFlagPublic) +// CHECK-LONG: ![[C7]] = !DIDerivedType(tag: DW_TAG_member, name: "c7", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 224, flags: DIFlagPublic) +// CHECK-LONG: !{{[^ ]+}} = !DILocalVariable(tag: DW_TAG_auto_variable, name: "d", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, line: 9, type: ![[TYDI]]) + +// CHECK-SHORT: ![[TYDI:[^ ]+]] = !DICompositeType(tag: DW_TAG_class_type, name: "vector", file: !{{[^ ]+}}, size: 128, align: 32, elements: ![[ELEMDI:[^ ]+]], +// CHECK-SHORT: ![[ELEMDI]] = !{![[X:[^ ]+]], ![[Y:[^ ]+]], ![[Z:[^ ]+]], ![[W:[^ ]+]]} +// CHECK-SHORT: ![[X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY:[^ ]+]], size: 32, align: 32, flags: DIFlagPublic) +// CHECK-SHORT: ![[BASETY]] = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) +// CHECK-SHORT: ![[Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 32, flags: DIFlagPublic) +// CHECK-SHORT: ![[Z]] = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 64, flags: DIFlagPublic) +// CHECK-SHORT: ![[W]] = !DIDerivedType(tag: DW_TAG_member, name: "w", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, baseType: ![[BASETY]], size: 32, align: 32, offset: 96, flags: DIFlagPublic) +// CHECK-SHORT: !{{[^ ]+}} = !DILocalVariable(tag: DW_TAG_auto_variable, name: "d", scope: !{{[^ ]+}}, file: !{{[^ ]+}}, line: 9, type: ![[TYDI]]) \ No newline at end of file From 0a470b51535265b759c0c3a3078fa8f97fd5eb12 Mon Sep 17 00:00:00 2001 From: Steve Urquhart <53908460+SteveUrquhart@users.noreply.github.com> Date: Wed, 16 Apr 2025 11:00:58 -0400 Subject: [PATCH 2/7] [SPIRV] Remove patch decoration from gl_TessCoord (#7187) (#7349) This PR fixes https://github.com/microsoft/DirectXShaderCompiler/issues/7187. gl_TessCoord is not a per-patch builtin and therefore the SPIRV should not be decorated with Patch. This is clear in the GLSL specification, and a SPIRV spec clarification is online here: https://gitlab.khronos.org/spirv/SPIR-V/-/issues/819 --- tools/clang/lib/SPIRV/DeclResultIdMapper.cpp | 3 ++- tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv | 1 - tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl | 1 - tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp index 0358873589..de73d5e417 100644 --- a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp +++ b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp @@ -3522,7 +3522,8 @@ SpirvVariable *DeclResultIdMapper::createSpirvInterfaceVariable( // Decorate with PerPrimitiveNV for per-primitive out variables. spvBuilder.decoratePerPrimitiveNV(varInstr, varInstr->getSourceLocation()); - } else { + } else if (stageVar.getSemanticInfo().getKind() != + hlsl::Semantic::Kind::DomainLocation) { spvBuilder.decoratePatch(varInstr, varInstr->getSourceLocation()); } } diff --git a/tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv b/tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv index 3b0c060a0d..9d915a84f2 100644 --- a/tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv +++ b/tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv @@ -96,7 +96,6 @@ DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input, // CHECK-NEXT: OpDecorate %in_var_TANVCORNER Patch // CHECK-NEXT: OpDecorate %in_var_TANWEIGHTS Patch // CHECK-NEXT: OpDecorate %gl_TessCoord BuiltIn TessCoord -// CHECK-NEXT: OpDecorate %gl_TessCoord Patch // CHECK-NEXT: OpDecorate %gl_Position BuiltIn Position // CHECK-NEXT: OpDecorate %in_var_BEZIERPOS Location 0 // CHECK-NEXT: OpDecorate %in_var_TANGENT Location 1 diff --git a/tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl b/tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl index 5e4049f8c3..391e09a428 100644 --- a/tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl +++ b/tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl @@ -4,7 +4,6 @@ // CHECK-SAME: %gl_TessCoord // CHECK: OpDecorate %gl_TessCoord BuiltIn TessCoord -// CHECK: OpDecorate %gl_TessCoord Patch // CHECK: %gl_TessCoord = OpVariable %_ptr_Input_v3float Input diff --git a/tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl b/tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl index a8fe81e021..6f073aeb46 100644 --- a/tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl +++ b/tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl @@ -85,7 +85,6 @@ struct DsOut { // CHECK: OpDecorateString %gl_PointSize UserSemantic "PSIZE" // CHECK: OpDecorate %gl_TessCoord BuiltIn TessCoord // CHECK: OpDecorateString %gl_TessCoord UserSemantic "SV_DomainLocation" -// CHECK: OpDecorate %gl_TessCoord Patch // CHECK: OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter // CHECK: OpDecorateString %gl_TessLevelOuter UserSemantic "SV_TessFactor" // CHECK: OpDecorate %gl_TessLevelOuter Patch From 0beaa767f7712f0ed0ab72e1e17cb94c25f84c34 Mon Sep 17 00:00:00 2001 From: Simon Moll Date: Thu, 17 Apr 2025 18:20:49 +0200 Subject: [PATCH 3/7] [SER] MaybeReorderThread + Make(Nop|Miss) HLSL -> DXIL lowering and tests (#7262) - HLSL -> DXIL lowering - ast, hlsl->dxil, dxilgen, and ScalarReplAggregatesHLSL tests SER implementation tracker (#7214) --- include/dxc/HLSL/HLOperations.h | 4 + lib/HLSL/HLOperationLower.cpp | 116 ++++++++++++-- .../Scalar/ScalarReplAggregatesHLSL.cpp | 8 + tools/clang/lib/Sema/SemaHLSL.cpp | 1 + .../hlsl/intrinsics/maybereorder.hlsl | 37 +++++ .../objects/HitObject/hitobject_make.hlsl | 75 +++++++++ .../hlsl/objects/HitObject/lit.local.cfg | 1 + .../DXC/Passes/DxilGen/hitobject_dxilgen.ll | 5 +- .../Passes/DxilGen/maybereorder_dxilgen.ll | 3 +- .../hitobject_make_scalarrepl.ll | 142 ++++++++++++++++++ .../objects/HitObject/hitobject_make.hlsl | 12 -- .../objects/HitObject/hitobject_make_ast.hlsl | 24 --- .../hlsl/objects/HitObject/maybereorder.hlsl | 13 -- .../objects/HitObject/maybereorder_ast.hlsl | 28 ---- 14 files changed, 376 insertions(+), 93 deletions(-) create mode 100644 tools/clang/test/CodeGenDXIL/hlsl/intrinsics/maybereorder.hlsl create mode 100644 tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_make.hlsl create mode 100644 tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/lit.local.cfg create mode 100644 tools/clang/test/DXC/Passes/ScalarReplHLSL/hitobject_make_scalarrepl.ll delete mode 100644 tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make.hlsl delete mode 100644 tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make_ast.hlsl delete mode 100644 tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder.hlsl delete mode 100644 tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder_ast.hlsl diff --git a/include/dxc/HLSL/HLOperations.h b/include/dxc/HLSL/HLOperations.h index f87d324baf..a7db8612a6 100644 --- a/include/dxc/HLSL/HLOperations.h +++ b/include/dxc/HLSL/HLOperations.h @@ -433,6 +433,10 @@ const unsigned kNodeHandleToResCastOpIdx = 1; const unsigned kAnnotateNodeHandleNodePropIdx = 2; const unsigned kAnnotateNodeRecordHandleNodeRecordPropIdx = 2; +// HitObject::MakeMiss +const unsigned kHitObjectMakeMiss_NumOp = 8; +const unsigned kHitObjectMakeMissRayDescOpIdx = 4; + } // namespace HLOperandIndex llvm::Function *GetOrCreateHLFunction(llvm::Module &M, diff --git a/lib/HLSL/HLOperationLower.cpp b/lib/HLSL/HLOperationLower.cpp index b5114fa34b..be45021e41 100644 --- a/lib/HLSL/HLOperationLower.cpp +++ b/lib/HLSL/HLOperationLower.cpp @@ -12,6 +12,7 @@ // // /////////////////////////////////////////////////////////////////////////////// +#include "dxc/DXIL/DxilConstants.h" #define _USE_MATH_DEFINES #include #include @@ -6183,19 +6184,114 @@ Value *TranslateUnpack(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode, // Shader Execution Reordering. namespace { -Value *TranslateHitObjectMake(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode, - HLOperationLowerHelper &helper, - HLObjectOperationLowerHelper *pObjHelper, +Value *TranslateHitObjectMake(CallInst *CI, IntrinsicOp IOP, OP::OpCode Opcode, + HLOperationLowerHelper &Helper, + HLObjectOperationLowerHelper *ObjHelper, bool &Translated) { - return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches + hlsl::OP *HlslOP = &Helper.hlslOP; + IRBuilder<> Builder(CI); + unsigned SrcIdx = 1; + Value *HitObjectPtr = CI->getArgOperand(SrcIdx++); + if (Opcode == OP::OpCode::HitObject_MakeNop) { + Value *HitObject = TrivialDxilOperation( + Opcode, {nullptr}, Type::getVoidTy(CI->getContext()), CI, HlslOP); + Builder.CreateStore(HitObject, HitObjectPtr); + DXASSERT( + CI->use_empty(), + "Default ctor return type is a Clang artifact. Value must not be used"); + return nullptr; + } + + DXASSERT_NOMSG(CI->getNumArgOperands() == + HLOperandIndex::kHitObjectMakeMiss_NumOp); + Value *RayFlags = CI->getArgOperand(SrcIdx++); + Value *MissShaderIdx = CI->getArgOperand(SrcIdx++); + DXASSERT_NOMSG(SrcIdx == HLOperandIndex::kHitObjectMakeMissRayDescOpIdx); + Value *RayDescOrigin = CI->getArgOperand(SrcIdx++); + Value *RayDescOriginX = + Builder.CreateExtractElement(RayDescOrigin, (uint64_t)0); + Value *RayDescOriginY = + Builder.CreateExtractElement(RayDescOrigin, (uint64_t)1); + Value *RayDescOriginZ = + Builder.CreateExtractElement(RayDescOrigin, (uint64_t)2); + + Value *RayDescTMin = CI->getArgOperand(SrcIdx++); + Value *RayDescDirection = CI->getArgOperand(SrcIdx++); + Value *RayDescDirectionX = + Builder.CreateExtractElement(RayDescDirection, (uint64_t)0); + Value *RayDescDirectionY = + Builder.CreateExtractElement(RayDescDirection, (uint64_t)1); + Value *RayDescDirectionZ = + Builder.CreateExtractElement(RayDescDirection, (uint64_t)2); + + Value *RayDescTMax = CI->getArgOperand(SrcIdx++); + DXASSERT_NOMSG(SrcIdx == CI->getNumArgOperands()); + + Value *OutHitObject = TrivialDxilOperation( + Opcode, + {nullptr, RayFlags, MissShaderIdx, RayDescOriginX, RayDescOriginY, + RayDescOriginZ, RayDescTMin, RayDescDirectionX, RayDescDirectionY, + RayDescDirectionZ, RayDescTMax}, + Helper.voidTy, CI, HlslOP); + Builder.CreateStore(OutHitObject, HitObjectPtr); + return nullptr; } Value *TranslateMaybeReorderThread(CallInst *CI, IntrinsicOp IOP, - OP::OpCode opcode, - HLOperationLowerHelper &helper, + OP::OpCode OpCode, + HLOperationLowerHelper &Helper, HLObjectOperationLowerHelper *pObjHelper, bool &Translated) { - return nullptr; // TODO: Merge SER DXIL patches + hlsl::OP *OP = &Helper.hlslOP; + + // clang-format off + // Match MaybeReorderThread overload variants: + // void MaybeReorderThread(, + // HitObject Hit); + // void MaybeReorderThread(, + // uint CoherenceHint, + // uint NumCoherenceHintBitsFromLSB ); + // void MaybeReorderThread(, + // HitObject Hit, + // uint CoherenceHint, + // uint NumCoherenceHintBitsFromLSB); + // clang-format on + const unsigned NumHLArgs = CI->getNumArgOperands(); + DXASSERT_NOMSG(NumHLArgs >= 2); + + // Use a NOP HitObject for MaybeReorderThread without HitObject. + Value *HitObject = nullptr; + unsigned HLIndex = 1; + if (3 == NumHLArgs) { + HitObject = TrivialDxilOperation(DXIL::OpCode::HitObject_MakeNop, {nullptr}, + Type::getVoidTy(CI->getContext()), CI, OP); + } else { + Value *FirstParam = CI->getArgOperand(HLIndex); + DXASSERT_NOMSG(isa(FirstParam->getType())); + IRBuilder<> Builder(CI); + HitObject = Builder.CreateLoad(FirstParam); + HLIndex++; + } + + // If there are trailing parameters, these have to be the two coherence bit + // parameters + Value *CoherenceHint = nullptr; + Value *NumCoherenceHintBits = nullptr; + if (2 != NumHLArgs) { + DXASSERT_NOMSG(HLIndex + 2 == NumHLArgs); + CoherenceHint = CI->getArgOperand(HLIndex++); + NumCoherenceHintBits = CI->getArgOperand(HLIndex++); + DXASSERT_NOMSG(Helper.i32Ty == CoherenceHint->getType()); + DXASSERT_NOMSG(Helper.i32Ty == NumCoherenceHintBits->getType()); + } else { + CoherenceHint = UndefValue::get(Helper.i32Ty); + NumCoherenceHintBits = OP->GetU32Const(0); + } + + TrivialDxilOperation( + OpCode, {nullptr, HitObject, CoherenceHint, NumCoherenceHintBits}, + Type::getVoidTy(CI->getContext()), CI, OP); + return nullptr; } Value *TranslateHitObjectFromRayQuery(CallInst *CI, IntrinsicOp IOP, @@ -6968,11 +7064,9 @@ IntrinsicLower gLowerTable[] = { {IntrinsicOp::MOP_InterlockedUMin, TranslateMopAtomicBinaryOperation, DXIL::OpCode::NumOpCodes}, {IntrinsicOp::MOP_DxHitObject_MakeNop, TranslateHitObjectMake, - DXIL::OpCode::NumOpCodes_Dxil_1_8}, // FIXME: Just a placeholder Dxil - // opcode + DXIL::OpCode::HitObject_MakeNop}, {IntrinsicOp::IOP_DxMaybeReorderThread, TranslateMaybeReorderThread, - DXIL::OpCode::NumOpCodes_Dxil_1_8}, // FIXME: Just a placeholder Dxil - // opcode + DXIL::OpCode::MaybeReorderThread}, {IntrinsicOp::IOP_Vkstatic_pointer_cast, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes}, {IntrinsicOp::IOP_Vkreinterpret_pointer_cast, UnsupportedVulkanIntrinsic, diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp index ec17fce9c8..e487079b94 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp @@ -2775,6 +2775,14 @@ void SROA_Helper::RewriteCall(CallInst *CI) { RewriteCallArg(CI, HLOperandIndex::kCallShaderPayloadOpIdx, /*bIn*/ true, /*bOut*/ true); } break; + case IntrinsicOp::MOP_DxHitObject_MakeMiss: { + if (OldVal == + CI->getArgOperand(HLOperandIndex::kHitObjectMakeMissRayDescOpIdx)) { + RewriteWithFlattenedHLIntrinsicCall(CI, OldVal, NewElts, + /*loadElts*/ true); + DeadInsts.push_back(CI); + } + } break; case IntrinsicOp::MOP_TraceRayInline: { if (OldVal == CI->getArgOperand(HLOperandIndex::kTraceRayInlineRayDescOpIdx)) { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 230c7e65d9..418425a468 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12066,6 +12066,7 @@ void Sema::DiagnoseReachableHLSLCall(CallExpr *CE, const hlsl::ShaderModel *SM, case hlsl::IntrinsicOp::MOP_TraceRayInline: DiagnoseTraceRayInline(*this, CE); break; + case hlsl::IntrinsicOp::MOP_DxHitObject_MakeMiss: case hlsl::IntrinsicOp::MOP_DxHitObject_MakeNop: DiagnoseReachableSERCall(*this, CE, EntrySK, EntryDecl, false); break; diff --git a/tools/clang/test/CodeGenDXIL/hlsl/intrinsics/maybereorder.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/intrinsics/maybereorder.hlsl new file mode 100644 index 0000000000..08836dfbaf --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/hlsl/intrinsics/maybereorder.hlsl @@ -0,0 +1,37 @@ +// RUN: %dxc -T lib_6_9 -E main %s | FileCheck %s --check-prefix DXIL +// RUN: %dxc -T lib_6_9 -E main %s -fcgl | FileCheck %s --check-prefix FCGL +// RUN: %dxc -T lib_6_9 -E main %s -ast-dump-implicit | FileCheck %s --check-prefix AST + +// AST: |-FunctionDecl {{[^ ]+}} <> implicit used MaybeReorderThread 'void (dx::HitObject)' extern +// AST-NEXT: | |-ParmVarDecl {{[^ ]+}} <> HitObject 'dx::HitObject':'dx::HitObject' +// AST-NEXT: | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 359 +// AST-NEXT: | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// AST: |-FunctionDecl {{[^ ]+}} <> implicit used MaybeReorderThread 'void (dx::HitObject, unsigned int, unsigned int)' extern +// AST-NEXT: | |-ParmVarDecl {{[^ ]+}} <> HitObject 'dx::HitObject':'dx::HitObject' +// AST-NEXT: | |-ParmVarDecl {{[^ ]+}} <> CoherenceHint 'unsigned int' +// AST-NEXT: | |-ParmVarDecl {{[^ ]+}} <> NumCoherenceHintBitsFromLSB 'unsigned int' +// AST-NEXT: | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 359 +// AST-NEXT: | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// AST: `-FunctionDecl {{[^ ]+}} <> implicit used MaybeReorderThread 'void (unsigned int, unsigned int)' extern +// AST-NEXT: |-ParmVarDecl {{[^ ]+}} <> CoherenceHint 'unsigned int' +// AST-NEXT: |-ParmVarDecl {{[^ ]+}} <> NumCoherenceHintBitsFromLSB 'unsigned int' +// AST-NEXT: |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 359 +// AST-NEXT: `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// FCGL: call void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32 359, %dx.types.HitObject* %[[NOP:[^ ]+]]) +// FCGL-NEXT: call void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32)"(i32 359, %dx.types.HitObject* %[[NOP]], i32 241, i32 3) +// FCGL-NEXT: call void @"dx.hl.op..void (i32, i32, i32)"(i32 359, i32 242, i32 7) + +// DXIL: call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %[[NOP:[^ ]+]], i32 undef, i32 0) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB) +// DXIL-NEXT: call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %[[NOP]], i32 241, i32 3) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB) +// DXIL-NEXT: call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %[[NOP]], i32 242, i32 7) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB) + +[shader("raygeneration")] +void main() { + dx::HitObject hit; + dx::MaybeReorderThread(hit); + dx::MaybeReorderThread(hit, 0xf1, 3); + dx::MaybeReorderThread(0xf2, 7); +} diff --git a/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_make.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_make.hlsl new file mode 100644 index 0000000000..1e947b2296 --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_make.hlsl @@ -0,0 +1,75 @@ +// RUN: %dxc -T lib_6_9 -E main %s | FileCheck %s --check-prefix DXIL +// RUN: %dxc -T lib_6_9 -E main %s -fcgl | FileCheck %s --check-prefix FCGL +// RUN: %dxc -T lib_6_9 -E main %s -ast-dump-implicit | FileCheck %s --check-prefix AST + +// AST: | |-CXXRecordDecl {{[^ ]+}} <> implicit referenced class HitObject definition +// AST-NEXT: | | |-FinalAttr {{[^ ]+}} <> Implicit final +// AST-NEXT: | | |-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" +// AST-NEXT: | | |-HLSLHitObjectAttr {{[^ ]+}} <> Implicit +// AST-NEXT: | | |-FieldDecl {{[^ ]+}} <> implicit h 'int' +// AST-NEXT: | | |-CXXConstructorDecl {{[^ ]+}} <> used HitObject 'void ()' +// AST-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 358 +// AST-NEXT: | | | `-HLSLCXXOverloadAttr {{[^ ]+}} <> Implicit + +// AST: | | |-FunctionTemplateDecl {{[^ ]+}} <> MakeMiss +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TResult +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TRayFlags +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TMissShaderIndex +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TRay +// AST-NEXT: | | | |-CXXMethodDecl {{[^ ]+}} <> implicit MakeMiss 'TResult (TRayFlags, TMissShaderIndex, TRay) const' static +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> RayFlags 'TRayFlags' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> MissShaderIndex 'TMissShaderIndex' +// AST-NEXT: | | | | `-ParmVarDecl {{[^ ]+}} <> Ray 'TRay' +// AST-NEXT: | | | `-CXXMethodDecl {{[^ ]+}} <> used MakeMiss 'dx::HitObject (unsigned int, unsigned int, RayDesc)' static +// AST-NEXT: | | | |-TemplateArgument type 'dx::HitObject' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'RayDesc' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> MakeMiss 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> RayFlags 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> MissShaderIndex 'RayDesc' +// AST-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 387 +// AST-NEXT: | | | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// AST: | | |-FunctionTemplateDecl {{[^ ]+}} <> MakeNop +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TResult +// AST-NEXT: | | | |-CXXMethodDecl {{[^ ]+}} <> implicit MakeNop 'TResult () const' static +// AST-NEXT: | | | `-CXXMethodDecl {{[^ ]+}} <> used MakeNop 'dx::HitObject ()' static +// AST-NEXT: | | | |-TemplateArgument type 'dx::HitObject' +// AST-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 358 +// AST-NEXT: | | | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// FCGL: %{{[^ ]+}} = call %dx.types.HitObject* @"dx.hl.op..%dx.types.HitObject* (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %{{[^ ]+}}) +// FCGL: call void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %{{[^ ]+}}) +// FCGL: call void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32, %struct.RayDesc*)"(i32 387, %dx.types.HitObject* %{{[^ ]+}}, i32 0, i32 1, %struct.RayDesc* %{{[^ ]+}}) +// FCGL: call void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32, %struct.RayDesc*)"(i32 387, %dx.types.HitObject* %{{[^ ]+}}, i32 0, i32 2, %struct.RayDesc* %{{[^ ]+}}) + +// Expect HitObject_Make* calls with identical parameters to be folded. +// DXIL: {{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop() +// DXIL-NOT: {{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeNop +// DXIL: %{{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeMiss(i32 265, i32 0, i32 1, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0x3FA99999A0000000, float 1.000000e+03) ; HitObject_MakeMiss(RayFlags,MissShaderIndex,Origin_X,Origin_Y,Origin_Z,TMin,Direction_X,Direction_Y,Direction_Z,TMax) +// DXIL-NOT: %{{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeMiss(i32 265, i32 0, i32 1 +// DXIL: %{{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeMiss(i32 265, i32 0, i32 2, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0x3FA99999A0000000, float 1.000000e+03) ; HitObject_MakeMiss(RayFlags,MissShaderIndex,Origin_X,Origin_Y,Origin_Z,TMin,Direction_X,Direction_Y,Direction_Z,TMax) + +void Use(in dx::HitObject hit) { + dx::MaybeReorderThread(hit); +} + +[shader("raygeneration")] +void main() { + dx::HitObject nop; + Use(nop); + + dx::HitObject nop2 = dx::HitObject::MakeNop(); + Use(nop2); + + RayDesc ray = {{0,0,0}, {0,0,1}, 0.05, 1000.0}; + dx::HitObject miss = dx::HitObject::MakeMiss(0, 1, ray); + Use(miss); + + dx::HitObject miss2 = dx::HitObject::MakeMiss(0, 1, ray); + Use(miss2); + + dx::HitObject miss3 = dx::HitObject::MakeMiss(0, 2, ray); + Use(miss3); +} diff --git a/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/lit.local.cfg b/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/lit.local.cfg new file mode 100644 index 0000000000..ba86568f9a --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/lit.local.cfg @@ -0,0 +1 @@ +config.unsupported = 'dxil-1-9' not in config.available_features diff --git a/tools/clang/test/DXC/Passes/DxilGen/hitobject_dxilgen.ll b/tools/clang/test/DXC/Passes/DxilGen/hitobject_dxilgen.ll index 01dafe5e86..17a968675f 100644 --- a/tools/clang/test/DXC/Passes/DxilGen/hitobject_dxilgen.ll +++ b/tools/clang/test/DXC/Passes/DxilGen/hitobject_dxilgen.ll @@ -1,9 +1,6 @@ ; RUN: %dxopt %s -hlsl-passes-resume -dxilgen -S | FileCheck %s ; REQUIRES: dxil-1-9 -; CHECK-NOT: @dx.op.hitObject_ -; CHECK-NOT: @dx.op.maybeReorderThread - ; ; Buffer Definitions: ; @@ -37,9 +34,11 @@ entry: %tmp = alloca %dx.types.HitObject, align 4 %0 = bitcast %dx.types.HitObject* %hit to i8*, !dbg !19 ; line:9 col:3 call void @llvm.lifetime.start(i64 4, i8* %0) #0, !dbg !19 ; line:9 col:3 +; CHECK: %{{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) %1 = call %dx.types.HitObject* @"dx.hl.op..%dx.types.HitObject* (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %hit), !dbg !23 ; line:9 col:17 %2 = bitcast %dx.types.HitObject* %tmp to i8*, !dbg !24 ; line:10 col:3 call void @llvm.lifetime.start(i64 4, i8* %2) #0, !dbg !24 ; line:10 col:3 +; CHECK: %{{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) call void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %tmp), !dbg !24 ; line:10 col:3 %3 = bitcast %dx.types.HitObject* %tmp to i8*, !dbg !24 ; line:10 col:3 call void @llvm.lifetime.end(i64 4, i8* %3) #0, !dbg !24 ; line:10 col:3 diff --git a/tools/clang/test/DXC/Passes/DxilGen/maybereorder_dxilgen.ll b/tools/clang/test/DXC/Passes/DxilGen/maybereorder_dxilgen.ll index f5130bca3f..ca25b1e115 100644 --- a/tools/clang/test/DXC/Passes/DxilGen/maybereorder_dxilgen.ll +++ b/tools/clang/test/DXC/Passes/DxilGen/maybereorder_dxilgen.ll @@ -1,8 +1,6 @@ ; RUN: %dxopt %s -hlsl-passes-resume -dxilgen -S | FileCheck %s ; REQUIRES: dxil-1-9 -; CHECK-NOT: @dx.op.hitObject_ -; CHECK-NOT: @dx.op.maybeReorderThread ; ; Buffer Definitions: @@ -36,6 +34,7 @@ entry: %hit = alloca %dx.types.HitObject, align 4 %0 = bitcast %dx.types.HitObject* %hit to i8*, !dbg !19 ; line:9 col:3 call void @llvm.lifetime.start(i64 4, i8* %0) #0, !dbg !19 ; line:9 col:3 +; CHECK: %{{[^ ]+}} = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) %1 = call %dx.types.HitObject* @"dx.hl.op..%dx.types.HitObject* (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %hit), !dbg !23 ; line:9 col:17 call void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32 359, %dx.types.HitObject* %hit), !dbg !24 ; line:10 col:3 call void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32)"(i32 359, %dx.types.HitObject* %hit, i32 241, i32 3), !dbg !25 ; line:11 col:3 diff --git a/tools/clang/test/DXC/Passes/ScalarReplHLSL/hitobject_make_scalarrepl.ll b/tools/clang/test/DXC/Passes/ScalarReplHLSL/hitobject_make_scalarrepl.ll new file mode 100644 index 0000000000..89ee886c2e --- /dev/null +++ b/tools/clang/test/DXC/Passes/ScalarReplHLSL/hitobject_make_scalarrepl.ll @@ -0,0 +1,142 @@ +; RUN: %dxopt %s -hlsl-passes-resume -scalarrepl-param-hlsl -S | FileCheck %s + +; +; Buffer Definitions: +; +; cbuffer $Globals +; { +; +; [0 x i8] (type annotation not present) +; +; } +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; $Globals cbuffer NA NA CB0 cb4294967295 1 +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%ConstantBuffer = type opaque +%dx.types.HitObject = type { i8* } +%"class.dx::HitObject" = type { i32 } +%struct.RayDesc = type { <3 x float>, float, <3 x float>, float } + +@"$Globals" = external constant %ConstantBuffer + +; Function Attrs: nounwind +define void @"\01?main@@YAXXZ"() #0 { +entry: + %hit = alloca %dx.types.HitObject, align 4 + %tmp = alloca %dx.types.HitObject, align 4 + %ray = alloca %struct.RayDesc, align 4 +; CHECK-NOT: %{{[^ ]+}} = alloca %struct.RayDesc + %tmp2 = alloca %dx.types.HitObject, align 4 +; CHECK: %[[HIT0:[^ ]+]] = alloca %dx.types.HitObject, align 4 +; CHECK: %[[HIT1:[^ ]+]] = alloca %dx.types.HitObject, align 4 +; CHECK: %[[HIT2:[^ ]+]] = alloca %dx.types.HitObject, align 4 + %0 = bitcast %dx.types.HitObject* %hit to i8*, !dbg !23 ; line:42 col:3 + call void @llvm.lifetime.start(i64 4, i8* %0) #0, !dbg !23 ; line:42 col:3 +; CHECK: %[[THIS0:[^ ]+]] = call %dx.types.HitObject* @"dx.hl.op..%dx.types.HitObject* (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %[[HIT0]]) +; CHECK-NOT: %[[THIS0]] + %1 = call %dx.types.HitObject* @"dx.hl.op..%dx.types.HitObject* (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %hit), !dbg !27 ; line:42 col:17 + %2 = bitcast %dx.types.HitObject* %tmp to i8*, !dbg !28 ; line:43 col:3 + call void @llvm.lifetime.start(i64 4, i8* %2) #0, !dbg !28 ; line:43 col:3 +; CHECK: call void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %[[HIT1]]) + call void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32 358, %dx.types.HitObject* %tmp), !dbg !28 ; line:43 col:3 + %3 = bitcast %dx.types.HitObject* %tmp to i8*, !dbg !28 ; line:43 col:3 + call void @llvm.lifetime.end(i64 4, i8* %3) #0, !dbg !28 ; line:43 col:3 + %4 = bitcast %struct.RayDesc* %ray to i8*, !dbg !29 ; line:44 col:3 + call void @llvm.lifetime.start(i64 32, i8* %4) #0, !dbg !29 ; line:44 col:3 + %5 = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %ray, i32 0, i32 0, !dbg !30 ; line:44 col:17 + store <3 x float> zeroinitializer, <3 x float>* %5, !dbg !30 ; line:44 col:17 + %6 = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %ray, i32 0, i32 1, !dbg !30 ; line:44 col:17 + store float 0.000000e+00, float* %6, !dbg !30 ; line:44 col:17 + %7 = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %ray, i32 0, i32 2, !dbg !30 ; line:44 col:17 + store <3 x float> , <3 x float>* %7, !dbg !30 ; line:44 col:17 + %8 = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %ray, i32 0, i32 3, !dbg !30 ; line:44 col:17 + store float 1.000000e+03, float* %8, !dbg !30 ; line:44 col:17 + %9 = bitcast %dx.types.HitObject* %tmp2 to i8*, !dbg !31 ; line:45 col:3 + call void @llvm.lifetime.start(i64 4, i8* %9) #0, !dbg !31 ; line:45 col:3 +; CHECK: store <3 x float> zeroinitializer, <3 x float>* %[[pRDO:[^ ]+]], +; CHECK: store float 0.000000e+00, float* %[[pRDTMIN:[^ ]+]], +; CHECK: store <3 x float> , <3 x float>* %[[pRDD:[^ ]+]], +; CHECK: store float 1.000000e+03, float* %[[pRDTMAX:[^ ]+]], +; CHECK-DAG: %[[RDO:[^ ]+]] = load <3 x float>, <3 x float>* %[[pRDO]], +; CHECK-DAG: %[[RDTMIN:[^ ]+]] = load float, float* %[[pRDTMIN]], +; CHECK-DAG: %[[RDD:[^ ]+]] = load <3 x float>, <3 x float>* %[[pRDD]], +; CHECK-DAG: %[[RDTMAX:[^ ]+]] = load float, float* %[[pRDTMAX]], +; CHECK: call void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32, <3 x float>, float, <3 x float>, float)"(i32 387, %dx.types.HitObject* %[[HIT2]], i32 0, i32 1, <3 x float> %[[RDO]], float %[[RDTMIN]], <3 x float> %[[RDD]], float %[[RDTMAX]]) + call void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32, %struct.RayDesc*)"(i32 387, %dx.types.HitObject* %tmp2, i32 0, i32 1, %struct.RayDesc* %ray), !dbg !31 ; line:45 col:3 + %10 = bitcast %dx.types.HitObject* %tmp2 to i8*, !dbg !31 ; line:45 col:3 + call void @llvm.lifetime.end(i64 4, i8* %10) #0, !dbg !31 ; line:45 col:3 + %11 = bitcast %struct.RayDesc* %ray to i8*, !dbg !32 ; line:46 col:1 + call void @llvm.lifetime.end(i64 32, i8* %11) #0, !dbg !32 ; line:46 col:1 + %12 = bitcast %dx.types.HitObject* %hit to i8*, !dbg !32 ; line:46 col:1 + call void @llvm.lifetime.end(i64 4, i8* %12) #0, !dbg !32 ; line:46 col:1 + ret void, !dbg !32 ; line:46 col:1 +} + +; Function Attrs: nounwind +declare void @llvm.lifetime.start(i64, i8* nocapture) #0 + +; Function Attrs: nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) #0 + +; Function Attrs: nounwind +declare %dx.types.HitObject* @"dx.hl.op..%dx.types.HitObject* (i32, %dx.types.HitObject*)"(i32, %dx.types.HitObject*) #0 + +; Function Attrs: nounwind +declare void @"dx.hl.op..void (i32, %dx.types.HitObject*)"(i32, %dx.types.HitObject*) #0 + +; Function Attrs: nounwind +declare void @"dx.hl.op..void (i32, %dx.types.HitObject*, i32, i32, %struct.RayDesc*)"(i32, %dx.types.HitObject*, i32, i32, %struct.RayDesc*) #0 + +attributes #0 = { nounwind } + +!llvm.module.flags = !{!0} +!pauseresume = !{!1} +!dx.version = !{!2} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.typeAnnotations = !{!4, !12} +!dx.entryPoints = !{!16} +!dx.fnprops = !{!20} +!dx.options = !{!21, !22} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"} +!2 = !{i32 1, i32 9} +!3 = !{!"lib", i32 6, i32 9} +!4 = !{i32 0, %"class.dx::HitObject" undef, !5, %struct.RayDesc undef, !7} +!5 = !{i32 4, !6} +!6 = !{i32 6, !"h", i32 3, i32 0, i32 7, i32 4} +!7 = !{i32 32, !8, !9, !10, !11} +!8 = !{i32 6, !"Origin", i32 3, i32 0, i32 7, i32 9, i32 13, i32 3} +!9 = !{i32 6, !"TMin", i32 3, i32 12, i32 7, i32 9} +!10 = !{i32 6, !"Direction", i32 3, i32 16, i32 7, i32 9, i32 13, i32 3} +!11 = !{i32 6, !"TMax", i32 3, i32 28, i32 7, i32 9} +!12 = !{i32 1, void ()* @"\01?main@@YAXXZ", !13} +!13 = !{!14} +!14 = !{i32 1, !15, !15} +!15 = !{} +!16 = !{null, !"", null, !17, null} +!17 = !{null, null, !18, null} +!18 = !{!19} +!19 = !{i32 0, %ConstantBuffer* @"$Globals", !"$Globals", i32 0, i32 -1, i32 1, i32 0, null} +!20 = !{void ()* @"\01?main@@YAXXZ", i32 7} +!21 = !{i32 -2147483584} +!22 = !{i32 -1} +!23 = !DILocation(line: 42, column: 3, scope: !24) +!24 = !DISubprogram(name: "main", scope: !25, file: !25, line: 41, type: !26, isLocal: false, isDefinition: true, scopeLine: 41, flags: DIFlagPrototyped, isOptimized: false, function: void ()* @"\01?main@@YAXXZ") +!25 = !DIFile(filename: "tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make_ast.hlsl", directory: "") +!26 = !DISubroutineType(types: !15) +!27 = !DILocation(line: 42, column: 17, scope: !24) +!28 = !DILocation(line: 43, column: 3, scope: !24) +!29 = !DILocation(line: 44, column: 3, scope: !24) +!30 = !DILocation(line: 44, column: 17, scope: !24) +!31 = !DILocation(line: 45, column: 3, scope: !24) +!32 = !DILocation(line: 46, column: 1, scope: !24) \ No newline at end of file diff --git a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make.hlsl deleted file mode 100644 index 4e09b770ec..0000000000 --- a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make.hlsl +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %dxc -T lib_6_9 -E main %s | FileCheck %s -// REQUIRES: dxil-1-9 - -// TODO: Implement lowering for dx::HitObject::MakeNop - -// CHECK-NOT: call - -[shader("raygeneration")] -void main() { - dx::HitObject hit; - dx::HitObject::MakeNop(); -} diff --git a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make_ast.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make_ast.hlsl deleted file mode 100644 index fd2fbc5974..0000000000 --- a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/hitobject_make_ast.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %dxc -T lib_6_9 -E main %s -ast-dump-implicit | FileCheck %s - -// CHECK: | |-CXXRecordDecl {{[^ ]+}} <> implicit referenced class HitObject definition -// CHECK-NEXT: | | |-FinalAttr {{[^ ]+}} <> Implicit final -// CHECK-NEXT: | | |-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" -// CHECK-NEXT: | | |-HLSLHitObjectAttr {{[^ ]+}} <> Implicit -// CHECK-NEXT: | | |-FieldDecl {{[^ ]+}} <> implicit h 'int' -// CHECK-NEXT: | | |-CXXConstructorDecl {{[^ ]+}} <> used HitObject 'void ()' -// CHECK-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 358 -// CHECK-NEXT: | | | `-HLSLCXXOverloadAttr {{[^ ]+}} <> Implicit - -// CHECK: | | |-FunctionTemplateDecl {{[^ ]+}} <> MakeNop -// CHECK-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TResult -// CHECK-NEXT: | | | |-CXXMethodDecl {{[^ ]+}} <> implicit MakeNop 'TResult () const' static -// CHECK-NEXT: | | | `-CXXMethodDecl {{[^ ]+}} <> used MakeNop 'dx::HitObject ()' static -// CHECK-NEXT: | | | |-TemplateArgument type 'dx::HitObject' -// CHECK-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 358 -// CHECK-NEXT: | | | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" - -[shader("raygeneration")] -void main() { - dx::HitObject hit; - dx::HitObject::MakeNop(); -} diff --git a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder.hlsl deleted file mode 100644 index 8824cffaec..0000000000 --- a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder.hlsl +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %dxc -T lib_6_9 -E main %s | FileCheck %s - -// TODO: Implement lowering for dx::MaybeReorderThread - -// CHECK-NOT: call - -[shader("raygeneration")] -void main() { - dx::HitObject hit; - dx::MaybeReorderThread(hit); - dx::MaybeReorderThread(hit, 0xf1, 3); - dx::MaybeReorderThread(0xf2, 7); -} diff --git a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder_ast.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder_ast.hlsl deleted file mode 100644 index d570ef021f..0000000000 --- a/tools/clang/test/HLSLFileCheck/hlsl/objects/HitObject/maybereorder_ast.hlsl +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %dxc -T lib_6_9 -E main %s -ast-dump-implicit | FileCheck %s - -// CHECK: |-FunctionDecl {{[^ ]+}} <> implicit used MaybeReorderThread 'void (dx::HitObject)' extern -// CHECK-NEXT: | |-ParmVarDecl {{[^ ]+}} <> HitObject 'dx::HitObject':'dx::HitObject' -// CHECK-NEXT: | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 359 -// CHECK-NEXT: | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" - -// CHECK: |-FunctionDecl {{[^ ]+}} <> implicit used MaybeReorderThread 'void (dx::HitObject, unsigned int, unsigned int)' extern -// CHECK-NEXT: | |-ParmVarDecl {{[^ ]+}} <> HitObject 'dx::HitObject':'dx::HitObject' -// CHECK-NEXT: | |-ParmVarDecl {{[^ ]+}} <> CoherenceHint 'unsigned int' -// CHECK-NEXT: | |-ParmVarDecl {{[^ ]+}} <> NumCoherenceHintBitsFromLSB 'unsigned int' -// CHECK-NEXT: | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 359 -// CHECK-NEXT: | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" - -// CHECK: `-FunctionDecl {{[^ ]+}} <> implicit used MaybeReorderThread 'void (unsigned int, unsigned int)' extern -// CHECK-NEXT: |-ParmVarDecl {{[^ ]+}} <> CoherenceHint 'unsigned int' -// CHECK-NEXT: |-ParmVarDecl {{[^ ]+}} <> NumCoherenceHintBitsFromLSB 'unsigned int' -// CHECK-NEXT: |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 359 -// CHECK-NEXT: `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" - - -[shader("raygeneration")] -void main() { - dx::HitObject hit; - dx::MaybeReorderThread(hit); - dx::MaybeReorderThread(hit, 0xf1, 3); - dx::MaybeReorderThread(0xf2, 7); -} \ No newline at end of file From b93f6a46fd78fe5557f7a5263d8f4885ea3930fd Mon Sep 17 00:00:00 2001 From: alecardoso-tech Date: Fri, 18 Apr 2025 14:59:52 -0700 Subject: [PATCH 4/7] Moved HANDLE management to Test Class Constructor and Destructor (#7357) Test class `ShaderOpTest` had a `HANDLE` not closed after `RunShaderOp` test ran. Created a constructor and destructor for the Test Class to manage the `HANDLE`. --- tools/clang/unittests/HLSLExec/ShaderOpTest.cpp | 13 +++++++++---- tools/clang/unittests/HLSLExec/ShaderOpTest.h | 3 +++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/clang/unittests/HLSLExec/ShaderOpTest.cpp b/tools/clang/unittests/HLSLExec/ShaderOpTest.cpp index e6c9b10f6c..8dde3faa0b 100644 --- a/tools/clang/unittests/HLSLExec/ShaderOpTest.cpp +++ b/tools/clang/unittests/HLSLExec/ShaderOpTest.cpp @@ -258,6 +258,15 @@ void CommandListRefs::CreateForDevice(ID3D12Device *pDevice, bool compute) { IID_PPV_ARGS(&List))); } +ShaderOpTest::ShaderOpTest() { + m_hFence = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (m_hFence == nullptr) { + AtlThrow(HRESULT_FROM_WIN32(GetLastError())); + } +} + +ShaderOpTest::~ShaderOpTest() { CloseHandle(m_hFence); } + void ShaderOpTest::CopyBackResources() { CommandListRefs ResCommandList; ResCommandList.CreateForDevice(m_pDevice, m_pShaderOp->IsCompute()); @@ -423,10 +432,6 @@ void ShaderOpTest::CreateDevice() { CHECK_HR(m_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void **)&m_pFence)); m_pFence->SetName(L"ShaderOpTest Fence"); - m_hFence = CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (m_hFence == nullptr) { - AtlThrow(HRESULT_FROM_WIN32(GetLastError())); - } } static void InitByteCode(D3D12_SHADER_BYTECODE *pBytecode, ID3D10Blob *pBlob) { diff --git a/tools/clang/unittests/HLSLExec/ShaderOpTest.h b/tools/clang/unittests/HLSLExec/ShaderOpTest.h index e65bd9e4e5..b71ee08765 100644 --- a/tools/clang/unittests/HLSLExec/ShaderOpTest.h +++ b/tools/clang/unittests/HLSLExec/ShaderOpTest.h @@ -275,6 +275,9 @@ class ShaderOpTest { typedef std::function TShaderCallbackFn; + + ShaderOpTest(); + ~ShaderOpTest(); void GetPipelineStats(D3D12_QUERY_DATA_PIPELINE_STATISTICS *pStats); void GetReadBackData(LPCSTR pResourceName, MappedData *pData); void RunShaderOp(ShaderOp *pShaderOp); From b4a3076caa92c4e9ed05761cbcd2141591fb3f89 Mon Sep 17 00:00:00 2001 From: Chris B Date: Mon, 21 Apr 2025 12:23:02 -0500 Subject: [PATCH 5/7] Revert ADO pipelines to Ubuntu 22.04 temporarily (#7365) DXC seems to be building inocrrectly with GCC-13 and later, which is causing our pre-merge testing on 24.04 to fail. This will take some time to sort out, so in the meantime I'm reverting to 22.04 on our pipelines. --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 33c5349f9e..7967fa03e3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -52,7 +52,7 @@ stages: variables: macOS: macOS-latest - linux: Ubuntu-latest + linux: Ubuntu-22.04 # FIXME: #7364, DXC does not build correctly with GCC 13+ strategy: matrix: From 8988e473465454f7a6dbc55223c7655c1b5af973 Mon Sep 17 00:00:00 2001 From: Simon Moll Date: Tue, 22 Apr 2025 18:31:31 +0200 Subject: [PATCH 6/7] [SER] Diagnose payload in HitObject::TraceRay|Invoke (#7356) - Generalize raypayload validation to HitObject::TraceRay|Invoke - Reject non-numeric payload types in [HitObject::]TraceRay|Invoke Specification: https://github.com/microsoft/hlsl-specs/blob/main/proposals/0027-shader-execution-reordering.md Bug: #7234 [SER] Diagnose and validate illegal use of HitObject in unsupported contexts --- tools/clang/lib/Sema/SemaDXR.cpp | 141 +++++++++++------- .../hitobject_traceinvoke_payload.hlsl | 27 ++++ .../hitobject_traceinvoke_payload_udt.hlsl | 22 +++ 3 files changed, 133 insertions(+), 57 deletions(-) create mode 100644 tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload.hlsl create mode 100644 tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl diff --git a/tools/clang/lib/Sema/SemaDXR.cpp b/tools/clang/lib/Sema/SemaDXR.cpp index 36ab55ea10..e5b2140cca 100644 --- a/tools/clang/lib/Sema/SemaDXR.cpp +++ b/tools/clang/lib/Sema/SemaDXR.cpp @@ -28,6 +28,7 @@ #include "dxc/DXIL/DxilConstants.h" #include "dxc/DXIL/DxilShaderModel.h" +#include "dxc/HlslIntrinsicOp.h" using namespace clang; using namespace sema; @@ -49,9 +50,9 @@ struct PayloadUse { const MemberExpr *Member = nullptr; }; -struct TraceRayCall { - TraceRayCall() = default; - TraceRayCall(const CallExpr *Call, const CFGBlock *Parent) +struct PayloadBuiltinCall { + PayloadBuiltinCall() = default; + PayloadBuiltinCall(const CallExpr *Call, const CFGBlock *Parent) : Call(Call), Parent(Parent) {} const CallExpr *Call = nullptr; const CFGBlock *Parent = nullptr; @@ -71,7 +72,7 @@ struct DxrShaderDiagnoseInfo { const FunctionDecl *funcDecl; const VarDecl *Payload; DXIL::PayloadAccessShaderStage Stage; - std::vector TraceCalls; + std::vector PayloadBuiltinCalls; std::map> WritesPerField; std::map> ReadsPerField; std::vector PayloadAsCallArg; @@ -121,24 +122,42 @@ GetPayloadQualifierForStage(FieldDecl *Field, return DXIL::PayloadAccessQualifier::NoAccess; } -// Returns the declaration of the payload used in a TraceRay call -const VarDecl *GetPayloadParameterForTraceCall(const CallExpr *Trace) { - const Decl *callee = Trace->getCalleeDecl(); - if (!callee) +static int GetPayloadParamIdxForIntrinsic(const FunctionDecl *FD) { + HLSLIntrinsicAttr *IntrinAttr = FD->getAttr(); + if (!IntrinAttr) + return -1; + switch ((IntrinsicOp)IntrinAttr->getOpcode()) { + default: + return -1; + case IntrinsicOp::IOP_TraceRay: + case IntrinsicOp::MOP_DxHitObject_TraceRay: + case IntrinsicOp::MOP_DxHitObject_Invoke: + return FD->getNumParams() - 1; + } +} + +static bool IsBuiltinWithPayload(const FunctionDecl *FD) { + return GetPayloadParamIdxForIntrinsic(FD) >= 0; +} + +// Returns the declaration of the payload used in a call to TraceRay, +// HitObject::TraceRay or HitObject::Invoke. +const VarDecl *GetPayloadParameterForBuiltinCall(const CallExpr *Call) { + const Decl *Callee = Call->getCalleeDecl(); + if (!Callee) return nullptr; - if (!isa(callee)) + if (!isa(Callee)) return nullptr; - const FunctionDecl *FD = cast(callee); + int PldParamIdx = GetPayloadParamIdxForIntrinsic(cast(Callee)); + if (PldParamIdx < 0) + return nullptr; - if (FD->isImplicit() && FD->getName() == "TraceRay") { - const Stmt *Param = IgnoreParensAndDecay(Trace->getArg(7)); - if (const DeclRefExpr *ParamRef = dyn_cast(Param)) { - if (const VarDecl *Decl = dyn_cast(ParamRef->getDecl())) - return Decl; - } - } + const Stmt *Param = IgnoreParensAndDecay(Call->getArg(PldParamIdx)); + if (const DeclRefExpr *ParamRef = dyn_cast(Param)) + if (const VarDecl *Decl = dyn_cast(ParamRef->getDecl())) + return Decl; return nullptr; } @@ -190,12 +209,9 @@ void CollectReadsWritesAndCallsForPayload(const Stmt *S, } } -// Collects all TraceRay calls. -void CollectTraceRayCalls(const Stmt *S, DxrShaderDiagnoseInfo &Info, - const CFGBlock *Block) { - // TraceRay has void as return type so it should never be something else - // than a plain CallExpr. - +// Collects all calls to TraceRay, HitObject::TraceRay and HitObject::Invoke. +void CollectBuiltinCallsWithPayload(const Stmt *S, DxrShaderDiagnoseInfo &Info, + const CFGBlock *Block) { if (const CallExpr *Call = dyn_cast(S)) { const Decl *Callee = Call->getCalleeDecl(); @@ -204,11 +220,8 @@ void CollectTraceRayCalls(const Stmt *S, DxrShaderDiagnoseInfo &Info, const FunctionDecl *CalledFunction = cast(Callee); - // Ignore trace calls here. - if (CalledFunction->isImplicit() && - CalledFunction->getName() == "TraceRay") { - Info.TraceCalls.push_back({Call, Block}); - } + if (IsBuiltinWithPayload(CalledFunction)) + Info.PayloadBuiltinCalls.push_back({Call, Block}); } } @@ -528,13 +541,14 @@ void TraverseCFG(const CFGBlock &Block, Action PerElementAction, } } -// Forward traverse the CFG and collect calls to TraceRay. -void ForwardTraverseCFGAndCollectTraceCalls( +// Forward traverse the CFG and collect calls to TraceRay, HitObject::TraceRay +// and HitObject::Invoke. +void ForwardTraverseCFGAndCollectBuiltinCallsWithPayload( const CFGBlock &Block, DxrShaderDiagnoseInfo &Info, std::set &Visited) { auto Action = [&Info](const CFGBlock &Block, const CFGElement &Element) { if (Optional S = Element.getAs()) { - CollectTraceRayCalls(S->getStmt(), Info, &Block); + CollectBuiltinCallsWithPayload(S->getStmt(), Info, &Block); } }; @@ -664,9 +678,9 @@ DiagnosePayloadAsFunctionArg( const FunctionDecl *CalledFunction = cast(Callee); // Ignore trace calls here. - if (CalledFunction->isImplicit() && - CalledFunction->getName() == "TraceRay") { - Info.TraceCalls.push_back(TraceRayCall{Call, Use.Parent}); + if (IsBuiltinWithPayload(CalledFunction)) { + Info.PayloadBuiltinCalls.push_back( + PayloadBuiltinCall{Call, Use.Parent}); continue; } @@ -789,10 +803,12 @@ void HandlePayloadInitializer(DxrShaderDiagnoseInfo &Info) { } } -// Emit diagnostics for a TraceRay call. -void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, - const TraceRayCall &Trace, DominatorTree &DT) { - // For each TraceRay call check if write(caller) fields are written. +// Emit diagnostics for this call to either TraceRay, HitObject::TraceRay or +// HitObject::Invoke. +void DiagnoseBuiltinCallWithPayload(Sema &S, const VarDecl *Payload, + const PayloadBuiltinCall &PldCall, + DominatorTree &DT) { + // For each call check if write(caller) fields are written. const DXIL::PayloadAccessShaderStage CallerStage = DXIL::PayloadAccessShaderStage::Caller; @@ -810,6 +826,13 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, return; } + // Verify that the payload type is legal + if (!hlsl::IsHLSLCopyableAnnotatableRecord(Payload->getType())) { + S.Diag(Payload->getLocation(), diag::err_payload_attrs_must_be_udt) + << /*payload|attributes|callable*/ 0 << Payload; + return; + } + if (ContainsLongVector(Payload->getType())) { const unsigned PayloadParametersIdx = 10; S.Diag(Payload->getLocation(), diag::err_hlsl_unsupported_long_vector) @@ -832,12 +855,12 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, std::set Visited; - const CFGBlock *Parent = Trace.Parent; + const CFGBlock *Parent = PldCall.Parent; Visited.insert(Parent); - // Collect payload accesses in the same block until we reach the TraceRay call + // Collect payload accesses in the same block until we reach the call for (auto Element : *Parent) { if (Optional S = Element.getAs()) { - if (S->getStmt() == Trace.Call) + if (S->getStmt() == PldCall.Call) break; CollectReadsWritesAndCallsForPayload(S->getStmt(), TraceInfo, Parent); } @@ -850,10 +873,12 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, BackwardTraverseCFGAndCollectReadsWrites(*Pred, TraceInfo, Visited); } + int PldArgIdx = PldCall.Call->getNumArgs() - 1; + // Warn if a writeable field has not been written. for (const FieldDecl *Field : WriteableFields) { if (!TraceInfo.WritesPerField.count(Field)) { - S.Diag(Trace.Call->getArg(7)->getExprLoc(), + S.Diag(PldCall.Call->getArg(PldArgIdx)->getExprLoc(), diag::warn_hlsl_payload_access_no_write_for_trace_payload) << Field->getName(); } @@ -862,7 +887,7 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, for (const FieldDecl *Field : NonWriteableFields) { if (TraceInfo.WritesPerField.count(Field)) { S.Diag( - Trace.Call->getArg(7)->getExprLoc(), + PldCall.Call->getArg(PldArgIdx)->getExprLoc(), diag::warn_hlsl_payload_access_write_but_no_write_for_trace_payload) << Field->getName(); } @@ -878,7 +903,7 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, bool CallFound = false; for (auto Element : *Parent) { // TODO: reverse iterate? if (Optional S = Element.getAs()) { - if (S->getStmt() == Trace.Call) { + if (S->getStmt() == PldCall.Call) { CallFound = true; continue; } @@ -895,7 +920,7 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, for (const FieldDecl *Field : ReadableFields) { if (!TraceInfo.ReadsPerField.count(Field)) { - S.Diag(Trace.Call->getArg(7)->getExprLoc(), + S.Diag(PldCall.Call->getArg(PldArgIdx)->getExprLoc(), diag::warn_hlsl_payload_access_read_but_no_read_after_trace) << Field->getName(); } @@ -928,27 +953,29 @@ void DiagnoseTraceCall(Sema &S, const VarDecl *Payload, } } -// Emit diagnostics for all TraceRay calls. -void DiagnoseTraceCalls(Sema &S, CFG &ShaderCFG, DominatorTree &DT, - DxrShaderDiagnoseInfo &Info) { - // Collect TraceRay calls in the shader. +// Emit diagnostics for all calls to TraceRay, HitObject::TraceRay or +// HitObject::Invoke. +void DiagnoseBuiltinCallsWithPayload(Sema &S, CFG &ShaderCFG, DominatorTree &DT, + DxrShaderDiagnoseInfo &Info) { + // Collect calls with payload in the shader. std::set Visited; - ForwardTraverseCFGAndCollectTraceCalls(ShaderCFG.getEntry(), Info, Visited); + ForwardTraverseCFGAndCollectBuiltinCallsWithPayload(ShaderCFG.getEntry(), + Info, Visited); std::set Diagnosed; - for (const TraceRayCall &TraceCall : Info.TraceCalls) { - if (Diagnosed.count(TraceCall.Call)) + for (const PayloadBuiltinCall &PldCall : Info.PayloadBuiltinCalls) { + if (Diagnosed.count(PldCall.Call)) continue; - Diagnosed.insert(TraceCall.Call); + Diagnosed.insert(PldCall.Call); - const VarDecl *Payload = GetPayloadParameterForTraceCall(TraceCall.Call); - DiagnoseTraceCall(S, Payload, TraceCall, DT); + const VarDecl *Payload = GetPayloadParameterForBuiltinCall(PldCall.Call); + DiagnoseBuiltinCallWithPayload(S, Payload, PldCall, DT); } } // Emit diagnostics for all access to the payload of a shader, -// and the input to TraceRay calls. +// and the input to TraceRay, HitObject::TraceRay or HitObject::Invoke calls. std::vector DiagnosePayloadAccess(Sema &S, DxrShaderDiagnoseInfo &Info, const std::set &FieldsToIgnoreRead, @@ -1012,7 +1039,7 @@ DiagnosePayloadAccess(Sema &S, DxrShaderDiagnoseInfo &Info, DiagnosePayloadReads(S, TheCFG, DT, Info, NonReadableFields); } - DiagnoseTraceCalls(S, TheCFG, DT, Info); + DiagnoseBuiltinCallsWithPayload(S, TheCFG, DT, Info); return WrittenFields; } diff --git a/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload.hlsl b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload.hlsl new file mode 100644 index 0000000000..f4781bc796 --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload.hlsl @@ -0,0 +1,27 @@ +// RUN: %dxc -T lib_6_9 %s -D TEST_NUM=0 %s -verify +// RUN: %dxc -T lib_6_9 %s -D TEST_NUM=1 %s -verify + +RaytracingAccelerationStructure scene : register(t0); + +struct Payload +{ + int a : read (caller, closesthit, miss) : write(caller, closesthit, miss); +}; + +struct Attribs +{ + float2 barys; +}; + +[shader("raygeneration")] +void RayGen() +{ +// expected-error@+1{{type 'Payload' used as payload requires that it is annotated with the [raypayload] attribute}} + Payload payload_in_rg; + RayDesc ray; +#if TEST_NUM == 0 + dx::HitObject::TraceRay( scene, RAY_FLAG_NONE, 0xff, 0, 1, 0, ray, payload_in_rg ); +#else + dx::HitObject::Invoke( dx::HitObject(), payload_in_rg ); +#endif +} \ No newline at end of file diff --git a/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl new file mode 100644 index 0000000000..e89e33a78f --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl @@ -0,0 +1,22 @@ +// RUN: %dxc -T lib_6_9 %s -verify + +struct +[raypayload] +Payload +{ + int a : read(caller, closesthit, miss) : write(caller, closesthit, miss); + dx::HitObject hit; +}; + +struct Attribs +{ + float2 barys; +}; + +[shader("raygeneration")] +void RayGen() +{ + // expected-error@+1{{payload parameter 'payload_in_rg' must be a user-defined type composed of only numeric types}} + Payload payload_in_rg; + dx::HitObject::Invoke( dx::HitObject(), payload_in_rg ); +} \ No newline at end of file From f19b5da54170210e3cbc7f080be3f080abc52505 Mon Sep 17 00:00:00 2001 From: Simon Moll Date: Tue, 22 Apr 2025 18:32:11 +0200 Subject: [PATCH 7/7] [SER] TraceRay|Invoke HLSL -> DXIL lowering (#7355) Lowering for - HitObject::TraceRay - HitObject::Invoke Specification: https://github.com/microsoft/hlsl-specs/blob/main/proposals/0027-shader-execution-reordering.md DXC SER implementation tracker:: #7214 --- include/dxc/DXIL/DxilConstants.h | 5 + include/dxc/HLSL/HLOperations.h | 4 + lib/HLSL/HLOperationLower.cpp | 126 ++++++++----- .../Scalar/ScalarReplAggregatesHLSL.cpp | 2 + tools/clang/lib/Sema/SemaHLSL.cpp | 2 + .../HitObject/hitobject_traceinvoke.hlsl | 102 +++++++++++ .../DxilGen/hitobject_traceinvoke_dxilgen.ll | 167 ++++++++++++++++++ 7 files changed, 367 insertions(+), 41 deletions(-) create mode 100644 tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_traceinvoke.hlsl create mode 100644 tools/clang/test/DXC/Passes/DxilGen/hitobject_traceinvoke_dxilgen.ll diff --git a/include/dxc/DXIL/DxilConstants.h b/include/dxc/DXIL/DxilConstants.h index 8c73328fbd..3752274f18 100644 --- a/include/dxc/DXIL/DxilConstants.h +++ b/include/dxc/DXIL/DxilConstants.h @@ -1556,6 +1556,11 @@ const unsigned kMSStoreOutputColOpIdx = 3; const unsigned kMSStoreOutputVIdxOpIdx = 4; const unsigned kMSStoreOutputValOpIdx = 5; +// HitObject::TraceRay +const unsigned kHitObjectTraceRay_RayDescOpIdx = 7; +const unsigned kHitObjectTraceRay_PayloadOpIdx = 15; +const unsigned kHitObjectTraceRay_NumOp = 16; + // TODO: add operand index for all the OpCodeClass. } // namespace OperandIndex diff --git a/include/dxc/HLSL/HLOperations.h b/include/dxc/HLSL/HLOperations.h index a7db8612a6..970ddd3e85 100644 --- a/include/dxc/HLSL/HLOperations.h +++ b/include/dxc/HLSL/HLOperations.h @@ -437,6 +437,10 @@ const unsigned kAnnotateNodeRecordHandleNodeRecordPropIdx = 2; const unsigned kHitObjectMakeMiss_NumOp = 8; const unsigned kHitObjectMakeMissRayDescOpIdx = 4; +// HitObject::TraceRay +const unsigned kHitObjectTraceRay_RayDescOpIdx = 8; +const unsigned kHitObjectTraceRay_NumOp = 10; + } // namespace HLOperandIndex llvm::Function *GetOrCreateHLFunction(llvm::Module &M, diff --git a/lib/HLSL/HLOperationLower.cpp b/lib/HLSL/HLOperationLower.cpp index be45021e41..69dd803f7b 100644 --- a/lib/HLSL/HLOperationLower.cpp +++ b/lib/HLSL/HLOperationLower.cpp @@ -19,6 +19,8 @@ #include #include +#include "dxc/DXIL/DxilConstants.h" +#include "dxc/DXIL/DxilInstructions.h" #include "dxc/DXIL/DxilModule.h" #include "dxc/DXIL/DxilOperations.h" #include "dxc/DXIL/DxilResourceProperties.h" @@ -5718,23 +5720,9 @@ Value *TranslateCallShader(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode, return Builder.CreateCall(F, {opArg, ShaderIndex, Parameter}); } -Value *TranslateTraceRay(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode, - HLOperationLowerHelper &helper, - HLObjectOperationLowerHelper *pObjHelper, - bool &Translated) { - hlsl::OP *hlslOP = &helper.hlslOP; - - Value *rayDesc = CI->getArgOperand(HLOperandIndex::kTraceRayRayDescOpIdx); - Value *payLoad = CI->getArgOperand(HLOperandIndex::kTraceRayPayLoadOpIdx); - - Value *opArg = hlslOP->GetU32Const(static_cast(opcode)); - - Value *Args[DXIL::OperandIndex::kTraceRayNumOp]; - Args[0] = opArg; - for (unsigned i = 1; i < HLOperandIndex::kTraceRayRayDescOpIdx; i++) { - Args[i] = CI->getArgOperand(i); - } - IRBuilder<> Builder(CI); +static unsigned LoadRayDescElementsIntoArgs(Value **Args, hlsl::OP *OP, + IRBuilder<> &Builder, + Value *RayDescPtr, unsigned Index) { // struct RayDesc //{ // float3 Origin; @@ -5742,34 +5730,51 @@ Value *TranslateTraceRay(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode, // float3 Direction; // float TMax; //}; - Value *zeroIdx = hlslOP->GetU32Const(0); - Value *origin = Builder.CreateGEP(rayDesc, {zeroIdx, zeroIdx}); - origin = Builder.CreateLoad(origin); - unsigned index = DXIL::OperandIndex::kTraceRayRayDescOpIdx; - Args[index++] = Builder.CreateExtractElement(origin, (uint64_t)0); - Args[index++] = Builder.CreateExtractElement(origin, 1); - Args[index++] = Builder.CreateExtractElement(origin, 2); + Value *ZeroIdx = OP->GetU32Const(0); + Value *Origin = Builder.CreateGEP(RayDescPtr, {ZeroIdx, ZeroIdx}); + Origin = Builder.CreateLoad(Origin); + Args[Index++] = Builder.CreateExtractElement(Origin, (uint64_t)0); + Args[Index++] = Builder.CreateExtractElement(Origin, 1); + Args[Index++] = Builder.CreateExtractElement(Origin, 2); - Value *tmin = Builder.CreateGEP(rayDesc, {zeroIdx, hlslOP->GetU32Const(1)}); - tmin = Builder.CreateLoad(tmin); - Args[index++] = tmin; + Value *TMinPtr = Builder.CreateGEP(RayDescPtr, {ZeroIdx, OP->GetU32Const(1)}); + Args[Index++] = Builder.CreateLoad(TMinPtr); - Value *direction = - Builder.CreateGEP(rayDesc, {zeroIdx, hlslOP->GetU32Const(2)}); - direction = Builder.CreateLoad(direction); + Value *DirectionPtr = + Builder.CreateGEP(RayDescPtr, {ZeroIdx, OP->GetU32Const(2)}); + Value *Direction = Builder.CreateLoad(DirectionPtr); - Args[index++] = Builder.CreateExtractElement(direction, (uint64_t)0); - Args[index++] = Builder.CreateExtractElement(direction, 1); - Args[index++] = Builder.CreateExtractElement(direction, 2); + Args[Index++] = Builder.CreateExtractElement(Direction, (uint64_t)0); + Args[Index++] = Builder.CreateExtractElement(Direction, 1); + Args[Index++] = Builder.CreateExtractElement(Direction, 2); - Value *tmax = Builder.CreateGEP(rayDesc, {zeroIdx, hlslOP->GetU32Const(3)}); - tmax = Builder.CreateLoad(tmax); - Args[index++] = tmax; + Value *TMaxPtr = Builder.CreateGEP(RayDescPtr, {ZeroIdx, OP->GetU32Const(3)}); + Args[Index++] = Builder.CreateLoad(TMaxPtr); + return Index; +} + +Value *TranslateTraceRay(CallInst *CI, IntrinsicOp IOP, OP::OpCode OpCode, + HLOperationLowerHelper &Helper, + HLObjectOperationLowerHelper *pObjHelper, + bool &Translated) { + hlsl::OP *OP = &Helper.hlslOP; - Args[DXIL::OperandIndex::kTraceRayPayloadOpIdx] = payLoad; + Value *RayDesc = CI->getArgOperand(HLOperandIndex::kTraceRayRayDescOpIdx); + Value *PayLoad = CI->getArgOperand(HLOperandIndex::kTraceRayPayLoadOpIdx); - Type *Ty = payLoad->getType(); - Function *F = hlslOP->GetOpFunc(opcode, Ty); + Value *Args[DXIL::OperandIndex::kTraceRayNumOp]; + Args[0] = OP->GetU32Const(static_cast(OpCode)); + for (unsigned i = 1; i < HLOperandIndex::kTraceRayRayDescOpIdx; i++) + Args[i] = CI->getArgOperand(i); + + IRBuilder<> Builder(CI); + LoadRayDescElementsIntoArgs(Args, OP, Builder, RayDesc, + DXIL::OperandIndex::kTraceRayRayDescOpIdx); + + Args[DXIL::OperandIndex::kTraceRayPayloadOpIdx] = PayLoad; + + Type *Ty = PayLoad->getType(); + Function *F = OP->GetOpFunc(OpCode, Ty); return Builder.CreateCall(F, Args); } @@ -6307,7 +6312,37 @@ Value *TranslateHitObjectTraceRay(CallInst *CI, IntrinsicOp IOP, HLOperationLowerHelper &Helper, HLObjectOperationLowerHelper *pObjHelper, bool &Translated) { - return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches + hlsl::OP *OP = &Helper.hlslOP; + IRBuilder<> Builder(CI); + + const unsigned DxilNumArgs = DxilInst_HitObject_TraceRay::arg_payload + 1; + DXASSERT_NOMSG(CI->getNumArgOperands() == + HLOperandIndex::kHitObjectTraceRay_NumOp); + Value *Args[DxilNumArgs]; + Value *OpArg = OP->GetU32Const(static_cast(OpCode)); + Args[0] = OpArg; + + unsigned DestIdx = 1, SrcIdx = 1; + Value *HitObjectPtr = CI->getArgOperand(SrcIdx++); + Args[DestIdx++] = CI->getArgOperand(SrcIdx++); + for (; SrcIdx < HLOperandIndex::kHitObjectTraceRay_RayDescOpIdx; + ++SrcIdx, ++DestIdx) { + Args[DestIdx] = CI->getArgOperand(SrcIdx); + } + + Value *RayDescPtr = CI->getArgOperand(SrcIdx++); + DestIdx = LoadRayDescElementsIntoArgs(Args, OP, Builder, RayDescPtr, DestIdx); + Value *Payload = CI->getArgOperand(SrcIdx++); + Args[DestIdx++] = Payload; + + DXASSERT_NOMSG(SrcIdx == CI->getNumArgOperands()); + DXASSERT_NOMSG(DestIdx == DxilNumArgs); + + Function *F = OP->GetOpFunc(OpCode, Payload->getType()); + + Value *OutHitObject = Builder.CreateCall(F, Args); + Builder.CreateStore(OutHitObject, HitObjectPtr); + return nullptr; } Value *TranslateHitObjectInvoke(CallInst *CI, IntrinsicOp IOP, @@ -6315,7 +6350,16 @@ Value *TranslateHitObjectInvoke(CallInst *CI, IntrinsicOp IOP, HLOperationLowerHelper &Helper, HLObjectOperationLowerHelper *pObjHelper, bool &Translated) { - return nullptr; // TODO: Merge SER DXIL patches + unsigned SrcIdx = 1; + Value *HitObjectPtr = CI->getArgOperand(SrcIdx++); + Value *Payload = CI->getArgOperand(SrcIdx++); + DXASSERT_NOMSG(SrcIdx == CI->getNumArgOperands()); + + IRBuilder<> Builder(CI); + Value *HitObject = Builder.CreateLoad(HitObjectPtr); + TrivialDxilOperation(OpCode, {nullptr, HitObject, Payload}, + Payload->getType(), CI, &Helper.hlslOP); + return nullptr; } Value *TranslateHitObjectGetAttributes(CallInst *CI, IntrinsicOp IOP, diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp index e487079b94..b13e9a0f5d 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp @@ -1540,6 +1540,8 @@ void isSafeForScalarRepl(Instruction *I, uint64_t Offset, AllocaInfo &Info) { // basing on IOP? IntrinsicOp opcode = static_cast(GetHLOpcode(CI)); if (IntrinsicOp::IOP_TraceRay == opcode || + IntrinsicOp::MOP_DxHitObject_TraceRay == opcode || + IntrinsicOp::MOP_DxHitObject_Invoke == opcode || IntrinsicOp::IOP_ReportHit == opcode || IntrinsicOp::IOP_CallShader == opcode) { return MarkUnsafe(Info, User); diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 418425a468..bddf834509 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12066,8 +12066,10 @@ void Sema::DiagnoseReachableHLSLCall(CallExpr *CE, const hlsl::ShaderModel *SM, case hlsl::IntrinsicOp::MOP_TraceRayInline: DiagnoseTraceRayInline(*this, CE); break; + case hlsl::IntrinsicOp::MOP_DxHitObject_Invoke: case hlsl::IntrinsicOp::MOP_DxHitObject_MakeMiss: case hlsl::IntrinsicOp::MOP_DxHitObject_MakeNop: + case hlsl::IntrinsicOp::MOP_DxHitObject_TraceRay: DiagnoseReachableSERCall(*this, CE, EntrySK, EntryDecl, false); break; case hlsl::IntrinsicOp::IOP_DxMaybeReorderThread: diff --git a/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_traceinvoke.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_traceinvoke.hlsl new file mode 100644 index 0000000000..13bff4a3f4 --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_traceinvoke.hlsl @@ -0,0 +1,102 @@ +// RUN: %dxc -T lib_6_9 -E main %s -ast-dump-implicit | FileCheck %s --check-prefix AST +// RUN: %dxc -T lib_6_9 -E main %s -fcgl | FileCheck %s --check-prefix FCGL +// RUN: %dxc -T lib_6_9 -E main %s | FileCheck %s --check-prefix DXIL + +// AST: | | |-FunctionTemplateDecl {{[^ ]+}} <> Invoke +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TResult +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class Tho +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TPayload +// AST-NEXT: | | | |-CXXMethodDecl {{[^ ]+}} <> implicit Invoke 'TResult (Tho, TPayload &) const' static +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> ho 'Tho' +// AST-NEXT: | | | | `-ParmVarDecl {{[^ ]+}} <> Payload 'TPayload &' +// AST-NEXT: | | | `-CXXMethodDecl {{[^ ]+}} <> used Invoke 'void (dx::HitObject, Payload &)' static +// AST-NEXT: | | | |-TemplateArgument type 'void' +// AST-NEXT: | | | |-TemplateArgument type 'dx::HitObject':'dx::HitObject' +// AST-NEXT: | | | |-TemplateArgument type 'Payload' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> Invoke 'dx::HitObject':'dx::HitObject' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> ho 'Payload &&__restrict' +// AST-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 382 +// AST-NEXT: | | | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// AST: | | |-FunctionTemplateDecl {{[^ ]+}} <> TraceRay +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TResult +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TAccelerationStructure +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TRayFlags +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TInstanceInclusionMask +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TRayContributionToHitGroupIndex +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TMultiplierForGeometryContributionToHitGroupIndex +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TMissShaderIndex +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TRay +// AST-NEXT: | | | |-TemplateTypeParmDecl {{[^ ]+}} <> class TPayload +// AST-NEXT: | | | |-CXXMethodDecl {{[^ ]+}} <> implicit TraceRay 'TResult (TAccelerationStructure, TRayFlags, TInstanceInclusionMask, TRayContributionToHitGroupIndex, TMultiplierForGeometryContributionToHitGroupIndex, TMissShaderIndex, TRay, TPayload &) const' static +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> AccelerationStructure 'TAccelerationStructure' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> RayFlags 'TRayFlags' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> InstanceInclusionMask 'TInstanceInclusionMask' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> RayContributionToHitGroupIndex 'TRayContributionToHitGroupIndex' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> MultiplierForGeometryContributionToHitGroupIndex 'TMultiplierForGeometryContributionToHitGroupIndex' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> MissShaderIndex 'TMissShaderIndex' +// AST-NEXT: | | | | |-ParmVarDecl {{[^ ]+}} <> Ray 'TRay' +// AST-NEXT: | | | | `-ParmVarDecl {{[^ ]+}} <> Payload 'TPayload &' +// AST-NEXT: | | | `-CXXMethodDecl {{[^ ]+}} <> used TraceRay 'dx::HitObject (RaytracingAccelerationStructure, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, RayDesc, Payload &)' static +// AST-NEXT: | | | |-TemplateArgument type 'dx::HitObject' +// AST-NEXT: | | | |-TemplateArgument type 'RaytracingAccelerationStructure' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'unsigned int' +// AST-NEXT: | | | |-TemplateArgument type 'RayDesc' +// AST-NEXT: | | | |-TemplateArgument type 'Payload' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> TraceRay 'RaytracingAccelerationStructure' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> AccelerationStructure 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> RayFlags 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> InstanceInclusionMask 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> RayContributionToHitGroupIndex 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> MultiplierForGeometryContributionToHitGroupIndex 'unsigned int' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> MissShaderIndex 'RayDesc' +// AST-NEXT: | | | |-ParmVarDecl {{[^ ]+}} <> Ray 'Payload &&__restrict' +// AST-NEXT: | | | |-HLSLIntrinsicAttr {{[^ ]+}} <> Implicit "op" "" 389 +// AST-NEXT: | | | `-AvailabilityAttr {{[^ ]+}} <> Implicit 6.9 0 0 "" + +// FCGL: %[[HANDLE:[^ ]+]] = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.RaytracingAccelerationStructure)"(i32 14, %dx.types.Handle %{{[^ ]+}}, %dx.types.ResourceProperties { i32 16, i32 0 }, %struct.RaytracingAccelerationStructure undef) +// FCGL-NEXT: call void @"dx.hl.op..void (i32, %dx.types.HitObject*, %dx.types.Handle, i32, i32, i32, i32, i32, %struct.RayDesc*, %struct.Payload*)"(i32 389, %dx.types.HitObject* %{{[^ ]+}}, %dx.types.Handle %[[HANDLE]], i32 513, i32 1, i32 2, i32 4, i32 0, %struct.RayDesc* %{{[^ ]+}}, %struct.Payload* %{{[^ ]+}}) +// FCGL-NEXT: call void @"dx.hl.op..void (i32, %dx.types.HitObject*, %struct.Payload*)"(i32 382, %dx.types.HitObject* %{{[^ ]+}}, %struct.Payload* %{{[^ ]+}}) + +// DXIL: %[[RTAS:[^ ]+]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %{{[^ ]+}}, %dx.types.ResourceProperties { i32 16, i32 0 }) ; AnnotateHandle(res,props) resource: RTAccelerationStructure +// DXIL: %[[HIT:[^ ]+]] = call %dx.types.HitObject @dx.op.hitObject_TraceRay.struct.Payload(i32 262, %dx.types.Handle %[[RTAS]], i32 513, i32 1, i32 2, i32 4, i32 0, float 0.000000e+00, float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00, float 5.000000e+00, float 6.000000e+00, float 7.000000e+00, %struct.Payload* nonnull %{{[^ ]+}}) ; HitObject_TraceRay(accelerationStructure,rayFlags,instanceInclusionMask,rayContributionToHitGroupIndex,multiplierForGeometryContributionToHitGroupIndex,missShaderIndex,Origin_X,Origin_Y,Origin_Z,TMin,Direction_X,Direction_Y,Direction_Z,TMax,payload) +// DXIL: call void @dx.op.hitObject_Invoke.struct.Payload(i32 267, %dx.types.HitObject %[[HIT]], %struct.Payload* nonnull %{{[^ ]+}}) ; HitObject_Invoke(hitObject,payload) + +// DXIL: !dx.dxrPayloadAnnotations = !{![[MDPLD:[^ ]+]]} +// DXIL: ![[MDPLD]] = !{i32 0, %struct.Payload undef, !{{[^ ]+}}} + +RaytracingAccelerationStructure RTAS; +RWStructuredBuffer UAV : register(u0); + +struct [raypayload] +Payload { + float3 dummy : read(closesthit) : write(caller, anyhit); +}; + +[shader("raygeneration")] +void main() { + RayDesc rayDesc; + rayDesc.Origin = float3(0.0, 1.0, 2.0); + rayDesc.TMin = 3.0f; + rayDesc.Direction = float3(4.0, 5.0, 6.0); + rayDesc.TMax = 7.0f; + + Payload pld; + pld.dummy = float3(7.0, 8.0, 9.0); + + dx::HitObject hit = dx::HitObject::TraceRay( + RTAS, + RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES, + 1, + 2, + 4, + 0, + rayDesc, + pld); + + dx::HitObject::Invoke(hit, pld); +} diff --git a/tools/clang/test/DXC/Passes/DxilGen/hitobject_traceinvoke_dxilgen.ll b/tools/clang/test/DXC/Passes/DxilGen/hitobject_traceinvoke_dxilgen.ll new file mode 100644 index 0000000000..6f364a0161 --- /dev/null +++ b/tools/clang/test/DXC/Passes/DxilGen/hitobject_traceinvoke_dxilgen.ll @@ -0,0 +1,167 @@ +; RUN: %dxopt %s -hlsl-passes-resume -dxilgen -S | FileCheck %s +; REQUIRES: dxil-1-9 + +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; RTAS texture i32 ras T0t4294967295,space4294967295 1 +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%struct.RaytracingAccelerationStructure = type { i32 } +%struct.RayDesc = type { <3 x float>, float, <3 x float>, float } +%struct.Payload = type { <3 x float> } +%dx.types.HitObject = type { i8* } +%dx.types.Handle = type { i8* } +%dx.types.ResourceProperties = type { i32, i32 } +%"class.RWStructuredBuffer" = type { float } +%"class.dx::HitObject" = type { i32 } + +@"\01?RTAS@@3URaytracingAccelerationStructure@@A" = external global %struct.RaytracingAccelerationStructure, align 4 + +; Function Attrs: nounwind +define void @"\01?main@@YAXXZ"() #0 { +entry: + %rayDesc = alloca %struct.RayDesc, align 4 + %pld = alloca %struct.Payload, align 4 + %hit = alloca %dx.types.HitObject, align 4 + %0 = bitcast %struct.RayDesc* %rayDesc to i8*, !dbg !31 ; line:80 col:3 + call void @llvm.lifetime.start(i64 32, i8* %0) #0, !dbg !31 ; line:80 col:3 + %Origin = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %rayDesc, i32 0, i32 0, !dbg !35 ; line:81 col:11 + store <3 x float> , <3 x float>* %Origin, align 4, !dbg !36, !tbaa !37 ; line:81 col:18 + %TMin = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %rayDesc, i32 0, i32 1, !dbg !40 ; line:82 col:11 + store float 3.000000e+00, float* %TMin, align 4, !dbg !41, !tbaa !42 ; line:82 col:16 + %Direction = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %rayDesc, i32 0, i32 2, !dbg !44 ; line:83 col:11 + store <3 x float> , <3 x float>* %Direction, align 4, !dbg !45, !tbaa !37 ; line:83 col:21 + %TMax = getelementptr inbounds %struct.RayDesc, %struct.RayDesc* %rayDesc, i32 0, i32 3, !dbg !46 ; line:84 col:11 + store float 7.000000e+00, float* %TMax, align 4, !dbg !47, !tbaa !42 ; line:84 col:16 + %1 = bitcast %struct.Payload* %pld to i8*, !dbg !48 ; line:86 col:3 + call void @llvm.lifetime.start(i64 12, i8* %1) #0, !dbg !48 ; line:86 col:3 + %dummy = getelementptr inbounds %struct.Payload, %struct.Payload* %pld, i32 0, i32 0, !dbg !49 ; line:87 col:7 + store <3 x float> , <3 x float>* %dummy, align 4, !dbg !50, !tbaa !37 ; line:87 col:13 + %2 = bitcast %dx.types.HitObject* %hit to i8*, !dbg !51 ; line:89 col:3 + call void @llvm.lifetime.start(i64 4, i8* %2) #0, !dbg !51 ; line:89 col:3 + %3 = load %struct.RaytracingAccelerationStructure, %struct.RaytracingAccelerationStructure* @"\01?RTAS@@3URaytracingAccelerationStructure@@A", !dbg !52 ; line:89 col:23 + %4 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.RaytracingAccelerationStructure)"(i32 0, %struct.RaytracingAccelerationStructure %3), !dbg !52 ; line:89 col:23 + %5 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.RaytracingAccelerationStructure)"(i32 14, %dx.types.Handle %4, %dx.types.ResourceProperties { i32 16, i32 0 }, %struct.RaytracingAccelerationStructure zeroinitializer), !dbg !52 ; line:89 col:23 + ; CHECK: %[[ORIGINPTR:[^ ]+]] = getelementptr %struct.RayDesc, %struct.RayDesc* %[[RAYDESCPTR:[^ ]+]], i32 0, i32 0 + ; CHECK: %[[ORIGIN:[^ ]+]] = load <3 x float>, <3 x float>* %[[ORIGINPTR]] + ; CHECK: %[[O0:[^ ]+]] = extractelement <3 x float> %[[ORIGIN]], i64 0 + ; CHECK: %[[O1:[^ ]+]] = extractelement <3 x float> %[[ORIGIN]], i64 1 + ; CHECK: %[[O2:[^ ]+]] = extractelement <3 x float> %[[ORIGIN]], i64 2 + ; CHECK: %[[TMINPTR:[^ ]+]] = getelementptr %struct.RayDesc, %struct.RayDesc* %[[RAYDESCPTR]], i32 0, i32 1 + ; CHECK: %[[TMIN:[^ ]+]] = load float, float* %[[TMINPTR]] + ; CHECK: %[[DIRPTR:[^ ]+]] = getelementptr %struct.RayDesc, %struct.RayDesc* %[[RAYDESCPTR]], i32 0, i32 2 + ; CHECK: %[[DIR:[^ ]+]] = load <3 x float>, <3 x float>* %[[DIRPTR]] + ; CHECK: %[[D0:[^ ]+]] = extractelement <3 x float> %[[DIR]], i64 0 + ; CHECK: %[[D1:[^ ]+]] = extractelement <3 x float> %[[DIR]], i64 1 + ; CHECK: %[[D2:[^ ]+]] = extractelement <3 x float> %[[DIR]], i64 2 + ; CHECK: %[[TMAXPTR:[^ ]+]] = getelementptr %struct.RayDesc, %struct.RayDesc* %[[RAYDESCPTR]], i32 0, i32 3 + ; CHECK: %[[TMAX:[^ ]+]] = load float, float* %[[TMAXPTR]] + ; CHECK: %[[TRACEHO:[^ ]+]] = call %dx.types.HitObject @dx.op.hitObject_TraceRay.struct.Payload(i32 262, %dx.types.Handle %5, i32 513, i32 1, i32 2, i32 4, i32 0, float %[[O0]], float %[[O1]], float %[[O2]], float %[[TMIN]], float %[[D0]], float %[[D1]], float %[[D2]], float %[[TMAX]], %struct.Payload* %pld) + call void @"dx.hl.op..void (i32, %dx.types.HitObject*, %dx.types.Handle, i32, i32, i32, i32, i32, %struct.RayDesc*, %struct.Payload*)"(i32 389, %dx.types.HitObject* %hit, %dx.types.Handle %5, i32 513, i32 1, i32 2, i32 4, i32 0, %struct.RayDesc* %rayDesc, %struct.Payload* %pld), !dbg !52 ; line:89 col:23 + ; CHECK: store %dx.types.HitObject %[[TRACEHO]], %dx.types.HitObject* %[[HOPTR:[^ ]+]] + ; CHECK: %[[INVOKEHO:[^ ]+]] = load %dx.types.HitObject, %dx.types.HitObject* %[[HOPTR]] + ; CHECK: call void @dx.op.hitObject_Invoke.struct.Payload(i32 267, %dx.types.HitObject %[[INVOKEHO]], %struct.Payload* %pld) + call void @"dx.hl.op..void (i32, %dx.types.HitObject*, %struct.Payload*)"(i32 382, %dx.types.HitObject* %hit, %struct.Payload* %pld), !dbg !53 ; line:99 col:3 + %6 = bitcast %dx.types.HitObject* %hit to i8*, !dbg !54 ; line:100 col:1 + call void @llvm.lifetime.end(i64 4, i8* %6) #0, !dbg !54 ; line:100 col:1 + %7 = bitcast %struct.Payload* %pld to i8*, !dbg !54 ; line:100 col:1 + call void @llvm.lifetime.end(i64 12, i8* %7) #0, !dbg !54 ; line:100 col:1 + %8 = bitcast %struct.RayDesc* %rayDesc to i8*, !dbg !54 ; line:100 col:1 + call void @llvm.lifetime.end(i64 32, i8* %8) #0, !dbg !54 ; line:100 col:1 + ret void, !dbg !54 ; line:100 col:1 +} + +; Function Attrs: nounwind +declare void @llvm.lifetime.start(i64, i8* nocapture) #0 + +; Function Attrs: nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) #0 + +; Function Attrs: nounwind +declare void @"dx.hl.op..void (i32, %dx.types.HitObject*, %dx.types.Handle, i32, i32, i32, i32, i32, %struct.RayDesc*, %struct.Payload*)"(i32, %dx.types.HitObject*, %dx.types.Handle, i32, i32, i32, i32, i32, %struct.RayDesc*, %struct.Payload*) #0 + +; Function Attrs: nounwind readnone +declare %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.RaytracingAccelerationStructure)"(i32, %struct.RaytracingAccelerationStructure) #1 + +; Function Attrs: nounwind readnone +declare %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.RaytracingAccelerationStructure)"(i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.RaytracingAccelerationStructure) #1 + +; Function Attrs: nounwind +declare void @"dx.hl.op..void (i32, %dx.types.HitObject*, %struct.Payload*)"(i32, %dx.types.HitObject*, %struct.Payload*) #0 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!llvm.module.flags = !{!0} +!pauseresume = !{!1} +!dx.version = !{!2} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.typeAnnotations = !{!4, !19} +!dx.entryPoints = !{!23} +!dx.fnprops = !{!28} +!dx.options = !{!29, !30} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"} +!2 = !{i32 1, i32 9} +!3 = !{!"lib", i32 6, i32 9} +!4 = !{i32 0, %"class.RWStructuredBuffer" undef, !5, %struct.RayDesc undef, !10, %struct.Payload undef, !15, %"class.dx::HitObject" undef, !17} +!5 = !{i32 4, !6, !7} +!6 = !{i32 6, !"h", i32 3, i32 0, i32 7, i32 9} +!7 = !{i32 0, !8} +!8 = !{!9} +!9 = !{i32 0, float undef} +!10 = !{i32 32, !11, !12, !13, !14} +!11 = !{i32 6, !"Origin", i32 3, i32 0, i32 7, i32 9, i32 13, i32 3} +!12 = !{i32 6, !"TMin", i32 3, i32 12, i32 7, i32 9} +!13 = !{i32 6, !"Direction", i32 3, i32 16, i32 7, i32 9, i32 13, i32 3} +!14 = !{i32 6, !"TMax", i32 3, i32 28, i32 7, i32 9} +!15 = !{i32 12, !16} +!16 = !{i32 6, !"dummy", i32 3, i32 0, i32 7, i32 9, i32 13, i32 3} +!17 = !{i32 4, !18} +!18 = !{i32 6, !"h", i32 3, i32 0, i32 7, i32 4} +!19 = !{i32 1, void ()* @"\01?main@@YAXXZ", !20} +!20 = !{!21} +!21 = !{i32 1, !22, !22} +!22 = !{} +!23 = !{null, !"", null, !24, null} +!24 = !{!25, null, null, null} +!25 = !{!26} +!26 = !{i32 0, %struct.RaytracingAccelerationStructure* @"\01?RTAS@@3URaytracingAccelerationStructure@@A", !"RTAS", i32 -1, i32 -1, i32 1, i32 16, i32 0, !27} +!27 = !{i32 0, i32 4} +!28 = !{void ()* @"\01?main@@YAXXZ", i32 7} +!29 = !{i32 -2147483584} +!30 = !{i32 -1} +!31 = !DILocation(line: 80, column: 3, scope: !32) +!32 = !DISubprogram(name: "main", scope: !33, file: !33, line: 79, type: !34, isLocal: false, isDefinition: true, scopeLine: 79, flags: DIFlagPrototyped, isOptimized: false, function: void ()* @"\01?main@@YAXXZ") +!33 = !DIFile(filename: "tools/clang/test/CodeGenDXIL/hlsl/objects/HitObject/hitobject_traceinvoke.hlsl", directory: "") +!34 = !DISubroutineType(types: !22) +!35 = !DILocation(line: 81, column: 11, scope: !32) +!36 = !DILocation(line: 81, column: 18, scope: !32) +!37 = !{!38, !38, i64 0} +!38 = !{!"omnipotent char", !39, i64 0} +!39 = !{!"Simple C/C++ TBAA"} +!40 = !DILocation(line: 82, column: 11, scope: !32) +!41 = !DILocation(line: 82, column: 16, scope: !32) +!42 = !{!43, !43, i64 0} +!43 = !{!"float", !38, i64 0} +!44 = !DILocation(line: 83, column: 11, scope: !32) +!45 = !DILocation(line: 83, column: 21, scope: !32) +!46 = !DILocation(line: 84, column: 11, scope: !32) +!47 = !DILocation(line: 84, column: 16, scope: !32) +!48 = !DILocation(line: 86, column: 3, scope: !32) +!49 = !DILocation(line: 87, column: 7, scope: !32) +!50 = !DILocation(line: 87, column: 13, scope: !32) +!51 = !DILocation(line: 89, column: 3, scope: !32) +!52 = !DILocation(line: 89, column: 23, scope: !32) +!53 = !DILocation(line: 99, column: 3, scope: !32) +!54 = !DILocation(line: 100, column: 1, scope: !32)