https://github.com/bogner updated https://github.com/llvm/llvm-project/pull/117303
>From 05f412f47b8d30ff1db9372225001c75289bed44 Mon Sep 17 00:00:00 2001 From: Justin Bogner <m...@justinbogner.com> Date: Thu, 21 Nov 2024 23:18:13 -0800 Subject: [PATCH 1/2] [HLSL] Get the index for resource bindings from the slot Resource bindings are indexed from the beginning of the binding space, not from the binding itself. This means that we need to populate the index for non-array resources with the same value as the slot number (and arrays, when we implement them, will be the sum of the slot number and the access index). --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 2 +- .../builtins/RWBuffer-constructor.hlsl | 2 +- .../StructuredBuffers-constructors.hlsl | 20 +++++++++---------- clang/test/CodeGenHLSL/resource-bindings.hlsl | 19 ++++++++++++++++++ 4 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 clang/test/CodeGenHLSL/resource-bindings.hlsl diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 7ba0d615018181..b4e17466087b16 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -588,7 +588,7 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { auto *Slot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber()); // FIXME: resource arrays are not yet implemented auto *Range = llvm::ConstantInt::get(CGM.IntTy, 1); - auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0); + auto *Index = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber()); // FIXME: NonUniformResourceIndex bit is not yet implemented auto *NonUniform = llvm::ConstantInt::get(Int1Ty, false); llvm::Value *Args[] = {Space, Slot, Range, Index, NonUniform}; diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl index 3949f7b943cfe0..a820d782896aaf 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl @@ -19,7 +19,7 @@ RWBuffer<float> Buf : register(u5, space3); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 5, i1 false) // CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4 // CHECK-SPIRV-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.spv.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4 diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl index 2e141b9279fa61..d7478c2981a85d 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl @@ -37,24 +37,24 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 10, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf, align 4 -// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 5, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2, align 4 -// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 3, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf3_h, ptr @Buf3, align 4 -// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 4, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4 -// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 1, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4 -// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 10, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf", align 4 -// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 5, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2", align 4 -// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 3, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf3_h, ptr @Buf3, align 4 -// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 4, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4 -// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 1, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4 diff --git a/clang/test/CodeGenHLSL/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resource-bindings.hlsl new file mode 100644 index 00000000000000..dfa65f3e6cc314 --- /dev/null +++ b/clang/test/CodeGenHLSL/resource-bindings.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil--shadermodel6.6-compute -x hlsl -finclude-default-header -emit-llvm -o - %s | FileCheck %s + +// CHECK: define internal void @_init_resource_bindings() { + +// CHECK: %U0S0_h = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) +RWBuffer<float4> U0S0 : register(u0); + +// CHECK: %U5S3_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 5, i1 false) +RWBuffer<float> U5S3 : register(u5, space3); + +// CHECK: %T2S2_h = call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i32_0_0t(i32 2, i32 2, i32 1, i32 2, i1 false) +StructuredBuffer<int> T2S2 : register(t2, space2); +struct S { + float4 f; + int i; +}; + +// CHECK: %T3S0_h = call target("dx.RawBuffer", %struct.S = type { <4 x float>, i32, [12 x i8] }, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_s_struct.Ss_0_0t(i32 0, i32 3, i32 1, i32 3, i1 false) +StructuredBuffer<S> T3S0 : register(t3); >From 2360f3a59f839cfba6c9e0246696fe4c2ded8044 Mon Sep 17 00:00:00 2001 From: Justin Bogner <m...@justinbogner.com> Date: Fri, 22 Nov 2024 14:07:32 -0800 Subject: [PATCH 2/2] Move the fix to the DirectX backend --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 2 +- .../builtins/RWBuffer-constructor.hlsl | 2 +- .../StructuredBuffers-constructors.hlsl | 20 +++++++------- clang/test/CodeGenHLSL/resource-bindings.hlsl | 6 ++--- llvm/docs/DirectX/DXILResources.rst | 15 ++++++++--- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 17 +++++++++--- llvm/test/CodeGen/DirectX/CreateHandle.ll | 27 ++++++++++--------- .../DirectX/CreateHandleFromBinding.ll | 27 ++++++++++--------- 8 files changed, 68 insertions(+), 48 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index b4e17466087b16..7ba0d615018181 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -588,7 +588,7 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { auto *Slot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber()); // FIXME: resource arrays are not yet implemented auto *Range = llvm::ConstantInt::get(CGM.IntTy, 1); - auto *Index = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber()); + auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0); // FIXME: NonUniformResourceIndex bit is not yet implemented auto *NonUniform = llvm::ConstantInt::get(Int1Ty, false); llvm::Value *Args[] = {Space, Slot, Range, Index, NonUniform}; diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl index a820d782896aaf..3949f7b943cfe0 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl @@ -19,7 +19,7 @@ RWBuffer<float> Buf : register(u5, space3); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 5, i1 false) +// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4 // CHECK-SPIRV-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.spv.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4 diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl index d7478c2981a85d..2e141b9279fa61 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl @@ -37,24 +37,24 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 10, i1 false) +// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf, align 4 -// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 5, i1 false) +// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2, align 4 -// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 3, i1 false) +// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf3_h, ptr @Buf3, align 4 -// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 4, i1 false) +// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4 -// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 1, i1 false) +// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4 -// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 10, i1 false) +// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf", align 4 -// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 5, i1 false) +// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2", align 4 -// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 3, i1 false) +// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf3_h, ptr @Buf3, align 4 -// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 4, i1 false) +// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4 -// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 1, i1 false) +// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4 diff --git a/clang/test/CodeGenHLSL/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resource-bindings.hlsl index dfa65f3e6cc314..bfec90e1871f8b 100644 --- a/clang/test/CodeGenHLSL/resource-bindings.hlsl +++ b/clang/test/CodeGenHLSL/resource-bindings.hlsl @@ -5,15 +5,15 @@ // CHECK: %U0S0_h = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) RWBuffer<float4> U0S0 : register(u0); -// CHECK: %U5S3_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 5, i1 false) +// CHECK: %U5S3_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) RWBuffer<float> U5S3 : register(u5, space3); -// CHECK: %T2S2_h = call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i32_0_0t(i32 2, i32 2, i32 1, i32 2, i1 false) +// CHECK: %T2S2_h = call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i32_0_0t(i32 2, i32 2, i32 1, i32 0, i1 false) StructuredBuffer<int> T2S2 : register(t2, space2); struct S { float4 f; int i; }; -// CHECK: %T3S0_h = call target("dx.RawBuffer", %struct.S = type { <4 x float>, i32, [12 x i8] }, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_s_struct.Ss_0_0t(i32 0, i32 3, i32 1, i32 3, i1 false) +// CHECK: %T3S0_h = call target("dx.RawBuffer", %struct.S = type { <4 x float>, i32, [12 x i8] }, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_s_struct.Ss_0_0t(i32 0, i32 3, i32 1, i32 0, i1 false) StructuredBuffer<S> T3S0 : register(t3); diff --git a/llvm/docs/DirectX/DXILResources.rst b/llvm/docs/DirectX/DXILResources.rst index ad8ede9c59fbfa..dcec9611d8aaa0 100644 --- a/llvm/docs/DirectX/DXILResources.rst +++ b/llvm/docs/DirectX/DXILResources.rst @@ -162,9 +162,10 @@ the subsequent ``dx.op.annotateHandle`` operation in. Note that we don't have an analogue for `dx.op.createHandle`_, since ``dx.op.createHandleFromBinding`` subsumes it. -For simplicity of lowering, we match DXIL in using an index from the beginning -of the binding space rather than an index from the lower bound of the binding -itself. +We diverge from DXIL and index from the beginning of the binding rather than +indexing from the beginning of the binding space. This matches the semantics +more clearly and avoids a non-obvious invariant in what constitutes valid +arguments. .. _dx.op.createHandle: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-handles @@ -194,7 +195,7 @@ itself. * - ``%index`` - 4 - ``i32`` - - Index from the beginning of the binding space to access. + - Index from the beginning of the binding. * - ``%non-uniform`` - 5 - i1 @@ -233,6 +234,12 @@ Examples: @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( i32 1, i32 8, i32 1, i32 0, i1 false) + ; RWBuffer<float4> Global[3] : register(u6, space5) + ; RWBuffer<float4> Buf = Global[2]; + %buf = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0( + i32 5, i32 6, i32 3, i32 2, i1 false) + .. list-table:: ``@llvm.dx.handle.fromHeap`` :header-rows: 1 diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 9f124394363a38..047c5412e1f3ae 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -236,9 +236,14 @@ class OpLowerer { dxil::ResourceInfo &RI = *It; const auto &Binding = RI.getBinding(); + Value *IndexOp = CI->getArgOperand(3); + if (Binding.LowerBound != 0) + IndexOp = IRB.CreateAdd(IndexOp, + ConstantInt::get(Int32Ty, Binding.LowerBound)); + std::array<Value *, 4> Args{ ConstantInt::get(Int8Ty, llvm::to_underlying(RI.getResourceClass())), - ConstantInt::get(Int32Ty, Binding.RecordID), CI->getArgOperand(3), + ConstantInt::get(Int32Ty, Binding.RecordID), IndexOp, CI->getArgOperand(4)}; Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(OpCode::CreateHandle, Args, CI->getName()); @@ -257,6 +262,7 @@ class OpLowerer { [[nodiscard]] bool lowerToBindAndAnnotateHandle(Function &F) { IRBuilder<> &IRB = OpBuilder.getIRB(); + Type *Int32Ty = IRB.getInt32Ty(); return replaceFunction(F, [&](CallInst *CI) -> Error { IRB.SetInsertPoint(CI); @@ -266,6 +272,12 @@ class OpLowerer { dxil::ResourceInfo &RI = *It; const auto &Binding = RI.getBinding(); + + Value *IndexOp = CI->getArgOperand(3); + if (Binding.LowerBound != 0) + IndexOp = IRB.CreateAdd(IndexOp, + ConstantInt::get(Int32Ty, Binding.LowerBound)); + std::pair<uint32_t, uint32_t> Props = RI.getAnnotateProps(); // For `CreateHandleFromBinding` we need the upper bound rather than the @@ -276,8 +288,7 @@ class OpLowerer { : Binding.LowerBound + Binding.Size - 1; Constant *ResBind = OpBuilder.getResBind( Binding.LowerBound, UpperBound, Binding.Space, RI.getResourceClass()); - std::array<Value *, 3> BindArgs{ResBind, CI->getArgOperand(3), - CI->getArgOperand(4)}; + std::array<Value *, 3> BindArgs{ResBind, IndexOp, CI->getArgOperand(4)}; Expected<CallInst *> OpBind = OpBuilder.tryCreateOp( OpCode::CreateHandleFromBinding, BindArgs, CI->getName()); if (Error E = OpBind.takeError()) diff --git a/llvm/test/CodeGen/DirectX/CreateHandle.ll b/llvm/test/CodeGen/DirectX/CreateHandle.ll index 40b3b2c7122722..234d4e035bf1d5 100644 --- a/llvm/test/CodeGen/DirectX/CreateHandle.ll +++ b/llvm/test/CodeGen/DirectX/CreateHandle.ll @@ -3,7 +3,7 @@ ; CHECK-PRETTY: Type Format Dim ID HLSL Bind Count ; CHECK-PRETTY: ---------- ------- ----------- ------- -------------- --------- -; CHECK-PRETTY: SRV f32 buf T0 t0 unbounded +; CHECK-PRETTY: SRV f32 buf T0 t7 unbounded ; CHECK-PRETTY: SRV byte r/o T1 t8,space1 1 ; CHECK-PRETTY: SRV struct r/o T2 t2,space4 1 ; CHECK-PRETTY: SRV u32 buf T3 t3,space5 24 @@ -18,44 +18,45 @@ define void @test_buffers() { ; RWBuffer<float4> Buf : register(u5, space3) %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0( - i32 3, i32 5, i32 1, i32 4, i1 false) - ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 4, i1 false) + i32 3, i32 5, i32 1, i32 0, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 5, i1 false) ; CHECK-NOT: @llvm.dx.cast.handle ; RWBuffer<int> Buf : register(u7, space2) %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t( - i32 2, i32 7, i32 1, i32 6, i1 false) - ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 6, i1 false) + i32 2, i32 7, i32 1, i32 0, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 7, i1 false) ; Buffer<uint4> Buf[24] : register(t3, space5) ; Buffer<uint4> typed2 = Buf[4] ; Note that the index below is 3 + 4 = 7 %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t( - i32 5, i32 3, i32 24, i32 7, i1 false) + i32 5, i32 3, i32 24, i32 4, i1 false) ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 3, i32 7, i1 false) ; struct S { float4 a; uint4 b; }; ; StructuredBuffer<S> Buf : register(t2, space4) %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t( - i32 4, i32 2, i32 1, i32 10, i1 true) - ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 10, i1 true) + i32 4, i32 2, i32 1, i32 0, i1 true) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 2, i1 true) ; ByteAddressBuffer Buf : register(t8, space1) %byteaddr0 = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( - i32 1, i32 8, i32 1, i32 12, i1 false) - ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 12, i1 false) + i32 1, i32 8, i32 1, i32 0, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 8, i1 false) - ; Buffer<float4> Buf[] : register(t0) + ; Buffer<float4> Buf[] : register(t7) ; Buffer<float4> typed3 = Buf[ix] %typed3_ix = call i32 @some_val() %typed3 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_0_0_0t( - i32 0, i32 0, i32 -1, i32 %typed3_ix, i1 false) - ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 %typed3_ix, i1 false) + i32 0, i32 7, i32 -1, i32 %typed3_ix, i1 false) + ; CHECK: %[[IX:.*]] = add i32 %typed3_ix, 7 + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 %[[IX]], i1 false) ret void } diff --git a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll index bce324509184be..aa143dfa8211d0 100644 --- a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll +++ b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll @@ -3,7 +3,7 @@ ; CHECK-PRETTY: Type Format Dim ID HLSL Bind Count ; CHECK-PRETTY: ---------- ------- ----------- ------- -------------- --------- -; CHECK-PRETTY: SRV f32 buf T0 t0 unbounded +; CHECK-PRETTY: SRV f32 buf T0 t7 unbounded ; CHECK-PRETTY: SRV byte r/o T1 t8,space1 1 ; CHECK-PRETTY: SRV struct r/o T2 t2,space4 1 ; CHECK-PRETTY: SRV u32 buf T3 t3,space5 24 @@ -18,15 +18,15 @@ define void @test_bindings() { ; RWBuffer<float4> Buf : register(u5, space3) %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0( - i32 3, i32 5, i32 1, i32 4, i1 false) - ; CHECK: [[BUF0:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 5, i32 5, i32 3, i8 1 }, i32 4, i1 false) + i32 3, i32 5, i32 1, i32 0, i1 false) + ; CHECK: [[BUF0:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 5, i32 5, i32 3, i8 1 }, i32 5, i1 false) ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF0]], %dx.types.ResourceProperties { i32 4106, i32 1033 }) ; RWBuffer<int> Buf : register(u7, space2) %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_0t( - i32 2, i32 7, i32 1, i32 6, i1 false) - ; CHECK: [[BUF1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 7, i32 7, i32 2, i8 1 }, i32 6, i1 false) + i32 2, i32 7, i32 1, i32 0, i1 false) + ; CHECK: [[BUF1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 7, i32 7, i32 2, i8 1 }, i32 7, i1 false) ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF1]], %dx.types.ResourceProperties { i32 4106, i32 260 }) ; Buffer<uint4> Buf[24] : register(t3, space5) @@ -34,7 +34,7 @@ define void @test_bindings() { ; Note that the index below is 3 + 4 = 7 %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t( - i32 5, i32 3, i32 24, i32 7, i1 false) + i32 5, i32 3, i32 24, i32 4, i1 false) ; CHECK: [[BUF2:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 3, i32 26, i32 5, i8 0 }, i32 7, i1 false) ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF2]], %dx.types.ResourceProperties { i32 10, i32 1029 }) @@ -42,24 +42,25 @@ define void @test_bindings() { ; StructuredBuffer<S> Buf : register(t2, space4) %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t( - i32 4, i32 2, i32 1, i32 10, i1 true) - ; CHECK: [[BUF3:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 2, i32 2, i32 4, i8 0 }, i32 10, i1 true) + i32 4, i32 2, i32 1, i32 0, i1 true) + ; CHECK: [[BUF3:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 2, i32 2, i32 4, i8 0 }, i32 2, i1 true) ; CHECK: = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF3]], %dx.types.ResourceProperties { i32 1036, i32 32 }) ; ByteAddressBuffer Buf : register(t8, space1) %byteaddr0 = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( - i32 1, i32 8, i32 1, i32 12, i1 false) - ; CHECK: [[BUF4:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 8, i32 8, i32 1, i8 0 }, i32 12, i1 false) + i32 1, i32 8, i32 1, i32 0, i1 false) + ; CHECK: [[BUF4:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 8, i32 8, i32 1, i8 0 }, i32 8, i1 false) ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF4]], %dx.types.ResourceProperties { i32 11, i32 0 }) - ; Buffer<float4> Buf[] : register(t0) + ; Buffer<float4> Buf[] : register(t7) ; Buffer<float4> typed3 = Buf[ix] %typed3_ix = call i32 @some_val() %typed3 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_0_0_0t( - i32 0, i32 0, i32 -1, i32 %typed3_ix, i1 false) - ; CHECK: [[BUF5:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 -1, i32 0, i8 0 }, i32 %typed3_ix, i1 false) + i32 0, i32 7, i32 -1, i32 %typed3_ix, i1 false) + ; CHECK: %[[IX:.*]] = add i32 %typed3_ix, 7 + ; CHECK: [[BUF5:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 7, i32 -1, i32 0, i8 0 }, i32 %[[IX]], i1 false) ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF5]], %dx.types.ResourceProperties { i32 10, i32 1033 }) ret void _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits