Skip to content

[DirectX] Validate if Textures/TypedBuffers are being bound in Root Signatures #147573

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: users/joaosaffran/146785
Choose a base branch
from

Conversation

joaosaffran
Copy link
Contributor

@joaosaffran joaosaffran commented Jul 8, 2025

DXC doesn't allow Textures/TypedBuffers to bind with root signature descriptors, this implements the same check.

Closes: #126647

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:DirectX HLSL HLSL Language Support labels Jul 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 8, 2025

@llvm/pr-subscribers-hlsl

Author: None (joaosaffran)

Changes

DXC doesn't allow Textures/TypedBuffers to bind with root signature descriptors, this implements the same check in clang.

Closes: #126647


Full diff: https://github.com/llvm/llvm-project/pull/147573.diff

2 Files Affected:

  • (added) clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl (+13)
  • (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+25)
diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl
new file mode 100644
index 0000000000000..9daf38e30dd67
--- /dev/null
+++ b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl
@@ -0,0 +1,13 @@
+// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s
+
+// CHECK: error: register srv (space=0, register=0) is bound to a texture or typed buffer.
+
+RWStructuredBuffer<int> Out : register(u0);
+Buffer<float> B : register(t0);
+// Compute Shader for UAV testing
+[numthreads(8, 8, 1)]
+[RootSignature("SRV(t0), UAV(u0)")]
+void CSMain(uint id : SV_GroupID)
+{
+    Out[0] = B[0];
+}
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index a52a04323514c..c34f31fbe35e5 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -85,6 +85,17 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
   }
 }
 
+static void
+reportInvalidHandleTyBoundInRs(Module &M, Twine Type,
+                               ResourceInfo::ResourceBinding Binding) {
+  SmallString<128> Message;
+  raw_svector_ostream OS(Message);
+  OS << "register " << Type << " (space=" << Binding.Space
+     << ", register=" << Binding.LowerBound << ")"
+     << " is bound to a texture or typed buffer.";
+  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
 static void reportRegNotBound(Module &M, Twine Type,
                               ResourceInfo::ResourceBinding Binding) {
   SmallString<128> Message;
@@ -163,12 +174,26 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
       ResourceInfo::ResourceBinding Binding = SRV.getBinding();
       if (!Validation.checkTRegBinding(Binding))
         reportRegNotBound(M, "srv", Binding);
+      else {
+        const auto *Handle =
+            dyn_cast_or_null<RawBufferExtType>(SRV.getHandleTy());
+
+        if (!Handle)
+          reportInvalidHandleTyBoundInRs(M, "srv", Binding);
+      }
     }
 
     for (const ResourceInfo &UAV : DRM.uavs()) {
       ResourceInfo::ResourceBinding Binding = UAV.getBinding();
       if (!Validation.checkURegBinding(Binding))
         reportRegNotBound(M, "uav", Binding);
+      else {
+        const auto *Handle =
+            dyn_cast_or_null<RawBufferExtType>(UAV.getHandleTy());
+
+        if (!Handle)
+          reportInvalidHandleTyBoundInRs(M, "srv", Binding);
+      }
     }
 
     for (const ResourceInfo &Sampler : DRM.samplers()) {

@llvmbot
Copy link
Member

llvmbot commented Jul 8, 2025

@llvm/pr-subscribers-backend-directx

Author: None (joaosaffran)

Changes

DXC doesn't allow Textures/TypedBuffers to bind with root signature descriptors, this implements the same check in clang.

Closes: #126647


Full diff: https://github.com/llvm/llvm-project/pull/147573.diff

2 Files Affected:

  • (added) clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl (+13)
  • (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+25)
diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl
new file mode 100644
index 0000000000000..9daf38e30dd67
--- /dev/null
+++ b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl
@@ -0,0 +1,13 @@
+// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s
+
+// CHECK: error: register srv (space=0, register=0) is bound to a texture or typed buffer.
+
+RWStructuredBuffer<int> Out : register(u0);
+Buffer<float> B : register(t0);
+// Compute Shader for UAV testing
+[numthreads(8, 8, 1)]
+[RootSignature("SRV(t0), UAV(u0)")]
+void CSMain(uint id : SV_GroupID)
+{
+    Out[0] = B[0];
+}
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index a52a04323514c..c34f31fbe35e5 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -85,6 +85,17 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
   }
 }
 
+static void
+reportInvalidHandleTyBoundInRs(Module &M, Twine Type,
+                               ResourceInfo::ResourceBinding Binding) {
+  SmallString<128> Message;
+  raw_svector_ostream OS(Message);
+  OS << "register " << Type << " (space=" << Binding.Space
+     << ", register=" << Binding.LowerBound << ")"
+     << " is bound to a texture or typed buffer.";
+  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
 static void reportRegNotBound(Module &M, Twine Type,
                               ResourceInfo::ResourceBinding Binding) {
   SmallString<128> Message;
@@ -163,12 +174,26 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
       ResourceInfo::ResourceBinding Binding = SRV.getBinding();
       if (!Validation.checkTRegBinding(Binding))
         reportRegNotBound(M, "srv", Binding);
+      else {
+        const auto *Handle =
+            dyn_cast_or_null<RawBufferExtType>(SRV.getHandleTy());
+
+        if (!Handle)
+          reportInvalidHandleTyBoundInRs(M, "srv", Binding);
+      }
     }
 
     for (const ResourceInfo &UAV : DRM.uavs()) {
       ResourceInfo::ResourceBinding Binding = UAV.getBinding();
       if (!Validation.checkURegBinding(Binding))
         reportRegNotBound(M, "uav", Binding);
+      else {
+        const auto *Handle =
+            dyn_cast_or_null<RawBufferExtType>(UAV.getHandleTy());
+
+        if (!Handle)
+          reportInvalidHandleTyBoundInRs(M, "srv", Binding);
+      }
     }
 
     for (const ResourceInfo &Sampler : DRM.samplers()) {

@llvmbot
Copy link
Member

llvmbot commented Jul 8, 2025

@llvm/pr-subscribers-clang

Author: None (joaosaffran)

Changes

DXC doesn't allow Textures/TypedBuffers to bind with root signature descriptors, this implements the same check in clang.

Closes: #126647


Full diff: https://github.com/llvm/llvm-project/pull/147573.diff

2 Files Affected:

  • (added) clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl (+13)
  • (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+25)
diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl
new file mode 100644
index 0000000000000..9daf38e30dd67
--- /dev/null
+++ b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl
@@ -0,0 +1,13 @@
+// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s
+
+// CHECK: error: register srv (space=0, register=0) is bound to a texture or typed buffer.
+
+RWStructuredBuffer<int> Out : register(u0);
+Buffer<float> B : register(t0);
+// Compute Shader for UAV testing
+[numthreads(8, 8, 1)]
+[RootSignature("SRV(t0), UAV(u0)")]
+void CSMain(uint id : SV_GroupID)
+{
+    Out[0] = B[0];
+}
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index a52a04323514c..c34f31fbe35e5 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -85,6 +85,17 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
   }
 }
 
+static void
+reportInvalidHandleTyBoundInRs(Module &M, Twine Type,
+                               ResourceInfo::ResourceBinding Binding) {
+  SmallString<128> Message;
+  raw_svector_ostream OS(Message);
+  OS << "register " << Type << " (space=" << Binding.Space
+     << ", register=" << Binding.LowerBound << ")"
+     << " is bound to a texture or typed buffer.";
+  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
 static void reportRegNotBound(Module &M, Twine Type,
                               ResourceInfo::ResourceBinding Binding) {
   SmallString<128> Message;
@@ -163,12 +174,26 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
       ResourceInfo::ResourceBinding Binding = SRV.getBinding();
       if (!Validation.checkTRegBinding(Binding))
         reportRegNotBound(M, "srv", Binding);
+      else {
+        const auto *Handle =
+            dyn_cast_or_null<RawBufferExtType>(SRV.getHandleTy());
+
+        if (!Handle)
+          reportInvalidHandleTyBoundInRs(M, "srv", Binding);
+      }
     }
 
     for (const ResourceInfo &UAV : DRM.uavs()) {
       ResourceInfo::ResourceBinding Binding = UAV.getBinding();
       if (!Validation.checkURegBinding(Binding))
         reportRegNotBound(M, "uav", Binding);
+      else {
+        const auto *Handle =
+            dyn_cast_or_null<RawBufferExtType>(UAV.getHandleTy());
+
+        if (!Handle)
+          reportInvalidHandleTyBoundInRs(M, "srv", Binding);
+      }
     }
 
     for (const ResourceInfo &Sampler : DRM.samplers()) {

@joaosaffran joaosaffran changed the title [DirectX] Validate if Textures/TypedBuffers are being bind in Root Signatures [DirectX] Validate if Textures/TypedBuffers are being bound in Root Signatures Jul 8, 2025
Copy link
Contributor

@bogner bogner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this implements the same check in clang.

This isn't a check "in clang" - that implies that this is a frontend check, but the logic here is fully in the backend. That said - does this need to be done post optimizations? Couldn't a frontend check catch this reliably?

Copy link
Contributor

@bogner bogner Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the right place for this test - we can't have clang tests for llvm backend behaviour. We'll need something in llvm/test/CodeGen/DirectX instead.

@joaosaffran joaosaffran requested a review from bogner July 8, 2025 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:DirectX clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants