[llvm] d75923d - [DirectX] Add shader flags for heap resources (#216461)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 14:50:05 PDT 2026
Author: Helena Kotas
Date: 2026-08-25T14:50:01-07:00
New Revision: d75923dd7cf0f7f69a9f296cef75f60d9f373e53
URL: https://github.com/llvm/llvm-project/commit/d75923dd7cf0f7f69a9f296cef75f60d9f373e53
DIFF: https://github.com/llvm/llvm-project/commit/d75923dd7cf0f7f69a9f296cef75f60d9f373e53.diff
LOG: [DirectX] Add shader flags for heap resources (#216461)
Descriptor-heap usage must be recorded in the shader feature flags. The
`DXILShaderFlags` pass inspects each `llvm.dx.resource.handlefromheap`
call and sets the `SamplerDescriptorHeapIndexing` shader flag when
`IsSamplerHeap` is `true`, or `ResourceDescriptorHeapIndexing` flag when
it is `false`.
Fixes #213825
Added:
llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources-max64uavs.ll
llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources.ll
llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs-heap.ll
Modified:
llvm/lib/Target/DirectX/DXILShaderFlags.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 668f2453d9157..e404eb8109769 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -34,7 +34,10 @@ using namespace llvm::dxil;
static bool hasUAVsAtEveryStage(const DXILResourceMap &DRM,
const ModuleMetadataInfo &MMDI) {
- if (DRM.uavs().empty())
+ // Heap resources do not count towards hasUAVsAtEveryStage.
+ bool HasUAVWithBinding = any_of(
+ DRM.uavs(), [](const ResourceInfo &RI) { return RI.hasBinding(); });
+ if (!HasUAVWithBinding)
return false;
switch (MMDI.ShaderProfile) {
@@ -274,6 +277,18 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
}
break;
}
+ case Intrinsic::dx_resource_handlefromheap: {
+ dxil::ResourceTypeInfo &RTI = DRTM[cast<TargetExtType>(II->getType())];
+ bool IsSamplerHeap = RTI.isSampler();
+ CSF.SamplerDescriptorHeapIndexing |= IsSamplerHeap;
+ CSF.ResourceDescriptorHeapIndexing |= !IsSamplerHeap;
+
+ if (!CSF.ResMayNotAlias && CanSetResMayNotAlias && RTI.isUAV() &&
+ MMDI.ValidatorVersion >= VersionTuple(1, 8)) {
+ CSF.ResMayNotAlias = true;
+ }
+ break;
+ }
case Intrinsic::dx_resource_load_typedbuffer: {
dxil::ResourceTypeInfo &RTI =
DRTM[cast<TargetExtType>(II->getArgOperand(0)->getType())];
@@ -338,7 +353,10 @@ ModuleShaderFlags::gatherGlobalModuleFlags(const Module &M,
// Set the Max64UAVs flag if the number of UAVs is > 8
uint32_t NumUAVs = 0;
- for (auto &UAV : DRM.uavs())
+ for (auto &UAV : DRM.uavs()) {
+ // Heap resources do not count towards Max64UAVs flag.
+ if (!UAV.hasBinding())
+ continue;
if (MMDI.ValidatorVersion < VersionTuple(1, 6)) {
NumUAVs++;
} else { // MMDI.ValidatorVersion >= VersionTuple(1, 6)
@@ -348,6 +366,7 @@ ModuleShaderFlags::gatherGlobalModuleFlags(const Module &M,
NewNum = ~0U;
NumUAVs = NewNum;
}
+ }
if (NumUAVs > 8)
CSF.Max64UAVs = true;
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources-max64uavs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources-max64uavs.ll
new file mode 100644
index 0000000000000..c18f05189fe6b
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources-max64uavs.ll
@@ -0,0 +1,42 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+; RUN: llc %s -disable-dxil-remove-unused-resources --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
+
+; This test verifies that the Max64UAVs flag is *not* set if there
+; are 9 or more heap UAVs, since a heap UAVs do not count.
+
+target triple = "dxil-pc-shadermodel6.6-library"
+
+; CHECK: Combined Shader Flags for Module
+; CHECK-NEXT: Shader Flags Value: 0x40000000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK-NOT: 64 UAV slots
+; CHECK: Resource descriptor heap indexing
+
+; CHECK: Function test : 0x40000000
+define void @test() "hlsl.export" {
+
+ %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 0)
+ %2 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 1)
+ %3 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 2)
+ %4 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 3)
+ %5 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 4)
+ %6 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 5)
+ %7 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 6)
+ %8 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 7)
+ %9 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromheap(i32 8)
+
+ ret void
+}
+
+!dx.valver = !{!0}
+!0 = !{i32 1, i32 8}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC: Max64UAVs: false
+; DXC: ResourceDescriptorHeapIndexing: true
+; DXC: SamplerDescriptorHeapIndexing: false
+; DXC: NextUnusedBit: false
+
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources.ll
new file mode 100644
index 0000000000000..edc66cf470505
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/heap-resources.ll
@@ -0,0 +1,52 @@
+; RUN: opt -S --passes="print-dx-shader-flags" -mtriple=dxil-pc-shadermodel6.6-library 2>&1 %s | FileCheck %s --check-prefixes=CHECK,CHECK-66
+; RUN: opt -S --passes="print-dx-shader-flags" -mtriple=dxil-pc-shadermodel6.7-library 2>&1 %s | FileCheck %s --check-prefixes=CHECK,CHECK-67
+; RUN: llc %s -disable-dxil-remove-unused-resources -mtriple=dxil-pc-shadermodel6.7-library --filetype=obj -o - | \
+; RUN: obj2yaml | FileCheck %s --check-prefix=DXC
+
+; This test makes sure that the shader flag 'Resource descriptor heap indexing'
+; is set when the shader uses llvm.dx.resource.handlefromheap intrinsic to get
+; a resource from a resource descriptor heap, and that the shader flag
+; `Sampler descriptor heap indexing` is set when the shader uses the same
+; intrinsic to get a sampler from a sampler descriptor heap.
+
+; It also checks that the flag "Any UAV may not alias any other UAV" is set for
+; a function that uses a heap UAV resource, but only for shader model 6.7 and higher.
+
+; CHECK: Combined Shader Flags for Module
+; CHECK-66: Shader Flags Value: 0xc0000000
+; CHECK-67: Shader Flags Value: 0x2c0000000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK: Resource descriptor heap indexing
+; CHECK: Sampler descriptor heap indexing
+
+; CHECK: Note: extra DXIL module flags:
+; CHECK-67: Any UAV may not alias any other UAV
+;
+; CHECK-66: Function test_1 : 0x40000000
+; CHECK-67: Function test_1 : 0x240000000
+define void @test_1() "hlsl.export" {
+ ; RWBuffer<float4> Buf = ResourceDescriptorHeap[3]
+ %typed = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.resource.handlefromheap.tdx.TypedBuffer_v4f32_1_0_0(i32 3)
+ ret void
+}
+
+; CHECK: Function test_2 : 0x80000000
+define void @test_2() "hlsl.export" {
+ ; SamplerState Samp = SamplerDescriptorHeap[100];
+ %samp = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefromheap.tdx.Sampler_0(i32 100)
+ ret void
+}
+
+!dx.valver = !{!0}
+!0 = !{i32 1, i32 8}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC: ResourceDescriptorHeapIndexing: true
+; DXC: SamplerDescriptorHeapIndexing: true
+; DXC: NextUnusedBit: false
+
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs-heap.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs-heap.ll
new file mode 100644
index 0000000000000..364147af538cd
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs-heap.ll
@@ -0,0 +1,36 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+; TODO: Remove this comment and add 'RUN' to the line below once vertex shaders are supported by llc
+; llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
+
+; This test ensures that a Vertex shader with a UAV resource from heap
+; does *not* set the module and shader feature flag UAVsAtEveryStage.
+
+target triple = "dxil-pc-shadermodel6.5-vertex"
+
+; CHECK: Combined Shader Flags for Module
+; CHECK-NOT: Shader Flags Value: 0x400000000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK-NOT: UAVs at every shader stage
+; CHECK: Resource descriptor heap indexing
+
+; CHECK: Function VSMain : 0x40000000
+define void @VSMain() {
+ ; RWBuffer<float> Buf : register(u0, space0)
+ %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
+ @llvm.dx.resource.handlefromheap.tdx.TypedBuffer_f32_1_0t(i32 7)
+ ret void
+}
+
+!dx.valver = !{!1}
+!1 = !{i32 1, i32 8}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC: UAVsAtEveryStage: false
+; DXC: NextUnusedBit: false
+; DXC: ...
More information about the llvm-commits
mailing list