Skip to content

Commit 0eba8cb

Browse files
authored
[DirectX] Implement Max64UAVs shader flag analysis (#136229)
Fixes [#114553](#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.
1 parent b20e063 commit 0eba8cb

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

llvm/lib/Target/DirectX/DXILShaderFlags.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,16 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
255255
EntryFunProps.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
256256
*(EntryFunProps.Entry), "Inconsistent optnone attribute "));
257257
}
258+
259+
// Set the Max64UAVs flag if the number of UAVs is > 8
260+
uint32_t NumUAVs = 0;
261+
for (auto &UAV : DRM.uavs())
262+
if (MMDI.DXILVersion < VersionTuple(1, 6))
263+
NumUAVs++;
264+
else // MMDI.DXILVersion >= VersionTuple(1, 6)
265+
NumUAVs += UAV.getBinding().Size;
266+
if (NumUAVs > 8)
267+
CombinedSFMask.Max64UAVs = true;
258268
}
259269

260270
void ComputedShaderFlags::print(raw_ostream &OS) const {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
; This test makes sure that resource arrays only add 1 to the count of the
4+
; number of UAVs for setting the shader flag '64 UAV slots' when the shader
5+
; model version is < 6.6
6+
7+
; Note: there is no feature flag here (only a module flag), so we don't have an
8+
; object test.
9+
10+
target triple = "dxil-pc-shadermodel6.5-library"
11+
12+
; CHECK: Combined Shader Flags for Module
13+
; CHECK-NEXT: Shader Flags Value: 0x00000000
14+
15+
; CHECK-NOT: Note: shader requires additional functionality:
16+
; CHECK-NOT: 64 UAV slots
17+
18+
; CHECK: Function test : 0x00000000
19+
define void @test() "hlsl.export" {
20+
; RWBuffer<float> Buf : register(u0, space0)
21+
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
22+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
23+
i32 0, i32 0, i32 1, i32 0, i1 false)
24+
25+
; RWBuffer<float> Buf[8] : register(u1, space0)
26+
%buf1 = call target("dx.TypedBuffer", float, 1, 0, 1)
27+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
28+
i32 0, i32 1, i32 8, i32 0, i1 false)
29+
ret void
30+
}
31+
32+
!llvm.module.flags = !{!0}
33+
!0 = !{i32 1, !"dx.resmayalias", i32 1}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
; This test makes sure that resource arrays sizes are accounted for when
4+
; counting the number of UAVs for setting the shader flag '64 UAV slots' when
5+
; the shader model version is >= 6.6
6+
7+
; Note: there is no feature flag here (only a module flag), so we don't have an
8+
; object test.
9+
10+
target triple = "dxil-pc-shadermodel6.6-library"
11+
12+
; CHECK: Combined Shader Flags for Module
13+
; CHECK-NEXT: Shader Flags Value: 0x00008000
14+
15+
; CHECK: Note: shader requires additional functionality:
16+
; CHECK: 64 UAV slots
17+
18+
; CHECK: Function test : 0x00000000
19+
define void @test() "hlsl.export" {
20+
; RWBuffer<float> Buf : register(u0, space0)
21+
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
22+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
23+
i32 0, i32 0, i32 1, i32 0, i1 false)
24+
25+
; RWBuffer<float> Buf[8] : register(u1, space0)
26+
%buf1 = call target("dx.TypedBuffer", float, 1, 0, 1)
27+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
28+
i32 0, i32 1, i32 8, i32 0, i1 false)
29+
ret void
30+
}
31+
32+
!llvm.module.flags = !{!0}
33+
!0 = !{i32 1, !"dx.resmayalias", i32 1}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
; This test makes sure that the shader flag '64 UAV slots' is set when there are
4+
; more than 8 UAVs in the module.
5+
6+
; Note: there is no feature flag here (only a module flag), so we don't have an
7+
; object test.
8+
9+
target triple = "dxil-pc-shadermodel6.7-library"
10+
11+
; CHECK: Combined Shader Flags for Module
12+
; CHECK-NEXT: Shader Flags Value: 0x00008000
13+
14+
; CHECK: Note: shader requires additional functionality:
15+
; CHECK: 64 UAV slots
16+
17+
; Note: 64 UAV slots does not get set per-function
18+
; CHECK: Function test : 0x00000000
19+
define void @test() "hlsl.export" {
20+
; RWBuffer<float> Buf : register(u0, space0)
21+
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
22+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
23+
i32 0, i32 0, i32 1, i32 0, i1 false)
24+
; RWBuffer<float> Buf : register(u1, space0)
25+
%buf1 = call target("dx.TypedBuffer", float, 1, 0, 1)
26+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
27+
i32 0, i32 1, i32 1, i32 0, i1 false)
28+
; RWBuffer<float> Buf : register(u2, space0)
29+
%buf2 = call target("dx.TypedBuffer", float, 1, 0, 1)
30+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
31+
i32 0, i32 2, i32 1, i32 0, i1 false)
32+
; RWBuffer<float> Buf : register(u3, space0)
33+
%buf3 = call target("dx.TypedBuffer", float, 1, 0, 1)
34+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
35+
i32 0, i32 3, i32 1, i32 0, i1 false)
36+
; RWBuffer<float> Buf : register(u4, space0)
37+
%buf4 = call target("dx.TypedBuffer", float, 1, 0, 1)
38+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
39+
i32 0, i32 4, i32 1, i32 0, i1 false)
40+
; RWBuffer<float> Buf : register(u5, space0)
41+
%buf5 = call target("dx.TypedBuffer", float, 1, 0, 1)
42+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
43+
i32 0, i32 5, i32 1, i32 0, i1 false)
44+
; RWBuffer<float> Buf : register(u6, space0)
45+
%buf6 = call target("dx.TypedBuffer", float, 1, 0, 1)
46+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
47+
i32 0, i32 6, i32 1, i32 0, i1 false)
48+
; RWBuffer<float> Buf : register(u7, space0)
49+
%buf7 = call target("dx.TypedBuffer", float, 1, 0, 1)
50+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
51+
i32 0, i32 7, i32 1, i32 0, i1 false)
52+
; RWBuffer<float> Buf : register(u8, space0)
53+
%buf8 = call target("dx.TypedBuffer", float, 1, 0, 1)
54+
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
55+
i32 0, i32 8, i32 1, i32 0, i1 false)
56+
ret void
57+
}
58+
59+
!llvm.module.flags = !{!0}
60+
!0 = !{i32 1, !"dx.resmayalias", i32 1}

0 commit comments

Comments
 (0)