Skip to content

[DirectX] Implement Max64UAVs shader flag analysis #136229

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

Merged
merged 1 commit into from
Apr 22, 2025

Conversation

Icohedron
Copy link
Contributor

Fixes #114553

This implementation replicates the behavior of DXC in setting the m_b64UAVs flag: the Max64UAVs DXIL module flag is set in the presence of more than 8 UAVs in a DXIL module.

The behavior of how UAV (resource) arrays are counted differs based on Shader Model version:

  • If Shader Model < 6.6, then a UAV array counts as a single UAV regardless of its range size
  • if Shader Model >= 6.6, then a UAV array contributes its range size to the total number of UAVs

I initially thought the complete implementation of this analysis may be blocked by the resource arrays implementation, but it seems that it is not the case, as the @llvm.dx.resource.handle* already includes a range size argument.

@llvmbot
Copy link
Member

llvmbot commented Apr 18, 2025

@llvm/pr-subscribers-backend-directx

Author: Deric C. (Icohedron)

Changes

Fixes #114553

This implementation replicates the behavior of DXC in setting the m_b64UAVs flag: the Max64UAVs DXIL module flag is set in the presence of more than 8 UAVs in a DXIL module.

The behavior of how UAV (resource) arrays are counted differs based on Shader Model version:

  • If Shader Model < 6.6, then a UAV array counts as a single UAV regardless of its range size
  • if Shader Model >= 6.6, then a UAV array contributes its range size to the total number of UAVs

I initially thought the complete implementation of this analysis may be blocked by the resource arrays implementation, but it seems that it is not the case, as the @<!-- -->llvm.dx.resource.handle* already includes a range size argument.


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

4 Files Affected:

  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+10)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll (+33)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll (+33)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll (+60)
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 1331b0d1d852b..282b9dcf6de2b 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -255,6 +255,16 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
         EntryFunProps.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
             *(EntryFunProps.Entry), "Inconsistent optnone attribute "));
   }
+
+  // Set the Max64UAVs flag if the number of UAVs is > 8
+  uint32_t NumUAVs = 0;
+  for (auto &UAV : DRM.uavs())
+    if (MMDI.DXILVersion < VersionTuple(1, 6))
+      NumUAVs++;
+    else // MMDI.DXILVersion >= VersionTuple(1, 6)
+      NumUAVs += UAV.getBinding().Size;
+  if (NumUAVs > 8)
+    CombinedSFMask.Max64UAVs = true;
 }
 
 void ComputedShaderFlags::print(raw_ostream &OS) const {
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll
new file mode 100644
index 0000000000000..5b978d67866be
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll
@@ -0,0 +1,33 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+; This test makes sure that resource arrays only add 1 to the count of the
+; number of UAVs for setting the shader flag '64 UAV slots' when the shader
+; model version is < 6.6
+
+; Note: there is no feature flag here (only a module flag), so we don't have an
+; object test.
+
+target triple = "dxil-pc-shadermodel6.5-library"
+
+; CHECK:      Combined Shader Flags for Module
+; CHECK-NEXT: Shader Flags Value: 0x00000000
+
+; CHECK-NOT: Note: shader requires additional functionality:
+; CHECK-NOT:    64 UAV slots
+
+; CHECK: Function test : 0x00000000
+define void @test() "hlsl.export" {
+  ; RWBuffer<float> Buf : register(u0, space0)
+  %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 0, i32 1, i32 0, i1 false)
+
+  ; RWBuffer<float> Buf[8] : register(u1, space0)
+  %buf1 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 1, i32 8, i32 0, i1 false)
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll
new file mode 100644
index 0000000000000..4b901a78e6ea4
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll
@@ -0,0 +1,33 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+; This test makes sure that resource arrays sizes are accounted for when
+; counting the number of UAVs for setting the shader flag '64 UAV slots' when
+; the shader model version is >= 6.6
+
+; Note: there is no feature flag here (only a module flag), so we don't have an
+; object test.
+
+target triple = "dxil-pc-shadermodel6.6-library"
+
+; CHECK:      Combined Shader Flags for Module
+; CHECK-NEXT: Shader Flags Value: 0x00008000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK:        64 UAV slots
+
+; CHECK: Function test : 0x00000000
+define void @test() "hlsl.export" {
+  ; RWBuffer<float> Buf : register(u0, space0)
+  %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 0, i32 1, i32 0, i1 false)
+
+  ; RWBuffer<float> Buf[8] : register(u1, space0)
+  %buf1 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 1, i32 8, i32 0, i1 false)
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll
new file mode 100644
index 0000000000000..c002ff2851452
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll
@@ -0,0 +1,60 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+; This test makes sure that the shader flag '64 UAV slots' is set when there are
+; more than 8 UAVs in the module.
+
+; Note: there is no feature flag here (only a module flag), so we don't have an
+; object test.
+
+target triple = "dxil-pc-shadermodel6.7-library"
+
+; CHECK:      Combined Shader Flags for Module
+; CHECK-NEXT: Shader Flags Value: 0x00008000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK:       64 UAV slots
+
+; Note: 64 UAV slots does not get set per-function
+; CHECK: Function test : 0x00000000
+define void @test() "hlsl.export" {
+  ; RWBuffer<float> Buf : register(u0, space0)
+  %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 0, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u1, space0)
+  %buf1 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 1, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u2, space0)
+  %buf2 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 2, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u3, space0)
+  %buf3 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 3, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u4, space0)
+  %buf4 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 4, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u5, space0)
+  %buf5 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 5, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u6, space0)
+  %buf6 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 6, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u7, space0)
+  %buf7 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 7, i32 1, i32 0, i1 false)
+  ; RWBuffer<float> Buf : register(u8, space0)
+  %buf8 = call target("dx.TypedBuffer", float, 1, 0, 1)
+       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
+           i32 0, i32 8, i32 1, i32 0, i1 false)
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}

Copy link
Contributor

@spall spall left a comment

Choose a reason for hiding this comment

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

lgtm

@Icohedron Icohedron merged commit 0eba8cb into llvm:main Apr 22, 2025
12 of 14 checks passed
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Fixes [llvm#114553](llvm#114553)

This implementation replicates the behavior of DXC in setting the
`m_b64UAVs` flag: the `Max64UAVs` DXIL module flag is set in the
presence of more than 8 UAVs in a DXIL module.

The behavior of how UAV (resource) arrays are counted differs based on
Shader Model version:
- If Shader Model < 6.6, then a UAV array counts as a single UAV
regardless of its range size
- if Shader Model >= 6.6, then a UAV array contributes its range size to
the total number of UAVs

I initially thought the complete implementation of this analysis may be
blocked by the resource arrays implementation, but it seems that it is
not the case, as the `@llvm.dx.resource.handle*` already includes a
range size argument.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Fixes [llvm#114553](llvm#114553)

This implementation replicates the behavior of DXC in setting the
`m_b64UAVs` flag: the `Max64UAVs` DXIL module flag is set in the
presence of more than 8 UAVs in a DXIL module.

The behavior of how UAV (resource) arrays are counted differs based on
Shader Model version:
- If Shader Model < 6.6, then a UAV array counts as a single UAV
regardless of its range size
- if Shader Model >= 6.6, then a UAV array contributes its range size to
the total number of UAVs

I initially thought the complete implementation of this analysis may be
blocked by the resource arrays implementation, but it seems that it is
not the case, as the `@llvm.dx.resource.handle*` already includes a
range size argument.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Fixes [llvm#114553](llvm#114553)

This implementation replicates the behavior of DXC in setting the
`m_b64UAVs` flag: the `Max64UAVs` DXIL module flag is set in the
presence of more than 8 UAVs in a DXIL module.

The behavior of how UAV (resource) arrays are counted differs based on
Shader Model version:
- If Shader Model < 6.6, then a UAV array counts as a single UAV
regardless of its range size
- if Shader Model >= 6.6, then a UAV array contributes its range size to
the total number of UAVs

I initially thought the complete implementation of this analysis may be
blocked by the resource arrays implementation, but it seems that it is
not the case, as the `@llvm.dx.resource.handle*` already includes a
range size argument.
@damyanp damyanp removed this from HLSL Support Jun 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DirectX] Implement Shader Flags Analysis for Max64UAVs
4 participants