[Validation] Add validation and tests for invalid system values in incompatible node launch type (#6108)
#5827 first requires validation at the DXIL level. The validation will check for functions that have incompatible node launch types, and intrinsics that represent certain system values. This PR implements this validation and adds some tests that exercise this validation. Fixes #6104
This commit is contained in:
Родитель
79a290e719
Коммит
02afa578c1
|
@ -3134,6 +3134,7 @@ INSTR.SAMPLERMODEFORSAMPLEC sample_c_*/gather_c instructions requi
|
|||
INSTR.SIGNATUREOPERATIONNOTINENTRY Dxil operation for input output signature must be in entryPoints.
|
||||
INSTR.STATUS Resource status should only be used by CheckAccessFullyMapped.
|
||||
INSTR.STRUCTBITCAST Bitcast on struct types is not allowed.
|
||||
INSTR.SVCONFLICTINGLAUNCHMODE Input system values are compatible with node shader launch mode.
|
||||
INSTR.TEXTUREOFFSET offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7.
|
||||
INSTR.TGSMRACECOND Race condition writing to shared memory detected, consider making this write conditional.
|
||||
INSTR.UNDEFINEDVALUEFORUAVSTORE Assignment of undefined values to UAV.
|
||||
|
|
|
@ -2134,6 +2134,19 @@ static void ValidateBarrierFlagArg(ValidationContext &ValCtx, CallInst *CI,
|
|||
}
|
||||
}
|
||||
|
||||
std::string GetLaunchTypeStr(DXIL::NodeLaunchType LT) {
|
||||
switch (LT) {
|
||||
case DXIL::NodeLaunchType::Broadcasting:
|
||||
return "Broadcasting";
|
||||
case DXIL::NodeLaunchType::Coalescing:
|
||||
return "Coalescing";
|
||||
case DXIL::NodeLaunchType::Thread:
|
||||
return "Thread";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateDxilOperationCallInProfile(CallInst *CI,
|
||||
DXIL::OpCode opcode,
|
||||
const ShaderModel *pSM,
|
||||
|
@ -2141,10 +2154,15 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
|
|||
DXIL::ShaderKind shaderKind =
|
||||
pSM ? pSM->GetKind() : DXIL::ShaderKind::Invalid;
|
||||
llvm::Function *F = CI->getParent()->getParent();
|
||||
DXIL::NodeLaunchType nodeLaunchType = DXIL::NodeLaunchType::Invalid;
|
||||
if (DXIL::ShaderKind::Library == shaderKind) {
|
||||
if (ValCtx.DxilMod.HasDxilFunctionProps(F))
|
||||
if (ValCtx.DxilMod.HasDxilFunctionProps(F)) {
|
||||
DxilEntryProps &entryProps = ValCtx.DxilMod.GetDxilEntryProps(F);
|
||||
shaderKind = ValCtx.DxilMod.GetDxilFunctionProps(F).shaderKind;
|
||||
else if (ValCtx.DxilMod.IsPatchConstantShader(F))
|
||||
if (shaderKind == DXIL::ShaderKind::Node)
|
||||
nodeLaunchType = entryProps.props.Node.LaunchType;
|
||||
|
||||
} else if (ValCtx.DxilMod.IsPatchConstantShader(F))
|
||||
shaderKind = DXIL::ShaderKind::Hull;
|
||||
}
|
||||
|
||||
|
@ -2346,6 +2364,65 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
|
|||
{"CreateHandle", "Shader model 6.5 and below"});
|
||||
}
|
||||
break;
|
||||
|
||||
case DXIL::OpCode::ThreadId: // SV_DispatchThreadID
|
||||
if (shaderKind != DXIL::ShaderKind::Node) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nodeLaunchType == DXIL::NodeLaunchType::Broadcasting)
|
||||
break;
|
||||
|
||||
ValCtx.EmitInstrFormatError(
|
||||
CI, ValidationRule::InstrSVConflictingLaunchMode,
|
||||
{"ThreadId", "SV_DispatchThreadID", GetLaunchTypeStr(nodeLaunchType)});
|
||||
break;
|
||||
|
||||
case DXIL::OpCode::GroupId: // SV_GroupId
|
||||
if (shaderKind != DXIL::ShaderKind::Node) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nodeLaunchType == DXIL::NodeLaunchType::Broadcasting)
|
||||
break;
|
||||
|
||||
ValCtx.EmitInstrFormatError(
|
||||
CI, ValidationRule::InstrSVConflictingLaunchMode,
|
||||
{"GroupId", "SV_GroupId", GetLaunchTypeStr(nodeLaunchType)});
|
||||
break;
|
||||
|
||||
case DXIL::OpCode::ThreadIdInGroup: // SV_GroupThreadID
|
||||
if (shaderKind != DXIL::ShaderKind::Node) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nodeLaunchType == DXIL::NodeLaunchType::Broadcasting ||
|
||||
nodeLaunchType == DXIL::NodeLaunchType::Coalescing)
|
||||
break;
|
||||
|
||||
ValCtx.EmitInstrFormatError(CI,
|
||||
ValidationRule::InstrSVConflictingLaunchMode,
|
||||
{"ThreadIdInGroup", "SV_GroupThreadID",
|
||||
GetLaunchTypeStr(nodeLaunchType)});
|
||||
|
||||
break;
|
||||
|
||||
case DXIL::OpCode::FlattenedThreadIdInGroup: // SV_GroupIndex
|
||||
if (shaderKind != DXIL::ShaderKind::Node) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nodeLaunchType == DXIL::NodeLaunchType::Broadcasting ||
|
||||
nodeLaunchType == DXIL::NodeLaunchType::Coalescing)
|
||||
break;
|
||||
|
||||
ValCtx.EmitInstrFormatError(CI,
|
||||
ValidationRule::InstrSVConflictingLaunchMode,
|
||||
{"FlattenedThreadIdInGroup", "SV_GroupIndex",
|
||||
GetLaunchTypeStr(nodeLaunchType)});
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: make sure every opcode is checked.
|
||||
// Skip opcodes don't need special check.
|
||||
|
@ -3520,7 +3597,6 @@ static void ValidateFunction(Function &F, ValidationContext &ValCtx) {
|
|||
{std::to_string(arg.getArgNo()), F.getName()});
|
||||
};
|
||||
|
||||
// Validate parameter type.
|
||||
unsigned numArgs = 0;
|
||||
for (auto &arg : F.args()) {
|
||||
Type *argTy = arg.getType();
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
; RUN: %dxv %s | FileCheck %s
|
||||
|
||||
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"
|
||||
|
||||
; CHECK: Function: entry3: error: Call to DXIL intrinsic ThreadId (SV_DispatchThreadID) is not allowed in node shader launch type Coalescing
|
||||
; CHECK: note: at '%1 = call i32 @dx.op.threadId.i32(i32 93, i32 1)' in block '#0' of function 'entry3'.
|
||||
; CHECK: Function: entry3: error: Call to DXIL intrinsic GroupId (SV_GroupId) is not allowed in node shader launch type Coalescing
|
||||
; CHECK: note: at '%2 = call i32 @dx.op.groupId.i32(i32 94, i32 2)' in block '#0' of function 'entry3'.
|
||||
|
||||
define void @entry3() {
|
||||
%1 = call i32 @dx.op.threadId.i32(i32 93, i32 1)
|
||||
%2 = call i32 @dx.op.groupId.i32(i32 94, i32 2)
|
||||
%3 = call i32 @dx.op.threadIdInGroup.i32(i32 95, i32 1)
|
||||
%4 = call i32 @dx.op.flattenedThreadIdInGroup.i32(i32 96)
|
||||
ret void
|
||||
}
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!2}
|
||||
!dx.shaderModel = !{!3}
|
||||
!dx.typeAnnotations = !{!4}
|
||||
!dx.entryPoints = !{!8, !9}
|
||||
|
||||
!0 = !{!"dxc(private) 1.7.0.14317 (main, e3c311409675)"}
|
||||
!1 = !{i32 1, i32 3}
|
||||
!2 = !{i32 1, i32 8}
|
||||
!3 = !{!"lib", i32 6, i32 3}
|
||||
!4 = !{i32 1, void ()* @entry3, !5}
|
||||
!5 = !{!6}
|
||||
!6 = !{i32 0, !7, !7}
|
||||
!7 = !{}
|
||||
!8 = !{null, !"", null, null, null}
|
||||
!9 = !{void ()* @entry3, !"entry3", null, null, !10}
|
||||
!10 = !{i32 8, i32 15, i32 13, i32 2, i32 15, !11, i32 16, i32 -1, i32 4, !12, i32 5, !13}
|
||||
!11 = !{!"entry3", i32 0}
|
||||
!12 = !{i32 1, i32 1, i32 1}
|
||||
!13 = !{i32 0}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.threadId.i32(i32, i32) #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.groupId.i32(i32, i32) #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.threadIdInGroup.i32(i32, i32) #0
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.flattenedThreadIdInGroup.i32(i32) #0
|
|
@ -0,0 +1,55 @@
|
|||
; RUN: %dxv %s | FileCheck %s
|
||||
|
||||
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"
|
||||
|
||||
; CHECK: Function: entry: error: Call to DXIL intrinsic ThreadId (SV_DispatchThreadID) is not allowed in node shader launch type Thread
|
||||
; CHECK: note: at '%1 = call i32 @dx.op.threadId.i32(i32 93, i32 1)' in block '#0' of function 'entry'.
|
||||
; CHECK: Function: entry: error: Call to DXIL intrinsic GroupId (SV_GroupId) is not allowed in node shader launch type Thread
|
||||
; CHECK: note: at '%2 = call i32 @dx.op.groupId.i32(i32 94, i32 2)' in block '#0' of function 'entry'.
|
||||
; CHECK: Function: entry: error: Call to DXIL intrinsic ThreadIdInGroup (SV_GroupThreadID) is not allowed in node shader launch type Thread
|
||||
; CHECK: note: at '%3 = call i32 @dx.op.threadIdInGroup.i32(i32 95, i32 1)' in block '#0' of function 'entry'.
|
||||
; CHECK: Function: entry: error: Call to DXIL intrinsic FlattenedThreadIdInGroup (SV_GroupIndex) is not allowed in node shader launch type Thread
|
||||
; CHECK: note: at '%4 = call i32 @dx.op.flattenedThreadIdInGroup.i32(i32 96)' in block '#0' of function 'entry'.
|
||||
|
||||
define void @entry() {
|
||||
%1 = call i32 @dx.op.threadId.i32(i32 93, i32 1)
|
||||
%2 = call i32 @dx.op.groupId.i32(i32 94, i32 2)
|
||||
%3 = call i32 @dx.op.threadIdInGroup.i32(i32 95, i32 1)
|
||||
%4 = call i32 @dx.op.flattenedThreadIdInGroup.i32(i32 96)
|
||||
ret void
|
||||
}
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!2}
|
||||
!dx.shaderModel = !{!3}
|
||||
!dx.typeAnnotations = !{!4}
|
||||
!dx.entryPoints = !{!8, !9}
|
||||
|
||||
!0 = !{!"dxc(private) 1.7.0.14317 (main, e3c311409675)"}
|
||||
!1 = !{i32 1, i32 3}
|
||||
!2 = !{i32 1, i32 8}
|
||||
!3 = !{!"lib", i32 6, i32 3}
|
||||
!4 = !{i32 1, void ()* @entry, !5}
|
||||
!5 = !{!6}
|
||||
!6 = !{i32 0, !7, !7}
|
||||
!7 = !{}
|
||||
!8 = !{null, !"", null, null, null}
|
||||
!9 = !{void ()* @entry, !"entry", null, null, !10}
|
||||
!10 = !{i32 8, i32 15, i32 13, i32 3, i32 15, !11, i32 16, i32 -1, i32 4, !12, i32 5, !13}
|
||||
!11 = !{!"entry", i32 0}
|
||||
!12 = !{i32 1, i32 1, i32 1}
|
||||
!13 = !{i32 0}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.threadId.i32(i32, i32) #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.groupId.i32(i32, i32) #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.threadIdInGroup.i32(i32, i32) #0
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @dx.op.flattenedThreadIdInGroup.i32(i32) #0
|
|
@ -7559,6 +7559,11 @@ class db_dxil(object):
|
|||
self.add_valrule(
|
||||
"Instr.AtomicIntrinNonUAV", "Non-UAV destination to atomic intrinsic."
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Instr.SVConflictingLaunchMode",
|
||||
"Input system values are compatible with node shader launch mode.",
|
||||
"Call to DXIL intrinsic %0 (%1) is not allowed in node shader launch type %2"
|
||||
)
|
||||
self.add_valrule("Instr.AtomicConst", "Constant destination to atomic.")
|
||||
|
||||
# Work-Graphs
|
||||
|
|
Загрузка…
Ссылка в новой задаче