Skip to content

[SER] Validate 'reordercoherent' resource property #7429

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

Merged
merged 7 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3175,6 +3175,7 @@ INSTR.OPCONSTRANGE Constant values must be in
INSTR.OPERANDRANGE DXIL intrinsic operand must be within defined range
INSTR.PARAMMULTIPLE Parameter must be a valid multiple
INSTR.PTRBITCAST Pointer type bitcast must be have same size.
INSTR.REORDERCOHERENTREQUIRESSM69 reordercoherent requires SM 6.9 or later.
INSTR.RESOURCECLASSFORLOAD load can only run on UAV/SRV resource.
INSTR.RESOURCECLASSFORSAMPLERGATHER sample, lod and gather should be on srv resource.
INSTR.RESOURCECLASSFORUAVSTORE store should be on uav resource.
Expand Down Expand Up @@ -3216,14 +3217,14 @@ META.BARYCENTRICSTWOPERSPECTIVES There can only be up to tw
META.BRANCHFLATTEN Can't use branch and flatten attributes together.
META.CLIPCULLMAXCOMPONENTS Combined elements of SV_ClipDistance and SV_CullDistance must fit in 8 components
META.CLIPCULLMAXROWS Combined elements of SV_ClipDistance and SV_CullDistance must fit in two rows.
META.COHERENCENOTONAPPENDCONSUME %0coherent cannot be used with append/consume buffers: '%1'.
META.COMPUTEWITHNODE Compute entry must not have node metadata
META.CONTROLFLOWHINTNOTONCONTROLFLOW Control flow hint only works on control flow inst.
META.DENSERESIDS Resource identifiers must be zero-based and dense.
META.DUPLICATESYSVALUE System value may only appear once in signature
META.ENTRYFUNCTION entrypoint not found.
META.FLAGSUSAGE Flags must match usage.
META.FORCECASEONSWITCH Attribute forcecase only works for switch.
META.GLCNOTONAPPENDCONSUME globallycoherent cannot be used with append/consume buffers: '%0'.
META.INTEGERINTERPMODE Interpolation mode on integer must be Constant
META.INTERPMODEINONEROW Interpolation mode must be identical for all elements packed into the same row.
META.INTERPMODEVALID Interpolation mode must be valid
Expand Down
24 changes: 17 additions & 7 deletions lib/DxilValidation/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ ValidateSignatureAccess(Instruction *I, DxilSignature &Sig, Value *SigId,

static DxilResourceProperties GetResourceFromHandle(Value *Handle,
ValidationContext &ValCtx) {
if (!isa<CallInst>(Handle)) {
CallInst *HandleCall = dyn_cast<CallInst>(Handle);
if (!HandleCall) {
if (Instruction *I = dyn_cast<Instruction>(Handle))
ValCtx.EmitInstrError(I, ValidationRule::InstrHandleNotFromCreateHandle);
else
Expand All @@ -175,10 +176,13 @@ static DxilResourceProperties GetResourceFromHandle(Value *Handle,
}

DxilResourceProperties RP = ValCtx.GetResourceFromVal(Handle);
if (RP.getResourceClass() == DXIL::ResourceClass::Invalid) {
if (RP.getResourceClass() == DXIL::ResourceClass::Invalid)
ValCtx.EmitInstrError(cast<CallInst>(Handle),
ValidationRule::InstrHandleNotFromCreateHandle);
}
if (RP.Basic.IsReorderCoherent &&
!ValCtx.DxilMod.GetShaderModel()->IsSM69Plus())
ValCtx.EmitInstrError(HandleCall,
ValidationRule::InstrReorderCoherentRequiresSM69);

return RP;
}
Expand Down Expand Up @@ -4182,6 +4186,9 @@ static void ValidateResourceOverlap(

static void ValidateResource(hlsl::DxilResource &Res,
ValidationContext &ValCtx) {
if (Res.IsReorderCoherent() && !ValCtx.DxilMod.GetShaderModel()->IsSM69Plus())
ValCtx.EmitResourceError(&Res,
ValidationRule::InstrReorderCoherentRequiresSM69);
switch (Res.GetKind()) {
case DXIL::ResourceKind::RawBuffer:
case DXIL::ResourceKind::TypedBuffer:
Expand Down Expand Up @@ -4413,10 +4420,13 @@ static void ValidateResources(ValidationContext &ValCtx) {
ValCtx.EmitResourceError(Uav.get(),
ValidationRule::SmCounterOnlyOnStructBuf);
}
if (Uav->HasCounter() && Uav->IsGloballyCoherent())
ValCtx.EmitResourceFormatError(Uav.get(),
ValidationRule::MetaGlcNotOnAppendConsume,
{ValCtx.GetResourceName(Uav.get())});
const bool UavIsCoherent =
Uav->IsGloballyCoherent() || Uav->IsReorderCoherent();
if (Uav->HasCounter() && UavIsCoherent) {
StringRef Prefix = Uav->IsGloballyCoherent() ? "globally" : "reorder";
ValCtx.EmitResourceFormatError(
Uav.get(), ValidationRule::MetaCoherenceNotOnAppendConsume, {Prefix});
}

ValidateResource(*Uav, ValCtx);
ValidateResourceOverlap(*Uav, UavAllocator, ValCtx);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
; REQUIRES: dxil-1-9
; RUN: not %dxv %s 2>&1 | FileCheck %s

; COM: Original HLSL source:
; COM: reordercoherent RWStructuredBuffer<float> buffer;
; COM:
; COM:
; COM: [Shader("raygeneration")]
; COM: void
; COM: main()
; COM: {
; COM: buffer.IncrementCounter();
; COM: buffer.DecrementCounter();
; COM: }

; CHECK: error: reordercoherent cannot be used on buffer with counter 'buffer'
; CHECK-NEXT: Validation failed.

; shader hash: 638950814a9023bf537d61dbb330a4c8
;
; Buffer Definitions:
;
; Resource bind info for buffer
; {
;
; float $Element; ; Offset: 0 Size: 4
;
; }
;
;
; Resource Bindings:
;
; Name Type Format Dim ID HLSL Bind Count
; ------------------------------ ---------- ------- ----------- ------- -------------- ------
; buffer UAV struct r/w+cnt U0u4294967295,space4294967295 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.ResourceProperties = type { i32, i32 }
%"class.RWStructuredBuffer<float>" = type { float }

@"\01?buffer@@3V?$RWStructuredBuffer@M@@A" = external constant %dx.types.Handle, align 4

; Function Attrs: nounwind
define void @"\01?main@@YAXXZ"() #0 {
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?buffer@@3V?$RWStructuredBuffer@M@@A", align 4
%2 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 102412, i32 4 }) ; AnnotateHandle(res,props) resource: reordercoherent RWStructuredBuffer<stride=4, counter>
%4 = call i32 @dx.op.bufferUpdateCounter(i32 70, %dx.types.Handle %3, i8 1) ; BufferUpdateCounter(uav,inc)
%5 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
%6 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %5, %dx.types.ResourceProperties { i32 102412, i32 4 }) ; AnnotateHandle(res,props) resource: reordercoherent RWStructuredBuffer<stride=4, counter>
%7 = call i32 @dx.op.bufferUpdateCounter(i32 70, %dx.types.Handle %6, i8 -1) ; BufferUpdateCounter(uav,inc)
ret void
}

; Function Attrs: nounwind
declare i32 @dx.op.bufferUpdateCounter(i32, %dx.types.Handle, i8) #0

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

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

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

!dx.version = !{!0}
!dx.valver = !{!0}
!dx.shaderModel = !{!1}
!dx.resources = !{!2}
!dx.typeAnnotations = !{!6}
!dx.entryPoints = !{!10, !12}

!0 = !{i32 1, i32 9}
!1 = !{!"lib", i32 6, i32 9}
!2 = !{null, !3, null, null}
!3 = !{!4}
!4 = !{i32 0, %"class.RWStructuredBuffer<float>"* bitcast (%dx.types.Handle* @"\01?buffer@@3V?$RWStructuredBuffer@M@@A" to %"class.RWStructuredBuffer<float>"*), !"buffer", i32 -1, i32 -1, i32 1, i32 12, i1 false, i1 true, i1 false, !5}
!5 = !{i32 1, i32 4, i32 4, i1 true}
!6 = !{i32 1, void ()* @"\01?main@@YAXXZ", !7}
!7 = !{!8}
!8 = !{i32 1, !9, !9}
!9 = !{}
!10 = !{null, !"", null, !2, !11}
!11 = !{i32 0, i64 8589934608}
!12 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !13}
!13 = !{i32 8, i32 7, i32 5, !14}
!14 = !{i32 0}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
; REQUIRES: dxil-1-8
; RUN: not %dxv %s 2>&1 | FileCheck %s


; CHECK: error: reordercoherent requires SM 6.9 or later. 'buf'
; CHECK-NEXT: Function: ?main@@YAXXZ: error: reordercoherent requires SM 6.9 or later.
; CHECK-NEXT: note: at '%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 69643, i32 0 })' in block '#0' of function '?main@@YAXXZ'.
; CHECK-NEXT: Function: ?main@@YAXXZ: error: reordercoherent requires SM 6.9 or later.
; CHECK-NEXT: note: at '%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 69643, i32 0 })' in block '#0' of function '?main@@YAXXZ'.
; CHECK-NEXT: Validation failed.
; COM: Original HLSL source:
; COM: reordercoherent RWByteAddressBuffer buf;
; COM:
; COM: [Shader("raygeneration")]
; COM: void main()
; COM: {
; COM: buf.Store(0, 11.f);
; COM: }

; shader hash: f7be6354830d1423764991adcfc26b0b
;
; Buffer Definitions:
;
;
; Resource Bindings:
;
; Name Type Format Dim ID HLSL Bind Count
; ------------------------------ ---------- ------- ----------- ------- -------------- ------
; buf UAV byte r/w U0u4294967295,space4294967295 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.ResourceProperties = type { i32, i32 }
%struct.RWByteAddressBuffer = type { i32 }

@"\01?buf@@3URWByteAddressBuffer@@A" = external constant %dx.types.Handle, align 4

; Function Attrs: nounwind
define void @"\01?main@@YAXXZ"() #0 {
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?buf@@3URWByteAddressBuffer@@A", align 4
%2 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 69643, i32 0 }) ; AnnotateHandle(res,props) resource: reordercoherent RWByteAddressBuffer
call void @dx.op.rawBufferStore.f32(i32 140, %dx.types.Handle %3, i32 0, i32 undef, float 1.100000e+01, float undef, float undef, float undef, i8 1, i32 4) ; RawBufferStore(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment)
ret void
}

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

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

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

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

!dx.version = !{!0}
!dx.valver = !{!0}
!dx.shaderModel = !{!1}
!dx.resources = !{!2}
!dx.typeAnnotations = !{!3}
!dx.entryPoints = !{!4, !5}

!0 = !{i32 1, i32 8}
!1 = !{!"lib", i32 6, i32 8}
!2 = !{null, !6, null, null}
!3 = !{i32 1, void ()* @"\01?main@@YAXXZ", !7}
!4 = !{null, !"", null, !2, !8}
!5 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !9}
!6 = !{!10}
!7 = !{!11}
!8 = !{i32 0, i64 8589934608}
!9 = !{i32 8, i32 7, i32 5, !12}
!10 = !{i32 0, %struct.RWByteAddressBuffer* bitcast (%dx.types.Handle* @"\01?buf@@3URWByteAddressBuffer@@A" to %struct.RWByteAddressBuffer*), !"buf", i32 -1, i32 -1, i32 1, i32 11, i1 false, i1 false, i1 false, !13}
!11 = !{i32 1, !14, !14}
!12 = !{i32 0}
!13 = !{i32 4, i1 true}
!14 = !{}
Loading
Loading