From e231f0b0313ec1554b5462856b3a7db0c9ef4e7b Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Fri, 20 Mar 2026 10:37:16 -0700 Subject: [PATCH 1/5] [SM6.10] Make DxilStructAnnotation aware of target types Fixes #8279 --- include/dxc/DXIL/DxilTypeSystem.h | 20 ++++++++-- lib/DXIL/DxilTypeSystem.cpp | 38 ++++++++++++++++++- lib/HLSL/DxilContainerReflection.cpp | 3 +- .../linalg/matrix-target-type-in-struct.hlsl | 22 +++++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl diff --git a/include/dxc/DXIL/DxilTypeSystem.h b/include/dxc/DXIL/DxilTypeSystem.h index 1cf6725ec7..f3da4f7017 100644 --- a/include/dxc/DXIL/DxilTypeSystem.h +++ b/include/dxc/DXIL/DxilTypeSystem.h @@ -148,10 +148,12 @@ class DxilStructAnnotation { void SetCBufferSize(unsigned size); void MarkEmptyStruct(); bool IsEmptyStruct(); - // Since resources don't take real space, IsEmptyBesidesResources - // determines if the structure is empty or contains only resources. - bool IsEmptyBesidesResources(); + // Since resources and target types don't take real space, + // IsEmptyBesidesResourcesAndTargetTypes() determines if the structure is + // empty or contains only resources or target types. + bool IsEmptyBesidesResourcesAndTargetTypes(); bool ContainsResources() const; + bool ContainsTargetTypes() const; // For template args, GetNumTemplateArgs() will return 0 if not a template unsigned GetNumTemplateArgs() const; @@ -174,6 +176,15 @@ class DxilStructAnnotation { False, Only } m_ResourcesContained = HasResources::False; + + void SetContainsTargetTypes(); + // HasTargetTypes::Only will be set on MarkEmptyStruct() when + // HasTargetTypes::True + enum class HasTargetTypes { + True, + False, + Only + } m_TargetTypesContained = HasTargetTypes::False; }; /// Use this class to represent type annotation for DXR payload field. @@ -343,6 +354,9 @@ class DxilTypeSystem { // Determines whether type is a resource or contains a resource bool IsResourceContained(llvm::Type *Ty); + // Determines whether type is a target type or contains a target type + bool IsTargetTypeContained(llvm::Type *Ty); + private: llvm::Module *m_pModule; StructAnnotationMap m_StructAnnotations; diff --git a/lib/DXIL/DxilTypeSystem.cpp b/lib/DXIL/DxilTypeSystem.cpp index 10b62002cb..0084cce7a1 100644 --- a/lib/DXIL/DxilTypeSystem.cpp +++ b/lib/DXIL/DxilTypeSystem.cpp @@ -236,14 +236,17 @@ void DxilStructAnnotation::SetCBufferSize(unsigned size) { void DxilStructAnnotation::MarkEmptyStruct() { if (m_ResourcesContained == HasResources::True) m_ResourcesContained = HasResources::Only; + else if (m_TargetTypesContained == HasTargetTypes::True) + m_TargetTypesContained = HasTargetTypes::Only; else m_FieldAnnotations.clear(); } bool DxilStructAnnotation::IsEmptyStruct() { return m_FieldAnnotations.empty(); } -bool DxilStructAnnotation::IsEmptyBesidesResources() { +bool DxilStructAnnotation::IsEmptyBesidesResourcesAndTargetTypes() { return m_ResourcesContained == HasResources::Only || + m_TargetTypesContained == HasTargetTypes::Only || m_FieldAnnotations.empty(); } @@ -256,6 +259,14 @@ bool DxilStructAnnotation::ContainsResources() const { return m_ResourcesContained != HasResources::False; } +void DxilStructAnnotation::SetContainsTargetTypes() { + if (m_TargetTypesContained == HasTargetTypes::False) + m_TargetTypesContained = HasTargetTypes::True; +} +bool DxilStructAnnotation::ContainsTargetTypes() const { + return m_TargetTypesContained != HasTargetTypes::False; +} + // For template args, GetNumTemplateArgs() will return 0 if not a template unsigned DxilStructAnnotation::GetNumTemplateArgs() const { return (unsigned)m_TemplateAnnotations.size(); @@ -393,6 +404,13 @@ void DxilTypeSystem::FinishStructAnnotation(DxilStructAnnotation &SA) { SA.SetContainsResources(); } + // Update target type containment + for (unsigned i = 0; i < SA.GetNumFields() && !SA.ContainsTargetTypes(); + i++) { + if (IsTargetTypeContained(ST->getElementType(i))) + SA.SetContainsTargetTypes(); + } + // Mark if empty if (SA.GetCBufferSize() == 0) SA.MarkEmptyStruct(); @@ -872,6 +890,24 @@ bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) { return false; } +bool DxilTypeSystem::IsTargetTypeContained(llvm::Type *Ty) { + // strip pointer/array + if (Ty->isPointerTy()) + Ty = Ty->getPointerElementType(); + if (Ty->isArrayTy()) + Ty = Ty->getArrayElementType(); + + if (auto ST = dyn_cast(Ty)) { + if (dxilutil::IsHLSLKnownTargetType(Ty)) { + return true; + } else if (auto SA = GetStructAnnotation(ST)) { + if (SA->ContainsTargetTypes()) + return true; + } + } + return false; +} + DxilStructTypeIterator::DxilStructTypeIterator( llvm::StructType *sTy, DxilStructAnnotation *sAnnotation, unsigned idx) : STy(sTy), SAnnotation(sAnnotation), index(idx) { diff --git a/lib/HLSL/DxilContainerReflection.cpp b/lib/HLSL/DxilContainerReflection.cpp index 4cddab7b60..e3c5848074 100644 --- a/lib/HLSL/DxilContainerReflection.cpp +++ b/lib/HLSL/DxilContainerReflection.cpp @@ -1278,7 +1278,8 @@ HRESULT CShaderReflectionType::Initialize( // There is no annotation for empty structs unsigned int fieldCount = 0; - if (structAnnotation && !structAnnotation->IsEmptyBesidesResources()) + if (structAnnotation && + !structAnnotation->IsEmptyBesidesResourcesAndTargetTypes()) fieldCount = type->getStructNumElements(); // The DXBC reflection info computes `Columns` for a diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl new file mode 100644 index 0000000000..434b5fcc5f --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl @@ -0,0 +1,22 @@ +// REQUIRES: dxil-1-10 +// RUN: %dxc -I %hlsl_headers -T cs_6_10 -enable-16bit-types %s | FileCheck %s + +using MyHandleT = __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(9, 4, 4, 0, 1)]]; + +class MyMatrix { + MyHandleT handle; + + static MyMatrix Splat(float Val) { + MyMatrix Result; + __builtin_LinAlg_FillMatrix(Result.handle, Val); + return Result; + } +}; + +[numthreads(4, 4, 4)] +void main() { + MyMatrix MatA = MyMatrix::Splat(1.0f); +} + +// CHECK: %1 = call %dx.types.LinAlgMatrixC9M4N4U0S1 @dx.op.linAlgFillMatrix.mC9M4N4U0S1.f32(i32 -2147483636, float 1.000000e+00) ; LinAlgFillMatrix(value) +// CHECK-NOT: @llvm.trap() From 20e6695ebed8d9874bcd8f81b29d50edd5ad1958 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Tue, 24 Mar 2026 10:26:51 -0700 Subject: [PATCH 2/5] code review feedback - add const and auto * --- include/dxc/DXIL/DxilTypeSystem.h | 6 +++--- lib/DXIL/DxilTypeSystem.cpp | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/dxc/DXIL/DxilTypeSystem.h b/include/dxc/DXIL/DxilTypeSystem.h index f3da4f7017..aa34060a54 100644 --- a/include/dxc/DXIL/DxilTypeSystem.h +++ b/include/dxc/DXIL/DxilTypeSystem.h @@ -151,7 +151,7 @@ class DxilStructAnnotation { // Since resources and target types don't take real space, // IsEmptyBesidesResourcesAndTargetTypes() determines if the structure is // empty or contains only resources or target types. - bool IsEmptyBesidesResourcesAndTargetTypes(); + bool IsEmptyBesidesResourcesAndTargetTypes() const; bool ContainsResources() const; bool ContainsTargetTypes() const; @@ -352,10 +352,10 @@ class DxilTypeSystem { void SetMinPrecision(bool bMinPrecision); // Determines whether type is a resource or contains a resource - bool IsResourceContained(llvm::Type *Ty); + bool IsResourceContained(llvm::Type *Ty) const; // Determines whether type is a target type or contains a target type - bool IsTargetTypeContained(llvm::Type *Ty); + bool IsTargetTypeContained(llvm::Type *Ty) const; private: llvm::Module *m_pModule; diff --git a/lib/DXIL/DxilTypeSystem.cpp b/lib/DXIL/DxilTypeSystem.cpp index 0084cce7a1..9dd7e95dce 100644 --- a/lib/DXIL/DxilTypeSystem.cpp +++ b/lib/DXIL/DxilTypeSystem.cpp @@ -244,7 +244,7 @@ void DxilStructAnnotation::MarkEmptyStruct() { bool DxilStructAnnotation::IsEmptyStruct() { return m_FieldAnnotations.empty(); } -bool DxilStructAnnotation::IsEmptyBesidesResourcesAndTargetTypes() { +bool DxilStructAnnotation::IsEmptyBesidesResourcesAndTargetTypes() const { return m_ResourcesContained == HasResources::Only || m_TargetTypesContained == HasTargetTypes::Only || m_FieldAnnotations.empty(); @@ -872,17 +872,17 @@ void DxilTypeSystem::SetMinPrecision(bool bMinPrecision) { m_LowPrecisionMode = mode; } -bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) { +bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) const { // strip pointer/array if (Ty->isPointerTy()) Ty = Ty->getPointerElementType(); if (Ty->isArrayTy()) Ty = Ty->getArrayElementType(); - if (auto ST = dyn_cast(Ty)) { + if (auto *ST = dyn_cast(Ty)) { if (dxilutil::IsHLSLResourceType(Ty)) { return true; - } else if (auto SA = GetStructAnnotation(ST)) { + } else if (auto *SA = GetStructAnnotation(ST)) { if (SA->ContainsResources()) return true; } @@ -890,17 +890,17 @@ bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) { return false; } -bool DxilTypeSystem::IsTargetTypeContained(llvm::Type *Ty) { +bool DxilTypeSystem::IsTargetTypeContained(llvm::Type *Ty) const { // strip pointer/array if (Ty->isPointerTy()) Ty = Ty->getPointerElementType(); if (Ty->isArrayTy()) Ty = Ty->getArrayElementType(); - if (auto ST = dyn_cast(Ty)) { + if (auto *ST = dyn_cast(Ty)) { if (dxilutil::IsHLSLKnownTargetType(Ty)) { return true; - } else if (auto SA = GetStructAnnotation(ST)) { + } else if (auto *SA = GetStructAnnotation(ST)) { if (SA->ContainsTargetTypes()) return true; } From ac00a58fcd7d31ce7f42c113ee1f48c0a809e3cc Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Wed, 25 Mar 2026 14:59:43 -0700 Subject: [PATCH 3/5] update test --- .../CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl index 434b5fcc5f..5b5d33b591 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl @@ -18,5 +18,5 @@ void main() { MyMatrix MatA = MyMatrix::Splat(1.0f); } -// CHECK: %1 = call %dx.types.LinAlgMatrixC9M4N4U0S1 @dx.op.linAlgFillMatrix.mC9M4N4U0S1.f32(i32 -2147483636, float 1.000000e+00) ; LinAlgFillMatrix(value) +// CHECK: call %dx.types.LinAlgMatrixC9M4N4U0S1 @dx.op.linAlgFillMatrix.mC9M4N4U0S1.f32(i32 -2147483636, float 1.000000e+00) ; LinAlgFillMatrix(value) // CHECK-NOT: @llvm.trap() From d0ad1206a9e0362547a89862e44040caac7a5038 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Wed, 25 Mar 2026 17:51:32 -0700 Subject: [PATCH 4/5] code review feedback - remove include, formatting --- lib/DXIL/DxilTypeSystem.cpp | 10 ++++------ .../hlsl/linalg/matrix-target-type-in-struct.hlsl | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/DXIL/DxilTypeSystem.cpp b/lib/DXIL/DxilTypeSystem.cpp index 9dd7e95dce..b3a7bfcdcd 100644 --- a/lib/DXIL/DxilTypeSystem.cpp +++ b/lib/DXIL/DxilTypeSystem.cpp @@ -880,13 +880,12 @@ bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) const { Ty = Ty->getArrayElementType(); if (auto *ST = dyn_cast(Ty)) { - if (dxilutil::IsHLSLResourceType(Ty)) { + if (dxilutil::IsHLSLResourceType(Ty)) return true; - } else if (auto *SA = GetStructAnnotation(ST)) { + else if (auto *SA = GetStructAnnotation(ST)) { if (SA->ContainsResources()) return true; } - } return false; } @@ -898,13 +897,12 @@ bool DxilTypeSystem::IsTargetTypeContained(llvm::Type *Ty) const { Ty = Ty->getArrayElementType(); if (auto *ST = dyn_cast(Ty)) { - if (dxilutil::IsHLSLKnownTargetType(Ty)) { + if (dxilutil::IsHLSLKnownTargetType(Ty)) return true; - } else if (auto *SA = GetStructAnnotation(ST)) { + else if (auto *SA = GetStructAnnotation(ST)) { if (SA->ContainsTargetTypes()) return true; } - } return false; } diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl index 5b5d33b591..a48c56f013 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/matrix-target-type-in-struct.hlsl @@ -1,5 +1,5 @@ // REQUIRES: dxil-1-10 -// RUN: %dxc -I %hlsl_headers -T cs_6_10 -enable-16bit-types %s | FileCheck %s +// RUN: %dxc -T cs_6_10 -enable-16bit-types %s | FileCheck %s using MyHandleT = __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(9, 4, 4, 0, 1)]]; From 80f4b16f197b5d5d5dd525f23e2faf1d6e3e0dec Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Wed, 25 Mar 2026 20:34:55 -0700 Subject: [PATCH 5/5] fix curlies --- lib/DXIL/DxilTypeSystem.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/DXIL/DxilTypeSystem.cpp b/lib/DXIL/DxilTypeSystem.cpp index b3a7bfcdcd..da7d85c754 100644 --- a/lib/DXIL/DxilTypeSystem.cpp +++ b/lib/DXIL/DxilTypeSystem.cpp @@ -882,10 +882,10 @@ bool DxilTypeSystem::IsResourceContained(llvm::Type *Ty) const { if (auto *ST = dyn_cast(Ty)) { if (dxilutil::IsHLSLResourceType(Ty)) return true; - else if (auto *SA = GetStructAnnotation(ST)) { + else if (auto *SA = GetStructAnnotation(ST)) if (SA->ContainsResources()) return true; - } + } return false; } @@ -899,10 +899,10 @@ bool DxilTypeSystem::IsTargetTypeContained(llvm::Type *Ty) const { if (auto *ST = dyn_cast(Ty)) { if (dxilutil::IsHLSLKnownTargetType(Ty)) return true; - else if (auto *SA = GetStructAnnotation(ST)) { + else if (auto *SA = GetStructAnnotation(ST)) if (SA->ContainsTargetTypes()) return true; - } + } return false; }