-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[DirectX] Validate registers are bound to root signature #146785
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
Changes from 118 commits
0e8828c
2edd215
242545e
3f8dec4
3b1ce3b
f5720af
ea54904
a49aa19
d90676f
a04eb9f
5994b8f
e8b14bf
8f40e83
28350b2
4fd2e0b
e25ee87
881dd36
8779ee9
c16f15b
c7d5be7
cc5afae
571a0ef
974d4bc
e0bc862
b5a0b32
00a74af
5ccb842
5423aba
a7637a7
da42c0c
edb015d
9f3888e
578a03b
b4a0e16
ef14638
662c3a8
260633c
d42f156
9ee3a4b
6db6224
04658b8
adf3feb
c95ce68
af6aa53
29eb893
ed4c553
28fb609
fc338b5
f5b5b3e
03d571a
ef51048
21675e6
403972d
0f0435d
e841a98
ae6d67a
41f32bd
47662f0
6da5fb0
6f3d019
971ad57
db73d71
3b04c2d
1ddffc3
db0008e
0c72dcf
b4e5fb4
4a655a5
cc94561
98f48d2
eb334b8
06c0da4
d58606f
74980c8
d376abf
4abb40d
bb44eef
1cf2d1e
373d871
d2750d7
6db8d93
e3a65b6
e902add
9a6d64c
15b7592
11b9fb2
0442b99
82bdf82
9f18475
964d165
e5ca2d6
84f449b
4d0fbbe
1ef79ad
485e9b6
1945403
acd966a
8d2a9d1
939b6aa
4f7856f
2c8b999
f866fa9
741960e
b275160
a6a0ab7
df3f096
b9eee70
3c2119f
9541ba3
1836e43
6726f1d
6254024
c87c1c0
239bf83
ad3d595
263ced2
c8ce514
e2ddf4d
4f90c8f
7a7c0bf
5443a62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
#ifndef LLVM_FRONTEND_HLSL_HLSLBINDING_H | ||
#define LLVM_FRONTEND_HLSL_HLSLBINDING_H | ||
|
||
#include "llvm/ADT/STLExtras.h" | ||
#include "llvm/ADT/STLFunctionalExtras.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/Support/Compiler.h" | ||
|
@@ -99,36 +100,55 @@ class BindingInfo { | |
friend class BindingInfoBuilder; | ||
}; | ||
|
||
/// Builder class for creating a /c BindingInfo. | ||
class BindingInfoBuilder { | ||
public: | ||
struct Binding { | ||
dxil::ResourceClass RC; | ||
uint32_t Space; | ||
uint32_t LowerBound; | ||
uint32_t UpperBound; | ||
const void *Cookie; | ||
struct Binding { | ||
bogner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
dxil::ResourceClass RC; | ||
uint32_t Space; | ||
uint32_t LowerBound; | ||
uint32_t UpperBound; | ||
const void *Cookie; | ||
|
||
Binding(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, | ||
uint32_t UpperBound, const void *Cookie) | ||
: RC(RC), Space(Space), LowerBound(LowerBound), UpperBound(UpperBound), | ||
Cookie(Cookie) {} | ||
Binding(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, | ||
uint32_t UpperBound, const void *Cookie) | ||
: RC(RC), Space(Space), LowerBound(LowerBound), UpperBound(UpperBound), | ||
Cookie(Cookie) {} | ||
|
||
bool isUnbounded() const { return UpperBound == ~0U; } | ||
bool isUnbounded() const { return UpperBound == ~0U; } | ||
|
||
bool operator==(const Binding &RHS) const { | ||
return std::tie(RC, Space, LowerBound, UpperBound, Cookie) == | ||
std::tie(RHS.RC, RHS.Space, RHS.LowerBound, RHS.UpperBound, | ||
RHS.Cookie); | ||
} | ||
bool operator!=(const Binding &RHS) const { return !(*this == RHS); } | ||
bool operator==(const Binding &RHS) const { | ||
return std::tie(RC, Space, LowerBound, UpperBound, Cookie) == | ||
std::tie(RHS.RC, RHS.Space, RHS.LowerBound, RHS.UpperBound, | ||
RHS.Cookie); | ||
} | ||
bool operator!=(const Binding &RHS) const { return !(*this == RHS); } | ||
|
||
bool operator<(const Binding &RHS) const { | ||
return std::tie(RC, Space, LowerBound) < | ||
std::tie(RHS.RC, RHS.Space, RHS.LowerBound); | ||
} | ||
}; | ||
bool operator<(const Binding &RHS) const { | ||
return std::tie(RC, Space, LowerBound) < | ||
std::tie(RHS.RC, RHS.Space, RHS.LowerBound); | ||
} | ||
}; | ||
|
||
class BoundRegs { | ||
bogner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
SmallVector<Binding> Bindings; | ||
|
||
public: | ||
BoundRegs(SmallVector<Binding> &&Bindings) : Bindings(std::move(Bindings)) {} | ||
|
||
bool isBound(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, | ||
uint32_t UpperBound) const { | ||
// UpperBound and Cookie are given dummy values, since they aren't | ||
// interesting for operator< | ||
const Binding *It = | ||
llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr}); | ||
bogner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (It == Bindings.begin()) | ||
return false; | ||
--It; | ||
return It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound && | ||
It->UpperBound >= UpperBound; | ||
} | ||
}; | ||
|
||
/// Builder class for creating a /c BindingInfo. | ||
class BindingInfoBuilder { | ||
private: | ||
SmallVector<Binding> Bindings; | ||
|
||
|
@@ -152,6 +172,12 @@ class BindingInfoBuilder { | |
[&HasOverlap](auto, auto) { HasOverlap = true; }); | ||
} | ||
|
||
LLVM_ABI BoundRegs getBoundRegs() { | ||
|
||
assert(std::is_sorted(Bindings.begin(), Bindings.end()) && | ||
"Bindings must be sorted"); | ||
|
||
return BoundRegs(std::move(Bindings)); | ||
} | ||
|
||
/// For use in the \c ReportOverlap callback of \c calculateBindingInfo - | ||
/// finds a binding that the \c ReportedBinding overlaps with. | ||
LLVM_ABI const Binding &findOverlapping(const Binding &ReportedBinding) const; | ||
|
joaosaffran marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s | ||
; This is a valid code, it checks the limits of a binding space | ||
; CHECK-NOT: error: | ||
|
||
%__cblayout_CB = type <{ float }> | ||
|
||
@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 | ||
|
||
define void @CSMain() "hlsl.shader"="compute" { | ||
entry: | ||
%CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 5, i32 0, i1 false, ptr nonnull @CB.str) | ||
ret void | ||
} | ||
|
||
!dx.rootsignatures = !{!0} | ||
|
||
!0 = !{ptr @CSMain, !1, i32 2} | ||
!1 = !{!2} | ||
!2 = !{!"DescriptorTable", i32 0, !3} | ||
!3 = !{!"CBV", i32 5, i32 0, i32 0, i32 0, i32 4} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s | ||
; This is a valid code, it checks the limits of a binding space | ||
|
||
; CHECK-NOT: error: | ||
|
||
%__cblayout_CB = type <{ float }> | ||
|
||
@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 | ||
|
||
define void @CSMain() "hlsl.shader"="compute" { | ||
entry: | ||
%CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 4294967294, i32 1, i32 0, i1 false, ptr nonnull @CB.str) | ||
%CB1 = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @CB.str) | ||
ret void | ||
} | ||
|
||
!dx.rootsignatures = !{!0} | ||
|
||
!0 = !{ptr @CSMain, !1, i32 2} | ||
!1 = !{!2, !3} | ||
!2 = !{!"RootCBV", i32 0, i32 4294967294, i32 0, i32 4} | ||
!3 = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should also add a couple tests for when it doesn't fail validation. For instance the cases:
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s | ||
; CHECK: error: CBV register 2 in space 666 does not have a binding in the Root Signature | ||
|
||
%__cblayout_CB = type <{ float }> | ||
|
||
@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 | ||
|
||
define void @CSMain() "hlsl.shader"="compute" { | ||
entry: | ||
%CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 666, i32 2, i32 1, i32 0, i1 false, ptr nonnull @CB.str) | ||
ret void | ||
} | ||
|
||
!dx.rootsignatures = !{!0} | ||
|
||
!0 = !{ptr @CSMain, !1, i32 2} | ||
!1 = !{!2} | ||
!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s | ||
; CHECK: CBV register 3 in space 0 does not have a binding in the Root Signature | ||
%__cblayout_CB = type <{ float }> | ||
|
||
@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 | ||
|
||
define void @CSMain() "hlsl.shader"="compute" { | ||
entry: | ||
%CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 3, i32 6, i32 0, i1 false, ptr nonnull @CB.str) | ||
ret void | ||
} | ||
|
||
!dx.rootsignatures = !{!0} | ||
|
||
!0 = !{ptr @CSMain, !1, i32 2} | ||
!1 = !{!2} | ||
!2 = !{!"DescriptorTable", i32 0, !3, !4} | ||
!3 = !{!"CBV", i32 5, i32 2, i32 0, i32 0, i32 4} | ||
!4 = !{!"CBV", i32 4, i32 7, i32 0, i32 10, i32 4} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s | ||
; CHECK: error: Sampler register 3 in space 2 does not have a binding in the Root Signature | ||
|
||
@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 | ||
|
||
|
||
define void @CSMain() "hlsl.shader"="compute" { | ||
entry: | ||
%Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) | ||
ret void | ||
} | ||
|
||
!dx.rootsignatures = !{!0} | ||
|
||
!0 = !{ptr @CSMain, !1, i32 2} | ||
!1 = !{!2} | ||
!2 = !{!"DescriptorTable", i32 0, !3} | ||
!3 = !{!"Sampler", i32 1, i32 42, i32 0, i32 -1, i32 0} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s | ||
; CHECK: error: SRV register 0 in space 0 does not have a binding in the Root Signature | ||
|
||
@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 | ||
|
||
define void @CSMain() "hlsl.shader"="compute" { | ||
entry: | ||
; StructuredBuffer<int> In : register(t0, space0); | ||
%SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @SB.str) | ||
ret void | ||
} | ||
|
||
!dx.rootsignatures = !{!0} | ||
|
||
!0 = !{ptr @CSMain, !1, i32 2} | ||
!1 = !{!2, !3, !5, !7} | ||
!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} | ||
!3 = !{!"DescriptorTable", i32 1, !4} | ||
!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} | ||
!5 = !{!"DescriptorTable", i32 0, !6} | ||
!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} | ||
!7 = !{!"DescriptorTable", i32 0, !8} | ||
!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2} |
Uh oh!
There was an error while loading. Please reload this page.