From 63a5b8b109ff57046b37e0ed1a5d9a8e36ac8620 Mon Sep 17 00:00:00 2001 From: Simon Moll Date: Wed, 15 Oct 2025 21:18:42 +0200 Subject: [PATCH] [SM6.10] VEC9 TriangleObjectPositions / passing validation tests SM6.10 tracking bug: #7824 --- lib/DXIL/DxilOperations.cpp | 15 +++- .../test/DXILValidation/clusterid_passing.ll | 74 ++++++++++++++++++ .../triangle_position_passing.ll | 77 +++++++++++++++++++ utils/hct/hctdb.py | 8 +- utils/hct/hctdb_instrhelp.py | 17 +++- 5 files changed, 182 insertions(+), 9 deletions(-) create mode 100644 tools/clang/test/DXILValidation/clusterid_passing.ll create mode 100644 tools/clang/test/DXILValidation/triangle_position_passing.ll diff --git a/lib/DXIL/DxilOperations.cpp b/lib/DXIL/DxilOperations.cpp index 0e8835c69c..9f0f040559 100644 --- a/lib/DXIL/DxilOperations.cpp +++ b/lib/DXIL/DxilOperations.cpp @@ -4081,6 +4081,7 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { #define RRT(_y) A(GetResRetType(_y)) #define CBRT(_y) A(GetCBufferRetType(_y)) #define VEC4(_y) A(GetStructVectorType(4, _y)) +#define VEC9(_y) A(VectorType::get(_y, 9)) // Extended Overload types are wrapped in an anonymous struct #define EXT(_y) A(cast(pOverloadType)->getElementType(_y)) @@ -6310,25 +6311,25 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { // Raytracing System Values case OpCode::TriangleObjectPosition: - A(pETy); + VEC9(pETy); A(pI32); break; // Inline Ray Query case OpCode::RayQuery_CandidateTriangleObjectPosition: - A(pETy); + VEC9(pETy); A(pI32); A(pI32); break; case OpCode::RayQuery_CommittedTriangleObjectPosition: - A(pETy); + VEC9(pETy); A(pI32); A(pI32); break; // Shader Execution Reordering case OpCode::HitObject_TriangleObjectPosition: - A(pETy); + VEC9(pETy); A(pI32); A(pHit); break; @@ -6653,6 +6654,12 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) { StructType *ST = cast(Ty); return ST->getElementType(0); } + case OpCode::TriangleObjectPosition: + case OpCode::RayQuery_CandidateTriangleObjectPosition: + case OpCode::RayQuery_CommittedTriangleObjectPosition: + case OpCode::HitObject_TriangleObjectPosition: + // These return <9 x float> vectors directly + return cast(Ty)->getElementType(); case OpCode::MatVecMul: case OpCode::MatVecMulAdd: if (FT->getNumParams() < 2) diff --git a/tools/clang/test/DXILValidation/clusterid_passing.ll b/tools/clang/test/DXILValidation/clusterid_passing.ll new file mode 100644 index 0000000000..ccbc2eb484 --- /dev/null +++ b/tools/clang/test/DXILValidation/clusterid_passing.ll @@ -0,0 +1,74 @@ +; RUN: %dxv %s | FileCheck %s + +; CHECK: Validation succeeded. + +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" + +%dx.types.Handle = type { i8* } +%struct.Payload = type { <4 x float> } +%struct.BuiltInTriangleIntersectionAttributes = type { <2 x float> } +%dx.types.ResourceProperties = type { i32, i32 } +%dx.types.HitObject = type { i8* } + +; Function Attrs: nounwind +define void @"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z"(%struct.Payload* noalias nocapture %payload, %struct.BuiltInTriangleIntersectionAttributes* nocapture readnone %attr) #0 { + %1 = call i32 @dx.op.clusterID(i32 2147483651) ; ClusterID() + ret void +} + +; Function Attrs: nounwind +define void @"\01?test_raygeneration@@YAXXZ"() #0 { + %1 = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop() + %2 = call i32 @dx.op.hitObject_StateScalar.i32(i32 2147483654, %dx.types.HitObject %1) ; HitObject_ClusterID(hitObject) + %3 = call i32 @dx.op.allocateRayQuery(i32 178, i32 0) ; AllocateRayQuery(constRayFlags) + %4 = call i32 @dx.op.rayQuery_StateScalar.i32(i32 2147483652, i32 %3) ; RayQuery_CandidateClusterID(rayQueryHandle) + %5 = call i32 @dx.op.rayQuery_StateScalar.i32(i32 2147483653, i32 %3) ; RayQuery_CommittedClusterID(rayQueryHandle) + ret void +} + +; Function Attrs: nounwind readnone +declare i32 @dx.op.clusterID(i32) #1 + +; Function Attrs: nounwind readnone +declare %dx.types.HitObject @dx.op.hitObject_MakeNop(i32) #1 + +; Function Attrs: nounwind readnone +declare i32 @dx.op.hitObject_StateScalar.i32(i32, %dx.types.HitObject) #1 + +; Function Attrs: nounwind +declare i32 @dx.op.allocateRayQuery(i32, i32) #0 + +; Function Attrs: nounwind readonly +declare i32 @dx.op.rayQuery_StateScalar.i32(i32, i32) #2 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } +attributes #2 = { nounwind readonly } + +!dx.version = !{!0} +!dx.valver = !{!0} +!dx.shaderModel = !{!1} +!dx.typeAnnotations = !{!2} +!dx.dxrPayloadAnnotations = !{!9} +!dx.entryPoints = !{!12, !14, !17} + +!0 = !{i32 1, i32 10} +!1 = !{!"lib", i32 6, i32 10} +!2 = !{i32 1, void (%struct.Payload*, %struct.BuiltInTriangleIntersectionAttributes*)* @"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z", !3, void ()* @"\01?test_raygeneration@@YAXXZ", !8} +!3 = !{!4, !6, !7} +!4 = !{i32 1, !5, !5} +!5 = !{} +!6 = !{i32 2, !5, !5} +!7 = !{i32 0, !5, !5} +!8 = !{!4} +!9 = !{i32 0, %struct.Payload undef, !10} +!10 = !{!11} +!11 = !{i32 0, i32 33} +!12 = !{null, !"", null, null, !13} +!13 = !{i32 0, i64 33554432} +!14 = !{void (%struct.Payload*, %struct.BuiltInTriangleIntersectionAttributes*)* @"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z", !"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z", null, null, !15} +!15 = !{i32 8, i32 10, i32 6, i32 16, i32 7, i32 8, i32 5, !16} +!16 = !{i32 0} +!17 = !{void ()* @"\01?test_raygeneration@@YAXXZ", !"\01?test_raygeneration@@YAXXZ", null, null, !18} +!18 = !{i32 8, i32 7, i32 5, !16} diff --git a/tools/clang/test/DXILValidation/triangle_position_passing.ll b/tools/clang/test/DXILValidation/triangle_position_passing.ll new file mode 100644 index 0000000000..463230674e --- /dev/null +++ b/tools/clang/test/DXILValidation/triangle_position_passing.ll @@ -0,0 +1,77 @@ +; RUN: %dxv %s | FileCheck %s + +; CHECK: Validation succeeded. + +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" + +%dx.types.Handle = type { i8* } +%struct.Payload = type { <4 x float> } +%struct.BuiltInTriangleIntersectionAttributes = type { <2 x float> } +%dx.types.ResourceProperties = type { i32, i32 } +%dx.types.HitObject = type { i8* } + +; Function Attrs: nounwind +define void @"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z"(%struct.Payload* noalias nocapture %payload, %struct.BuiltInTriangleIntersectionAttributes* nocapture readnone %attr) #0 { + %1 = call <9 x float> @dx.op.triangleObjectPosition.f32(i32 2147483655) ; TriangleObjectPosition() + ret void +} + +; Function Attrs: nounwind +define void @"\01?test_raygeneration@@YAXXZ"() #0 { + %1 = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop() + %2 = call <9 x float> @dx.op.hitObject_TriangleObjectPosition.f32(i32 2147483658, %dx.types.HitObject %1) ; HitObject_TriangleObjectPosition(hitObject) + %3 = call i32 @dx.op.allocateRayQuery(i32 178, i32 0) ; AllocateRayQuery(constRayFlags) + %4 = call <9 x float> @dx.op.rayQuery_CandidateTriangleObjectPosition.f32(i32 2147483656, i32 %3) ; RayQuery_CandidateTriangleObjectPosition(rayQueryHandle) + %5 = call <9 x float> @dx.op.rayQuery_CommittedTriangleObjectPosition.f32(i32 2147483657, i32 %3) ; RayQuery_CommittedTriangleObjectPosition(rayQueryHandle) + ret void +} + +; Function Attrs: nounwind readnone +declare <9 x float> @dx.op.triangleObjectPosition.f32(i32) #1 + +; Function Attrs: nounwind readnone +declare <9 x float> @dx.op.hitObject_TriangleObjectPosition.f32(i32, %dx.types.HitObject) #1 + +; Function Attrs: nounwind readnone +declare %dx.types.HitObject @dx.op.hitObject_MakeNop(i32) #1 + +; Function Attrs: nounwind +declare i32 @dx.op.allocateRayQuery(i32, i32) #0 + +; Function Attrs: nounwind readonly +declare <9 x float> @dx.op.rayQuery_CandidateTriangleObjectPosition.f32(i32, i32) #2 + +; Function Attrs: nounwind readonly +declare <9 x float> @dx.op.rayQuery_CommittedTriangleObjectPosition.f32(i32, i32) #2 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } +attributes #2 = { nounwind readonly } + +!dx.version = !{!0} +!dx.valver = !{!0} +!dx.shaderModel = !{!1} +!dx.typeAnnotations = !{!2} +!dx.dxrPayloadAnnotations = !{!9} +!dx.entryPoints = !{!12, !14, !17} + +!0 = !{i32 1, i32 10} +!1 = !{!"lib", i32 6, i32 10} +!2 = !{i32 1, void (%struct.Payload*, %struct.BuiltInTriangleIntersectionAttributes*)* @"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z", !3, void ()* @"\01?test_raygeneration@@YAXXZ", !8} +!3 = !{!4, !6, !7} +!4 = !{i32 1, !5, !5} +!5 = !{} +!6 = !{i32 2, !5, !5} +!7 = !{i32 0, !5, !5} +!8 = !{!4} +!9 = !{i32 0, %struct.Payload undef, !10} +!10 = !{!11} +!11 = !{i32 0, i32 33} +!12 = !{null, !"", null, null, !13} +!13 = !{i32 0, i64 33554432} +!14 = !{void (%struct.Payload*, %struct.BuiltInTriangleIntersectionAttributes*)* @"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z", !"\01?test_closesthit@@YAXUPayload@@UBuiltInTriangleIntersectionAttributes@@@Z", null, null, !15} +!15 = !{i32 8, i32 10, i32 6, i32 16, i32 7, i32 8, i32 5, !16} +!16 = !{i32 0} +!17 = !{void ()* @"\01?test_raygeneration@@YAXXZ", !"\01?test_raygeneration@@YAXXZ", null, null, !18} +!18 = !{i32 8, i32 7, i32 5, !16} diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index a3b22024ff..4520a992df 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -6263,7 +6263,7 @@ def populate_ExperimentalOps(self): "f", "rn", [ - db_dxil_param(0, "$o", "", "operation result"), # TODO: $vec9 + db_dxil_param(0, "$vec9", "", "operation result"), ], ) add_dxil_op( @@ -6273,7 +6273,7 @@ def populate_ExperimentalOps(self): "f", "ro", [ - db_dxil_param(0, "$o", "", "operation result"), # TODO: $vec9 + db_dxil_param(0, "$vec9", "", "operation result"), db_dxil_param(2, "i32", "rayQueryHandle", "RayQuery handle"), ], ) @@ -6284,7 +6284,7 @@ def populate_ExperimentalOps(self): "f", "ro", [ - db_dxil_param(0, "$o", "", "operation result"), # TODO: $vec9 + db_dxil_param(0, "$vec9", "", "operation result"), db_dxil_param(2, "i32", "rayQueryHandle", "RayQuery handle"), ], ) @@ -6295,7 +6295,7 @@ def populate_ExperimentalOps(self): "f", "rn", [ - db_dxil_param(0, "$o", "", "operation result"), # TODO: $vec9 + db_dxil_param(0, "$vec9", "", "operation result"), db_dxil_param(2, "hit_object", "hitObject", "hit"), ], ) diff --git a/utils/hct/hctdb_instrhelp.py b/utils/hct/hctdb_instrhelp.py index b703772ebc..6208032bf1 100644 --- a/utils/hct/hctdb_instrhelp.py +++ b/utils/hct/hctdb_instrhelp.py @@ -630,6 +630,7 @@ def print_opfunc_table(self): "u8": "A(pI8);", "v": "A(pV);", "$vec4": "VEC4(pETy);", + "$vec9": "VEC9(pETy);", "SamplePos": "A(pPos);", "$udt": "A(udt);", "$obj": "A(obj);", @@ -683,6 +684,7 @@ def print_opfunc_oload_type(self): # grouped by the set of overload parameter indices. extended_dict = collections.OrderedDict() struct_list = [] + vec9_list = [] # For $vec9 operations that return native vectors extended_list = [] for instr in self.db.get_dxil_ops(): @@ -705,7 +707,11 @@ def print_opfunc_oload_type(self): continue if ret_ty.startswith(vec_ty): - struct_list.append(instr.name) + # $vec9 returns native <9 x float> vectors, not struct wrappers + if ret_ty == "$vec9": + vec9_list.append(instr.name) + else: + struct_list.append(instr.name) continue in_param_ty = False @@ -822,6 +828,15 @@ def print_opfunc_oload_type(self): line = line + "}" print(line) + # Generate code for $vec9 operations (native <9 x float> vectors) + if vec9_list: + line = "" + for opcode in vec9_list: + line = line + "case OpCode::{name}".format(name=opcode + ":\n") + line = line + " // These return <9 x float> vectors directly\n" + line = line + " return cast(Ty)->getElementType();" + print(line) + for instr in extended_list: # Collect indices for overloaded return and types, make a tuple of # indices the key, and add the opcode to a list of opcodes for that