llvm / llvm/offload-test-suite

[WARP][Validation Layer][DXC] Hang when DeviceMemoryBarrierWithGroupSync() is followed by a live UAV read

Open
#1,418 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18
Forks
39
Avg merge
2d 18h
Merged PRs (30d)
40

Description

When executing a shader with WARP, with validation layer enabled (GBV), and compiling the shader with DXC, there is a runtime hang.
This is the minimal offload test repro in HLSL:
```hlsl
RWStructuredBuffer Out : register(u0);
RWStructuredBuffer OutMono : register(u1);
RWByteAddressBuffer BABuf : register(u2);
RWStructuredBuffer OutMono2 : register(u3);

[numthreads(256, 1, 1)]
void main(uint3 GTID : SV_GroupThreadID) {
if (GTID.x == 0) {
Out[0] = 0u;
BABuf.Store(0, 0u);
}
DeviceMemoryBarrierWithGroupSync();

uint Acc = 0u;
for (uint I = 0; I < 2; ++I) {
InterlockedAdd(Out[0], 1u);
DeviceMemoryBarrierWithGroupSync();
Acc += Out[0];
}
OutMono[GTID.x] = Acc;
OutMono2[GTID.x] = 1u;
}
```

Targeting SM 6.5 also produces a hang.
Here is a table of various results:
| Compiler | Target | Offloader flags | Result |
| --- | --- | --- | --- |
| DXC | `cs_6_5` | `-warp -debug-layer -validation-layer` | **hang** |
| DXC | `cs_6_6` | `-warp -debug-layer -validation-layer` | **hang** |
| DXC | `cs_6_5` | `-warp` | completes |
| clang-dxc | `cs_6_5` | `-warp -debug-layer -validation-layer` | completes |
| clang-dxc | `cs_6_6` | `-warp -debug-layer -validation-layer` | completes |
| clang-dxc | `cs_6_5` | `-warp` | completes |

However, removing the validation layer option for runtime execution resolves the hang issue for both SM targets.

DXIL for SM 6.6:
```
;
; Input signature:
;
; Name Index Mask Register SysValue Format Used
; -------------------- ----- ------ -------- -------- ------- ------
; no parameters
;
; Output signature:
;
; Name Index Mask Register SysValue Format Used
; -------------------- ----- ------ -------- -------- ------- ------
; no parameters
; shader hash: 7dc7c169d0b5d2d8a75f41fcc3c286f2
;
; Pipeline Runtime Information:
;
;PSVRuntimeInfo:
; Compute Shader
; NumThreads=(256,1,1)
; NumBytesGroupSharedMemory: 0
; MinimumExpectedWaveLaneCount: 0
; MaximumExpectedWaveLaneCount: 4294967295
; UsesViewID: false
; SigInputElements: 0
; SigOutputElements: 0
; SigPatchConstOrPrimElements: 0
; SigInputVectors: 0
; SigOutputVectors[0]: 0
; SigOutputVectors[1]: 0
; SigOutputVectors[2]: 0
; SigOutputVectors[3]: 0
; EntryFunctionName: main
;
;
; Buffer Definitions:
;
; Resource bind info for Out
; {
;
; uint $Element; ; Offset: 0 Size: 4
;
; }
;
; Resource bind info for OutMono
; {
;
; uint $Element; ; Offset: 0 Size: 4
;
; }
;
; Resource bind info for OutMono2
; {
;
; uint $Element; ; Offset: 0 Size: 4
;
; }
;
;
; Resource Bindings:
;
; Name Type Format Dim ID HLSL Bind Count
; ------------------------------ ---------- ------- ----------- ------- -------------- ------
; Out UAV struct r/w U0 u0 1
; OutMono UAV struct r/w U1 u1 1
; BABuf UAV byte r/w U2 u2 1
; OutMono2 UAV struct r/w U3 u3 1
;
target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
target triple = "dxil-ms-dx"

%dx.types.Handle = type { i8* }
%dx.types.ResBind = type { i32, i32, i32, i8 }
%dx.types.ResourceProperties = type { i32, i32 }
%dx.types.ResRet.i32 = type { i32, i32, i32, i32, i32 }
%"class.RWStructuredBuffer" = type { i32 }
%struct.RWByteAddressBuffer = type { i32 }

define void @main() {
%1 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 3, i32 3, i32 0, i8 1 }, i32 3, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex)
%2 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 2, i32 2, i32 0, i8 1 }, i32 2, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex)
%3 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 1, i32 0, i8 1 }, i32 1, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex)
%4 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 0, i32 0, i8 1 }, i32 0, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex)
%5 = call i32 @dx.op.threadIdInGroup.i32(i32 95, i32 0) ; ThreadIdInGroup(component)
%6 = icmp eq i32 %5, 0
br i1 %6, label %7, label %10

; :7 ; preds = %0
%8 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %4, %dx.types.ResourceProperties { i32 4108, i32 4 }) ; AnnotateHandle(res,props) resource: RWStructuredBuffer
call void @dx.op.rawBufferStore.i32(i32 140, %dx.types.Handle %8, i32 0, i32 0, i32 0, i32 undef, i32 undef, i32 undef, i8 1, i32 4) ; RawBufferStore(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment)
%9 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 4107, i32 0 }) ; AnnotateHandle(res,props) resource: RWByteAddressBuffer
call void @dx.op.rawBufferStore.i32(i32 140, %dx.types.Handle %9, i32 0, i32 undef, i32 0, i32 undef, i32 undef, i32 undef, i8 1, i32 4) ; RawBufferStore(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment)
br label %10

; :10 ; preds = %7, %0
call void @dx.op.barrier(i32 80, i32 3) ; Barrier(barrierMode)
br label %14

; :11 ; preds = %14
%12 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 4108, i32 4 }) ; AnnotateHandle(res,props) resource: RWStructuredBuffer
call void @dx.op.rawBufferStore.i32(i32 140, %dx.types.Handle %12, i32 %5, i32 0, i32 %22, i32 undef, i32 undef, i32 undef, i8 1, i32 4) ; RawBufferStore(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment)
%13 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %1, %dx.types.ResourceProperties { i32 4108, i32 4 }) ; AnnotateHandle(res,props) resource: RWStructuredBuffer
call void @dx.op.rawBufferStore.i32(i32 140, %dx.types.Handle %13, i32 %5, i32 0, i32 1, i32 undef, i32 undef, i32 undef, i8 1, i32 4) ; RawBufferStore(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment)
ret void

; :14 ; preds = %14, %10
%15 = phi i32 [ 0, %10 ], [ %22, %14 ]
%16 = phi i32 [ 0, %10 ], [ %23, %14 ]
%17 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %4, %dx.types.ResourceProperties { i32 4108, i32 4 }) ; AnnotateHandle(res,props) resource: RWStructuredBuffer
%18 = call i32 @dx.op.atomicBinOp.i32(i32 78, %dx.types.Handle %17, i32 0, i32 0, i32 0, i32 undef, i32 1) ; AtomicBinOp(handle,atomicOp,offset0,offset1,offset2,newValue)
call void @dx.op.barrier(i32 80, i32 3) ; Barrier(barrierMode)
%19 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %4, %dx.types.ResourceProperties { i32 4108, i32 4 }) ; AnnotateHandle(res,props) resource: RWStructuredBuffer
%20 = call %dx.types.ResRet.i32 @dx.op.rawBufferLoad.i32(i32 139, %dx.types.Handle %19, i32 0, i32 0, i8 1, i32 4) ; RawBufferLoad(srv,index,elementOffset,mask,alignment)
%21 = extractvalue %dx.types.ResRet.i32 %20, 0
%22 = add i32 %21, %15
%23 = add nuw nsw i32 %16, 1
%24 = icmp eq i32 %23, 2
br i1 %24, label %11, label %14
}

; Function Attrs: nounwind readnone
declare i32 @dx.op.threadIdInGroup.i32(i32, i32) #0

; Function Attrs: nounwind
declare void @dx.op.rawBufferStore.i32(i32, %dx.types.Handle, i32, i32, i32, i32, i32, i32, i8, i32) #1

; Function Attrs: nounwind
declare i32 @dx.op.atomicBinOp.i32(i32, %dx.types.Handle, i32, i32, i32, i32, i32) #1

; Function Attrs: nounwind readonly
declare %dx.types.ResRet.i32 @dx.op.rawBufferLoad.i32(i32, %dx.types.Handle, i32, i32, i8, i32) #2

; Function Attrs: noduplicate nounwind
declare void @dx.op.barrier(i32, i32) #3

; Function Attrs: nounwind readnone
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #0

; Function Attrs: nounwind readnone
declare %dx.types.Handle @dx.op.createHandleFromBinding(i32, %dx.types.ResBind, i32, i1) #0

attributes #0 = { nounwind readnone }
attributes #1 = { nounwind }
attributes #2 = { nounwind readonly }
attributes #3 = { noduplicate nounwind }

!llvm.ident = !{!0}
!dx.version = !{!1}
!dx.valver = !{!2}
!dx.shaderModel = !{!3}
!dx.resources = !{!4}
!dx.entryPoints = !{!11}

!0 = !{!"dxc(private) 1.9.0.5364 (update_containertest_headers, 3aaa95da5)"}
!1 = !{i32 1, i32 6}
!2 = !{i32 1, i32 10}
!3 = !{!"cs", i32 6, i32 6}
!4 = !{null, !5, null, null}
!5 = !{!6, !8, !9, !10}
!6 = !{i32 0, %"class.RWStructuredBuffer"* undef, !"", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !7}
!7 = !{i32 1, i32 4}
!8 = !{i32 1, %"class.RWStructuredBuffer"* undef, !"", i32 0, i32 1, i32 1, i32 12, i1 false, i1 false, i1 false, !7}
!9 = !{i32 2, %struct.RWByteAddressBuffer* undef, !"", i32 0, i32 2, i32 1, i32 11, i1 false, i1 false, i1 false, null}
!10 = !{i32 3, %"class.RWStructuredBuffer"* undef, !"", i32 0, i32 3, i32 1, i32 12, i1 false, i1 false, i1 false, !7}
!11 = !{void ()* @main, !"main", null, !4, !12}
!12 = !{i32 0, i64 16, i32 4, !13}
!13 = !{i32 256, i32 1, i32 1}
```

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the minimal HLSL repro with WARP, the validation layer, and DXC for shader models cs_6_5 and cs_6_6. Compare it with clang-dxc and with validation disabled; done means the DXC cases complete without the runtime hang while the reported control cases remain unchanged.

Written by the indexing model from the issue text.

Assessment

Domain
testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.