-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[DirectX] NonUniformResourceIndex lowering #159608
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 all commits
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 |
---|---|---|
@@ -0,0 +1,70 @@ | ||
; RUN: opt -S -passes=dxil-op-lower %s | FileCheck %s | ||
|
||
target triple = "dxil-pc-shadermodel6.0-compute" | ||
|
||
@A.str = internal unnamed_addr constant [2 x i8] c"A\00", align 1 | ||
@B.str = internal unnamed_addr constant [2 x i8] c"A\00", align 1 | ||
|
||
declare i32 @some_val(); | ||
|
||
define void @test_buffers_with_nuri() { | ||
|
||
%val = call i32 @some_val() | ||
%foo = alloca i32, align 4 | ||
|
||
; RWBuffer<float> A[10]; | ||
; | ||
; A[NonUniformResourceIndex(val)]; | ||
|
||
%nuri1 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
%res1 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %nuri1, ptr @A.str) | ||
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %val, i1 true) #[[ATTR:.*]] | ||
; CHECK-NOT: @llvm.dx.cast.handle | ||
; CHECK-NOT: @llvm.dx.resource.nonuniformindex | ||
|
||
; A[NonUniformResourceIndex(val + 1) % 10]; | ||
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. This is interesting. I feel like DXC doesn't really support this kind of case well. |
||
%add1 = add i32 %val, 1 | ||
%nuri2 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %add1) | ||
%rem1 = urem i32 %nuri2, 10 | ||
%res2 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %rem1, ptr @A.str) | ||
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %rem1, i1 true) #[[ATTR]] | ||
|
||
; A[10 + 3 * NonUniformResourceIndex(GI)]; | ||
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. What about something like:
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. This works as long as the 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. It's difficult to say where to draw the line here. DXC requires it to be on the index, but it's possible that's applied after SSA (so store & load chain may be collapsed). FXC was a bit more flexible, leading to code which would work for FXC, but not for DXC. However, there wasn't a hard rule you could follow to guarantee it would work still. If we have the rule that it must be on the index used directly in the operation, which is what we've said for DXC, it's easiest to make sure that works. Some HLSL authors have complained a bit about this strictness though. If we could find another objective rule we could apply and guarantee works which gives more flexibility, we could use that, but we might never implement that for DXC. 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 suspect this handling is already more robust than DXC, so we can probably just call it good. 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. If we can, we should consider emitting some error, or at least a warning, if a NURI call doesn't lead to marking a resource indexing create handle as NURI. 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. Since the call can be safely ignored when it is not on a resource index and there are no side effects, I don't think adding a special check just to emit a warning is useful. |
||
%mul1 = mul i32 %nuri1, 3 | ||
%add2 = add i32 %mul1, 10 | ||
%res3 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %add2, ptr @A.str) | ||
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %add2, i1 true) #[[ATTR]] | ||
|
||
; NonUniformResourceIndex value going through store & load - the flag is not going to get picked up: | ||
%a = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
store i32 %a, ptr %foo | ||
%b = load i32, ptr %foo | ||
%res4 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %b, ptr @A.str) | ||
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %b, i1 false) #[[ATTR]] | ||
|
||
; NonUniformResourceIndex index value on a single resouce (not an array) - the flag is not going to get picked up: | ||
; | ||
; RWBuffer<float> B : register(u20); | ||
; B[NonUniformResourceIndex(val)]; | ||
%nuri3 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
%res5 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 20, i32 0, i32 1, i32 %nuri1, ptr @B.str) | ||
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 %val, i1 false) #[[ATTR]] | ||
|
||
; NonUniformResourceIndex on unrelated value - the call is removed: | ||
; foo = NonUniformResourceIndex(val); | ||
%nuri4 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
store i32 %nuri4, ptr %foo | ||
; CHECK: store i32 %val, ptr %foo | ||
; CHECK-NOT: @llvm.dx.resource.nonuniformindex | ||
|
||
ret void | ||
} | ||
|
||
; CHECK: attributes #[[ATTR]] = {{{.*}} memory(read) {{.*}}} | ||
|
||
attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
; RUN: opt -S -passes=dxil-op-lower %s | FileCheck %s | ||
|
||
target triple = "dxil-pc-shadermodel6.6-compute" | ||
|
||
@A.str = internal unnamed_addr constant [2 x i8] c"A\00", align 1 | ||
@B.str = internal unnamed_addr constant [2 x i8] c"A\00", align 1 | ||
|
||
declare i32 @some_val(); | ||
|
||
define void @test_buffers_with_nuri() { | ||
|
||
%val = call i32 @some_val() | ||
%foo = alloca i32, align 4 | ||
|
||
; RWBuffer<float> A[10]; | ||
; | ||
; A[NonUniformResourceIndex(val)]; | ||
|
||
%nuri1 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
%res1 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %nuri1, ptr @A.str) | ||
; CHECK: %[[RES1:.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 9, i32 0, i8 1 }, i32 %val, i1 true) #[[ATTR:.*]] | ||
; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %[[RES1]], %dx.types.ResourceProperties { i32 4106, i32 265 }) #[[ATTR]] | ||
; CHECK-NOT: @llvm.dx.cast.handle | ||
; CHECK-NOT: @llvm.dx.resource.nonuniformindex | ||
|
||
; A[NonUniformResourceIndex(val + 1) % 10]; | ||
%add1 = add i32 %val, 1 | ||
%nuri2 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %add1) | ||
%rem1 = urem i32 %nuri2, 10 | ||
%res2 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %rem1, ptr @A.str) | ||
; CHECK: %[[RES2:.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 9, i32 0, i8 1 }, i32 %rem1, i1 true) #[[ATTR]] | ||
; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %[[RES2]], %dx.types.ResourceProperties { i32 4106, i32 265 }) #[[ATTR]] | ||
|
||
; A[10 + 3 * NonUniformResourceIndex(GI)]; | ||
%mul1 = mul i32 %nuri1, 3 | ||
%add2 = add i32 %mul1, 10 | ||
%res3 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %add2, ptr @A.str) | ||
; CHECK: %[[RES3:.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 9, i32 0, i8 1 }, i32 %add2, i1 true) #[[ATTR]] | ||
; CHECK: %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %[[RES3]], %dx.types.ResourceProperties { i32 4106, i32 265 }) #[[ATTR]] | ||
ret void | ||
|
||
; NonUniformResourceIndex value going through store & load: the flag is not going to get picked up | ||
%a = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
store i32 %a, ptr %foo | ||
%b = load i32, ptr %foo | ||
%res4 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %b, ptr @A.str) | ||
; CHECK: %[[RES4:.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 9, i32 0, i8 1 }, i32 %b, i1 false) #[[ATTR]] | ||
; CHECK: %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %[[RES4]], %dx.types.ResourceProperties { i32 4106, i32 265 }) #[[ATTR]] | ||
|
||
; NonUniformResourceIndex index value on a single resouce (not an array): the flag is not going to get picked up | ||
; RWBuffer<float> B : register(u20); | ||
; | ||
; B[NonUniformResourceIndex(val)]; | ||
|
||
%nuri3 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
%res5 = call target("dx.TypedBuffer", float, 1, 0, 0) | ||
@llvm.dx.resource.handlefrombinding(i32 20, i32 0, i32 1, i32 %nuri1, ptr @B.str) | ||
; CHECK: %[[RES4:.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 0, i32 20, i8 1 }, i32 %val, i1 false) #[[ATTR]] | ||
; CHECK: %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %[[RES4]], %dx.types.ResourceProperties { i32 4106, i32 265 }) #[[ATTR]] | ||
|
||
; NonUniformResourceIndex on unrelated value - the call is removed: | ||
; foo = NonUniformResourceIndex(val); | ||
%nuri4 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val) | ||
store i32 %nuri4, ptr %foo | ||
; CHECK: store i32 %val, ptr %foo | ||
; CHECK-NOT: @llvm.dx.resource.nonuniformindex | ||
|
||
ret void | ||
} | ||
|
||
; CHECK: attributes #[[ATTR]] = {{{.*}} memory(none) {{.*}}} | ||
|
||
attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) } |
Uh oh!
There was an error while loading. Please reload this page.