llvm / llvm/offload-test-suite
[WARP][Validation Layer][DXC] Hang when DeviceMemoryBarrierWithGroupSync() is followed by a live UAV read
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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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