DxilValidation: add ShaderCompatInfo call graph checking (#6332)
ShaderCompatInfo identifies compatibility for functions that could be called from an entry point. Currently, this checking detects compatibility problems between entry points and internal function calls that the validator otherwise misses. This change adds a check for ShaderCompatInfo, recursing into called functions looking for a source of conflict when not compatible with the current entry point properties. Errors are emitted for the entry point and at one source of each type of conflict that ShaderCompatInfo detects. A function is considered the source of a conflict when it has the conflict but none of the functions called from this function have this conflict. Removed early exit for ShaderFlags validation when module is a library, since these flags should be validated for libraries, and running CollectShaderFlagsForModule fills in the ShaderCompatInfo data we need for validation. Also fixed tests for illegal barrier and derivative use, as well as replacing the ignored MaxOutputRecords with the correct MaxRecords attribute. Fixes #6292.
This commit is contained in:
Родитель
1a48b86e08
Коммит
696a13a2a8
|
@ -3216,6 +3216,14 @@ SM.GSVALIDINPUTPRIMITIVE GS input primitive unrecognized.
|
|||
SM.GSVALIDOUTPUTPRIMITIVETOPOLOGY GS output primitive topology unrecognized.
|
||||
SM.HSINPUTCONTROLPOINTCOUNTRANGE HS input control point count must be [0..%0]. %1 specified.
|
||||
SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH For pass thru hull shader, input control point count must match output control point count
|
||||
SM.INCOMPATIBLECALLINENTRY Features used in internal function calls must be compatible with entry
|
||||
SM.INCOMPATIBLEDERIVINCOMPUTESHADERMODEL Derivatives in compute-model shaders require shader model 6.6 and above
|
||||
SM.INCOMPATIBLEDERIVLAUNCH Node shaders only support derivatives in broadcasting launch mode
|
||||
SM.INCOMPATIBLEOPERATION Operations used in entry function must be compatible with shader stage and other properties
|
||||
SM.INCOMPATIBLEREQUIRESGROUP Functions requiring groupshared memory must be called from shaders with a visible group
|
||||
SM.INCOMPATIBLESHADERMODEL Functions may only use features available in the current shader model
|
||||
SM.INCOMPATIBLESTAGE Functions may only use features available in the entry function's stage
|
||||
SM.INCOMPATIBLETHREADGROUPDIM When derivatives are used in compute-model shaders, the thread group dimensions must be compatible
|
||||
SM.INSIDETESSFACTORSIZEMATCHDOMAIN InsideTessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column.
|
||||
SM.INVALIDRESOURCECOMPTYPE Invalid resource return type.
|
||||
SM.INVALIDRESOURCEKIND Invalid resources kind.
|
||||
|
|
|
@ -174,6 +174,7 @@ struct ValidationContext {
|
|||
const unsigned kLLVMLoopMDKind;
|
||||
unsigned m_DxilMajor, m_DxilMinor;
|
||||
ModuleSlotTracker slotTracker;
|
||||
std::unique_ptr<CallGraph> pCallGraph;
|
||||
|
||||
ValidationContext(Module &llvmModule, Module *DebugModule,
|
||||
DxilModule &dxilModule)
|
||||
|
@ -397,6 +398,12 @@ struct ValidationContext {
|
|||
|
||||
EntryStatus &GetEntryStatus(Function *F) { return *entryStatusMap[F]; }
|
||||
|
||||
CallGraph &GetCallGraph() {
|
||||
if (!pCallGraph)
|
||||
pCallGraph = llvm::make_unique<CallGraph>(M);
|
||||
return *pCallGraph.get();
|
||||
}
|
||||
|
||||
DxilResourceProperties GetResourceFromVal(Value *resVal);
|
||||
|
||||
void EmitGlobalVariableFormatError(GlobalVariable *GV, ValidationRule rule,
|
||||
|
@ -5386,6 +5393,216 @@ static void ValidateEntrySignatures(ValidationContext &ValCtx) {
|
|||
}
|
||||
}
|
||||
|
||||
// CompatibilityChecker is used to identify incompatibilities in an entry
|
||||
// function and any functions called by that entry function.
|
||||
struct CompatibilityChecker {
|
||||
ValidationContext &ValCtx;
|
||||
Function *EntryFn;
|
||||
const DxilFunctionProps &props;
|
||||
DXIL::ShaderKind shaderKind;
|
||||
|
||||
// These masks identify the potential conflict flags based on the entry
|
||||
// function's shader kind and properties when either UsesDerivatives or
|
||||
// RequiresGroup flags are set in ShaderCompatInfo.
|
||||
uint32_t maskForDeriv = 0;
|
||||
uint32_t maskForGroup = 0;
|
||||
|
||||
enum class ConflictKind : uint32_t {
|
||||
Stage,
|
||||
ShaderModel,
|
||||
DerivLaunch,
|
||||
DerivThreadGroupDim,
|
||||
DerivInComputeShaderModel,
|
||||
RequiresGroup,
|
||||
};
|
||||
enum class ConflictFlags : uint32_t {
|
||||
Stage = 1 << (uint32_t)ConflictKind::Stage,
|
||||
ShaderModel = 1 << (uint32_t)ConflictKind::ShaderModel,
|
||||
DerivLaunch = 1 << (uint32_t)ConflictKind::DerivLaunch,
|
||||
DerivThreadGroupDim = 1 << (uint32_t)ConflictKind::DerivThreadGroupDim,
|
||||
DerivInComputeShaderModel =
|
||||
1 << (uint32_t)ConflictKind::DerivInComputeShaderModel,
|
||||
RequiresGroup = 1 << (uint32_t)ConflictKind::RequiresGroup,
|
||||
};
|
||||
|
||||
CompatibilityChecker(ValidationContext &ValCtx, Function *EntryFn)
|
||||
: ValCtx(ValCtx), EntryFn(EntryFn),
|
||||
props(ValCtx.DxilMod.GetDxilEntryProps(EntryFn).props),
|
||||
shaderKind(props.shaderKind) {
|
||||
|
||||
// Precompute potential incompatibilities based on shader stage, shader kind
|
||||
// and entry attributes. These will turn into full conflicts if the entry
|
||||
// point's shader flags indicate that they use relevant features.
|
||||
if (!ValCtx.DxilMod.GetShaderModel()->IsSM66Plus() &&
|
||||
(shaderKind == DXIL::ShaderKind::Mesh ||
|
||||
shaderKind == DXIL::ShaderKind::Amplification ||
|
||||
shaderKind == DXIL::ShaderKind::Compute)) {
|
||||
maskForDeriv |=
|
||||
static_cast<uint32_t>(ConflictFlags::DerivInComputeShaderModel);
|
||||
} else if (shaderKind == DXIL::ShaderKind::Node) {
|
||||
// Only broadcasting launch supports derivatives.
|
||||
if (props.Node.LaunchType != DXIL::NodeLaunchType::Broadcasting)
|
||||
maskForDeriv |= static_cast<uint32_t>(ConflictFlags::DerivLaunch);
|
||||
// Thread launch node has no group.
|
||||
if (props.Node.LaunchType == DXIL::NodeLaunchType::Thread)
|
||||
maskForGroup |= static_cast<uint32_t>(ConflictFlags::RequiresGroup);
|
||||
}
|
||||
|
||||
if (shaderKind == DXIL::ShaderKind::Mesh ||
|
||||
shaderKind == DXIL::ShaderKind::Amplification ||
|
||||
shaderKind == DXIL::ShaderKind::Compute ||
|
||||
shaderKind == DXIL::ShaderKind::Node) {
|
||||
// All compute-like stages
|
||||
// Thread dimensions must be either 1D and X is multiple of 4, or 2D
|
||||
// and X and Y must be multiples of 2.
|
||||
if (props.numThreads[1] == 1 && props.numThreads[2] == 1) {
|
||||
if ((props.numThreads[0] & 0x3) != 0)
|
||||
maskForDeriv |=
|
||||
static_cast<uint32_t>(ConflictFlags::DerivThreadGroupDim);
|
||||
} else if ((props.numThreads[0] & 0x1) || (props.numThreads[1] & 0x1))
|
||||
maskForDeriv |=
|
||||
static_cast<uint32_t>(ConflictFlags::DerivThreadGroupDim);
|
||||
} else {
|
||||
// other stages have no group
|
||||
maskForGroup |= static_cast<uint32_t>(ConflictFlags::RequiresGroup);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
IdentifyConflict(const DxilModule::ShaderCompatInfo &compatInfo) const {
|
||||
uint32_t conflictMask = 0;
|
||||
|
||||
// Compatibility check said this shader kind is not compatible.
|
||||
if (0 == ((1 << (uint32_t)shaderKind) & compatInfo.mask))
|
||||
conflictMask |= (uint32_t)ConflictFlags::Stage;
|
||||
|
||||
// Compatibility check said this shader model is not compatible.
|
||||
if (DXIL::CompareVersions(ValCtx.DxilMod.GetShaderModel()->GetMajor(),
|
||||
ValCtx.DxilMod.GetShaderModel()->GetMinor(),
|
||||
compatInfo.minMajor, compatInfo.minMinor) < 0)
|
||||
conflictMask |= (uint32_t)ConflictFlags::ShaderModel;
|
||||
|
||||
if (compatInfo.shaderFlags.GetUsesDerivatives())
|
||||
conflictMask |= maskForDeriv;
|
||||
|
||||
if (compatInfo.shaderFlags.GetRequiresGroup())
|
||||
conflictMask |= maskForGroup;
|
||||
|
||||
return conflictMask;
|
||||
}
|
||||
|
||||
void Diagnose(Function *F, uint32_t conflictMask, ConflictKind conflict,
|
||||
ValidationRule rule, ArrayRef<StringRef> args = {}) {
|
||||
if (conflictMask & (1 << (unsigned)conflict))
|
||||
ValCtx.EmitFnFormatError(F, rule, args);
|
||||
}
|
||||
|
||||
void DiagnoseConflicts(Function *F, uint32_t conflictMask) {
|
||||
// Emit a diagnostic indicating that either the entry function or a function
|
||||
// called by the entry function contains a disallowed operation.
|
||||
if (F == EntryFn)
|
||||
ValCtx.EmitFnError(EntryFn, ValidationRule::SmIncompatibleOperation);
|
||||
else
|
||||
ValCtx.EmitFnError(EntryFn, ValidationRule::SmIncompatibleCallInEntry);
|
||||
|
||||
// Emit diagnostics for each conflict found in this function.
|
||||
Diagnose(F, conflictMask, ConflictKind::Stage,
|
||||
ValidationRule::SmIncompatibleStage,
|
||||
{ShaderModel::GetKindName(props.shaderKind)});
|
||||
Diagnose(F, conflictMask, ConflictKind::ShaderModel,
|
||||
ValidationRule::SmIncompatibleShaderModel);
|
||||
Diagnose(F, conflictMask, ConflictKind::DerivLaunch,
|
||||
ValidationRule::SmIncompatibleDerivLaunch,
|
||||
{GetLaunchTypeStr(props.Node.LaunchType)});
|
||||
Diagnose(F, conflictMask, ConflictKind::DerivThreadGroupDim,
|
||||
ValidationRule::SmIncompatibleThreadGroupDim,
|
||||
{std::to_string(props.numThreads[0]),
|
||||
std::to_string(props.numThreads[1]),
|
||||
std::to_string(props.numThreads[2])});
|
||||
Diagnose(F, conflictMask, ConflictKind::DerivInComputeShaderModel,
|
||||
ValidationRule::SmIncompatibleDerivInComputeShaderModel);
|
||||
Diagnose(F, conflictMask, ConflictKind::RequiresGroup,
|
||||
ValidationRule::SmIncompatibleRequiresGroup);
|
||||
}
|
||||
|
||||
// Visit function and all functions called by it.
|
||||
// Emit diagnostics for incompatibilities found in a function when no
|
||||
// functions called by that function introduced the conflict.
|
||||
// In those cases, the called functions themselves will emit the diagnostic.
|
||||
// Return conflict mask for this function.
|
||||
uint32_t Visit(Function *F, uint32_t &remainingMask,
|
||||
llvm::SmallPtrSet<Function *, 8> &visited, CallGraph &CG) {
|
||||
// Recursive check looks for where a conflict is found and not present
|
||||
// in functions called by the current function.
|
||||
// - When a source is found, emit diagnostics and clear the conflict
|
||||
// flags introduced by this function from the working mask so we don't
|
||||
// report this conflict again.
|
||||
// - When the remainingMask is 0, we are done.
|
||||
|
||||
if (remainingMask == 0)
|
||||
return 0; // Nothing left to search for.
|
||||
if (!visited.insert(F).second)
|
||||
return 0; // Already visited.
|
||||
|
||||
const DxilModule::ShaderCompatInfo *compatInfo =
|
||||
ValCtx.DxilMod.GetCompatInfoForFunction(F);
|
||||
DXASSERT(compatInfo, "otherwise, compat info not computed in module");
|
||||
if (!compatInfo)
|
||||
return 0;
|
||||
uint32_t maskForThisFunction = IdentifyConflict(*compatInfo);
|
||||
|
||||
uint32_t maskForCalls = 0;
|
||||
if (CallGraphNode *CGNode = CG[F]) {
|
||||
for (auto &Call : *CGNode) {
|
||||
Function *called = Call.second->getFunction();
|
||||
if (called->isDeclaration())
|
||||
continue;
|
||||
maskForCalls |= Visit(called, remainingMask, visited, CG);
|
||||
if (remainingMask == 0)
|
||||
return 0; // Nothing left to search for.
|
||||
}
|
||||
}
|
||||
|
||||
// Mask of incompatibilities introduced by this function.
|
||||
uint32_t conflictsIntroduced =
|
||||
remainingMask & maskForThisFunction & ~maskForCalls;
|
||||
if (conflictsIntroduced) {
|
||||
// This function introduces at least one conflict.
|
||||
DiagnoseConflicts(F, conflictsIntroduced);
|
||||
// Mask off diagnosed incompatibilities.
|
||||
remainingMask &= ~conflictsIntroduced;
|
||||
}
|
||||
return maskForThisFunction;
|
||||
}
|
||||
|
||||
void FindIncompatibleCall(const DxilModule::ShaderCompatInfo &compatInfo) {
|
||||
uint32_t conflictMask = IdentifyConflict(compatInfo);
|
||||
if (conflictMask == 0)
|
||||
return;
|
||||
|
||||
CallGraph &CG = ValCtx.GetCallGraph();
|
||||
llvm::SmallPtrSet<Function *, 8> visited;
|
||||
Visit(EntryFn, conflictMask, visited, CG);
|
||||
}
|
||||
};
|
||||
|
||||
static void ValidateEntryCompatibility(ValidationContext &ValCtx) {
|
||||
// Make sure functions called from each entry are compatible with that entry.
|
||||
DxilModule &DM = ValCtx.DxilMod;
|
||||
for (Function &F : DM.GetModule()->functions()) {
|
||||
if (DM.HasDxilEntryProps(&F)) {
|
||||
const DxilModule::ShaderCompatInfo *compatInfo =
|
||||
DM.GetCompatInfoForFunction(&F);
|
||||
DXASSERT(compatInfo, "otherwise, compat info not computed in module");
|
||||
if (!compatInfo)
|
||||
continue;
|
||||
|
||||
CompatibilityChecker checker(ValCtx, &F);
|
||||
checker.FindIncompatibleCall(*compatInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckPatchConstantSemantic(ValidationContext &ValCtx,
|
||||
const DxilEntryProps &EntryProps,
|
||||
EntryStatus &Status, Function *F) {
|
||||
|
@ -5900,7 +6117,7 @@ CalculateCallDepth(CallGraphNode *node,
|
|||
|
||||
static void ValidateCallGraph(ValidationContext &ValCtx) {
|
||||
// Build CallGraph.
|
||||
CallGraph CG(*ValCtx.DxilMod.GetModule());
|
||||
CallGraph &CG = ValCtx.GetCallGraph();
|
||||
|
||||
std::unordered_map<CallGraphNode *, unsigned> depthMap;
|
||||
std::unordered_set<CallGraphNode *> callStack;
|
||||
|
@ -6161,6 +6378,8 @@ HRESULT ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule) {
|
|||
|
||||
ValidateShaderFlags(ValCtx);
|
||||
|
||||
ValidateEntryCompatibility(ValCtx);
|
||||
|
||||
ValidateEntrySignatures(ValCtx);
|
||||
|
||||
ValidateUninitializedOutput(ValCtx);
|
||||
|
|
|
@ -15,7 +15,7 @@ EmptyNodeOutput outputNode)
|
|||
[NodeDispatchGrid(1, 1, 1)]
|
||||
[NumThreads(1, 1, 1)]
|
||||
void node_EmptyNodeOutput(
|
||||
[MaxOutputRecords(1)] EmptyNodeOutput loadStressChild
|
||||
[MaxRecords(1)] EmptyNodeOutput loadStressChild
|
||||
)
|
||||
{
|
||||
loadStressEmptyRecWorker(wrapper(loadStressChild));
|
||||
|
|
|
@ -301,7 +301,7 @@ void node_RWGroupNodeInputRecords([MaxRecords(4)] RWGroupNodeInputRecords<RECORD
|
|||
[NodeLaunch("thread")]
|
||||
void node_RWThreadNodeInputRecord(RWThreadNodeInputRecord<RECORD> input)
|
||||
{
|
||||
Barrier(wrapper(input), 3);
|
||||
Barrier(wrapper(input), 0);
|
||||
}
|
||||
|
||||
// ThreadNodeInputRecord
|
||||
|
@ -317,7 +317,7 @@ void node_RWThreadNodeInputRecord(RWThreadNodeInputRecord<RECORD> input)
|
|||
[NodeLaunch("thread")]
|
||||
void node_ThreadNodeInputRecord(ThreadNodeInputRecord<RECORD> input)
|
||||
{
|
||||
Barrier(wrapper(input), 3);
|
||||
Barrier(wrapper(input), 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ void samplecmpbias() {
|
|||
// RDAT: MinShaderTarget: 0x50068
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(1,1,1)]
|
||||
[numthreads(4,1,1)]
|
||||
void samplecmpbias_compute(uint tidx : SV_GroupIndex) {
|
||||
samplecmpbias();
|
||||
}
|
||||
|
|
|
@ -38,9 +38,11 @@ float2 ddy;
|
|||
bool clamp;
|
||||
|
||||
[Shader("node")]
|
||||
[NodeLaunch("thread")]
|
||||
[NodeLaunch("broadcasting")]
|
||||
[NodeDispatchGrid(1, 1, 1)]
|
||||
[NumThreads(4, 1, 1)]
|
||||
void BackwardRef(
|
||||
RWThreadNodeInputRecord<rec0> InputyMcInputFace,
|
||||
RWDispatchNodeInputRecord<rec0> InputyMcInputFace,
|
||||
[MaxRecords(5)] NodeOutput<rec1> Output1,
|
||||
[MaxRecordsSharedWith(Output1)] NodeOutput<rec1> Output2)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,9 @@ static const int a = 7;
|
|||
static const int b = 3;
|
||||
|
||||
[Shader("node")]
|
||||
[NodeLaunch("thread")]
|
||||
[NodeLaunch("broadcasting")]
|
||||
[NodeDispatchGrid(1, 1, 1)]
|
||||
[NumThreads(1, 1, 1)]
|
||||
void node117_barrier_memoryarg()
|
||||
{
|
||||
// literal integer flag values
|
||||
|
@ -67,9 +69,9 @@ void node117_barrier_memoryarg()
|
|||
// Arg #1: ShaderKind Tag (8)
|
||||
// Arg #2: Node (15)
|
||||
// Arg #3: NodeLaunch Tag (13)
|
||||
// Arg #4: thread (3)
|
||||
// Arg #4: broadcasting (1)
|
||||
// ...
|
||||
// ------------------------------------------------------------------
|
||||
// CHECK: [[ATTRS]] = !{
|
||||
// CHECK-SAME: i32 8, i32 15, i32 13, i32 3
|
||||
// CHECK-SAME: i32 8, i32 15, i32 13, i32 1
|
||||
// CHECK-SAME: }
|
||||
|
|
|
@ -37,12 +37,12 @@ void node02([MaxRecords(8)] GroupNodeInputRecords<RECORD> input)
|
|||
[NodeLaunch("thread")]
|
||||
void node03(RWThreadNodeInputRecord<RECORD> input)
|
||||
{
|
||||
Barrier(input, 3);
|
||||
Barrier(input, 0);
|
||||
}
|
||||
// CHECK: define void @node03() {
|
||||
// CHECK: [[NODE03_A:%[0-9]+]] = call %dx.types.NodeRecordHandle @dx.op.createNodeInputRecordHandle(i32 {{[0-9]+}}, i32 0) ; CreateNodeInputRecordHandle(MetadataIdx)
|
||||
// CHECK: [[ANN_NODE03_A:%[0-9]+]] = call %dx.types.NodeRecordHandle @dx.op.annotateNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[NODE03_A]], %dx.types.NodeRecordInfo { i32 37, i32 4 })
|
||||
// CHECK: call void @dx.op.barrierByNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[ANN_NODE03_A]], i32 3) ; BarrierByNodeRecordHandle(object,SemanticFlags)
|
||||
// CHECK: call void @dx.op.barrierByNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[ANN_NODE03_A]], i32 0) ; BarrierByNodeRecordHandle(object,SemanticFlags)
|
||||
|
||||
[Shader("node")]
|
||||
[NodeLaunch("coalescing")]
|
||||
|
@ -74,22 +74,22 @@ void node05([MaxRecords(5)] NodeOutput<RECORD> outputs)
|
|||
|
||||
[Shader("node")]
|
||||
[NodeLaunch("thread")]
|
||||
void node06([MaxOutputRecords(5)] NodeOutput<RECORD> outputs)
|
||||
void node06([MaxRecords(5)] NodeOutput<RECORD> outputs)
|
||||
{
|
||||
ThreadNodeOutputRecords<RECORD> outrec = outputs.GetThreadNodeOutputRecords(3);
|
||||
Barrier(outrec, 3);
|
||||
Barrier(outrec, 0);
|
||||
}
|
||||
// CHECK: define void @node06() {
|
||||
// CHECK: [[NODE06_A:%[0-9]+]] = call %dx.types.NodeHandle @dx.op.createNodeOutputHandle(i32 {{[0-9]+}}, i32 0) ; CreateNodeOutputHandle(MetadataIdx)
|
||||
// CHECK: [[ANN_NODE06_A:%[0-9]+]] = call %dx.types.NodeHandle @dx.op.annotateNodeHandle(i32 {{[0-9]+}}, %dx.types.NodeHandle [[NODE06_A]], %dx.types.NodeInfo { i32 6, i32 4 })
|
||||
// CHECK: [[NODE06_B:%[0-9]+]] = call %dx.types.NodeRecordHandle @dx.op.allocateNodeOutputRecords(i32 {{[0-9]+}}, %dx.types.NodeHandle [[ANN_NODE06_A]], i32 3, i1 true) ; AllocateNodeOutputRecords(output,numRecords,perThread)
|
||||
// CHECK: [[ANN_NODE06_B:%[0-9]+]] = call %dx.types.NodeRecordHandle @dx.op.annotateNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[NODE06_B]], %dx.types.NodeRecordInfo { i32 38, i32 4 })
|
||||
// CHECK: call void @dx.op.barrierByNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[ANN_NODE06_B]], i32 3) ; BarrierByNodeRecordHandle(object,SemanticFlags)
|
||||
// CHECK: call void @dx.op.barrierByNodeRecordHandle(i32 {{[0-9]+}}, %dx.types.NodeRecordHandle [[ANN_NODE06_B]], i32 0) ; BarrierByNodeRecordHandle(object,SemanticFlags)
|
||||
|
||||
[Shader("node")]
|
||||
[NodeLaunch("coalescing")]
|
||||
[NumThreads(256,1,3)]
|
||||
void node07([MaxOutputRecords(5)] NodeOutput<RECORD> outputs)
|
||||
void node07([MaxRecords(5)] NodeOutput<RECORD> outputs)
|
||||
{
|
||||
GroupNodeOutputRecords<RECORD> outrec = outputs.GetGroupNodeOutputRecords(1);
|
||||
Barrier(outrec, 3);
|
||||
|
|
|
@ -71,7 +71,7 @@ void node03(NodeOutput<RECORD> output3)
|
|||
[Shader("node")]
|
||||
[NumThreads(1024,1,1)]
|
||||
[NodeLaunch("coalescing")]
|
||||
void node04([MaxOutputRecords(5)] NodeOutput<RECORD> outputs4)
|
||||
void node04([MaxRecords(5)] NodeOutput<RECORD> outputs4)
|
||||
{
|
||||
ThreadNodeOutputRecords<RECORD> outrec = outputs4.GetThreadNodeOutputRecords(1);
|
||||
// CHECK: getelementptr %struct.RECORD, %struct.RECORD addrspace(6)*
|
||||
|
|
|
@ -116,7 +116,7 @@ void node03(NodeOutput<RECORD> output3)
|
|||
[Shader("node")]
|
||||
[NumThreads(1024,1,1)]
|
||||
[NodeLaunch("coalescing")]
|
||||
void node04([MaxOutputRecords(5)] NodeOutput<RECORD> outputs4)
|
||||
void node04([MaxRecords(5)] NodeOutput<RECORD> outputs4)
|
||||
{
|
||||
GroupNodeOutputRecords<RECORD> outrec = outputs4.GetGroupNodeOutputRecords(1);
|
||||
// CHECK: %[[p1_0:[^ ]+]] = getelementptr inbounds %[[RECORD]], %[[RECORD]] addrspace(6)* %{{[^,]+}}, i32 0, i32 1, i32 0
|
||||
|
|
|
@ -12,7 +12,7 @@ EmptyNodeOutput outputNode)
|
|||
[NodeDispatchGrid(1, 1, 1)]
|
||||
[NumThreads(1, 1, 1)]
|
||||
void loadStressEmptyRec_1(
|
||||
[MaxOutputRecords(1)] EmptyNodeOutput loadStressChild
|
||||
[MaxRecords(1)] EmptyNodeOutput loadStressChild
|
||||
)
|
||||
{
|
||||
loadStressEmptyRecWorker(loadStressChild);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
// RUN: %dxc -T lib_6_8 -Vd %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
|
||||
|
||||
// Verifies that a Barrier requiring a visible group in a noinline function
|
||||
// called by a vertex shader is correctly marked as requiring a group in RDAT.
|
||||
// Validation is disabled to allow this to produce the RDAT blob for checking
|
||||
// the flags, and for generating .ll tests.
|
||||
|
||||
// RDAT: FunctionTable[{{.*}}] = {
|
||||
|
||||
RWBuffer<uint> Buf : register(u0);
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "write_value"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: 0
|
||||
// RDAT: ShaderStageFlag: (Pixel | Vertex | Geometry | Hull | Domain | Compute | Library | RayGeneration | Intersection | AnyHit | ClosestHit | Miss | Callable | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void write_value(uint value) {
|
||||
Buf[value] = value;
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "barrier_group"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_RequiresGroup)
|
||||
// RDAT: ShaderStageFlag: (Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void barrier_group() {
|
||||
write_value(1);
|
||||
Barrier(GROUP_SHARED_MEMORY, GROUP_SCOPE);
|
||||
write_value(2);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "intermediate"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_RequiresGroup)
|
||||
// RDAT: ShaderStageFlag: (Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void intermediate() {
|
||||
write_value(3);
|
||||
barrier_group();
|
||||
write_value(4);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "main"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_RequiresGroup)
|
||||
// ShaderStageFlag indicates no compatible entry type after masking for vertex.
|
||||
// RDAT: ShaderStageFlag: 0
|
||||
// MinShaderTarget still indicates vertex shader.
|
||||
// RDAT: MinShaderTarget: 0x10060
|
||||
|
||||
[shader("vertex")]
|
||||
void main() {
|
||||
intermediate();
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Make sure function compatibility checking is done for called functions.
|
||||
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}barrier_group{{.*}}: error: Function uses features incompatible with the shader stage (vs) of the entry function.
|
||||
; CHECK: Function: {{.*}}barrier_group{{.*}}: error: Function requires a visible group, but is called from a shader without one.
|
||||
|
||||
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.RWBuffer<unsigned int>" = type { i32 }
|
||||
|
||||
@"\01?Buf@@3V?$RWBuffer@I@@A" = external constant %dx.types.Handle, align 4
|
||||
|
||||
; Function to call that does nothing, so is not to blame for conflict.
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?write_value@@YAXI@Z"(i32 %value) #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@I@@A", align 4
|
||||
%2 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1)
|
||||
%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 4106, i32 261 })
|
||||
call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle %3, i32 %value, i32 undef, i32 %value, i32 %value, i32 %value, i32 %value, i8 15)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function that uses a barrier requiring visible group.
|
||||
; Also calls write_value, but this function is to blame for group requirement.
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?barrier_group@@YAXXZ"() #0 {
|
||||
call void @"\01?write_value@@YAXI@Z"(i32 1)
|
||||
call void @dx.op.barrierByMemoryType(i32 244, i32 2, i32 2)
|
||||
call void @"\01?write_value@@YAXI@Z"(i32 2)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Intermediate function that is not directly to blame for conflict.
|
||||
; Function calls barrier_group, and write_value.
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call void @"\01?write_value@@YAXI@Z"(i32 3)
|
||||
call void @"\01?barrier_group@@YAXXZ"()
|
||||
call void @"\01?write_value@@YAXI@Z"(i32 4)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #1 {
|
||||
call void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.i32(i32, %dx.types.Handle, i32, i32, i32, i32, i32, i32, i8) #1
|
||||
|
||||
; Function Attrs: noduplicate nounwind
|
||||
declare void @dx.op.barrierByMemoryType(i32, i32, i32) #2
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #3
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32, %dx.types.Handle) #4
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { noduplicate nounwind }
|
||||
attributes #3 = { nounwind readnone }
|
||||
attributes #4 = { nounwind readonly }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!1}
|
||||
!dx.shaderModel = !{!2}
|
||||
!dx.resources = !{!3}
|
||||
!dx.typeAnnotations = !{!7}
|
||||
!dx.entryPoints = !{!14, !16}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4482 (val-compat-calls, 055b660e4)"}
|
||||
!1 = !{i32 1, i32 8}
|
||||
!2 = !{!"lib", i32 6, i32 8}
|
||||
!3 = !{null, !4, null, null}
|
||||
!4 = !{!5}
|
||||
!5 = !{i32 0, %"class.RWBuffer<unsigned int>"* bitcast (%dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@I@@A" to %"class.RWBuffer<unsigned int>"*), !"Buf", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !6}
|
||||
!6 = !{i32 0, i32 5}
|
||||
!7 = !{i32 1, void (i32)* @"\01?write_value@@YAXI@Z", !8, void ()* @"\01?barrier_group@@YAXXZ", !13, void ()* @"\01?intermediate@@YAXXZ", !13, void ()* @main, !13}
|
||||
!8 = !{!9, !11}
|
||||
!9 = !{i32 1, !10, !10}
|
||||
!10 = !{}
|
||||
!11 = !{i32 0, !12, !10}
|
||||
!12 = !{i32 7, i32 5}
|
||||
!13 = !{!9}
|
||||
!14 = !{null, !"", null, !3, !15}
|
||||
!15 = !{i32 0, i64 8589934592}
|
||||
!16 = !{void ()* @main, !"main", null, null, !17}
|
||||
!17 = !{i32 8, i32 1, i32 5, !18}
|
||||
!18 = !{i32 0}
|
|
@ -0,0 +1,60 @@
|
|||
// RUN: %dxilver 1.8 | %dxc -T lib_6_5 -Vd %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
|
||||
|
||||
// Verifies that a Sample operation requiring derivatives in a noinline function
|
||||
// called by a compute shader is correctly marked as requiring SM 6.6 in RDAT.
|
||||
// Validation is disabled to allow this to produce the RDAT blob for checking
|
||||
// the MinShaderTarget, and for generating .ll tests.
|
||||
|
||||
// RDAT: FunctionTable[{{.*}}] = {
|
||||
|
||||
Texture2D<float4> T : register(t0);
|
||||
SamplerState S : register(s0);
|
||||
RWBuffer<float4> Buf : register(u0);
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "write_value"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: 0
|
||||
// RDAT: ShaderStageFlag: (Pixel | Vertex | Geometry | Hull | Domain | Compute | Library | RayGeneration | Intersection | AnyHit | ClosestHit | Miss | Callable | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void write_value(float value) {
|
||||
Buf[uint(value)] = value;
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "fn_sample"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Pixel | Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void fn_sample() {
|
||||
write_value(T.Sample(S, float2(0, 0)).x);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "intermediate"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Pixel | Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void intermediate() {
|
||||
write_value(1);
|
||||
fn_sample();
|
||||
write_value(2);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "main"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Compute)
|
||||
// MinShaderTarget indicates higher requirement.
|
||||
// RDAT: MinShaderTarget: 0x50066
|
||||
|
||||
[numthreads(8, 8, 1)]
|
||||
[shader("compute")]
|
||||
void main() {
|
||||
intermediate();
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Verify that Sample called from compute shader is not allowed when shader
|
||||
; model is less than 6.6 when compiled to library.
|
||||
; test generated from deriv-in-nested-fn-cs65.hlsl
|
||||
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function uses derivatives in compute-model shader, which is only supported in shader model 6.6 and above.
|
||||
|
||||
; This next error is also emitted because when the derivative usage is combined
|
||||
; with the shader stage at the entry point, it results in setting the minimum
|
||||
; shader model to 6.6. It is seen as an independent conflict in a way.
|
||||
; It would be difficult to mask it off without missing other conflicts that
|
||||
; could have independently caused the minimum shader model to be set higher.
|
||||
; CHECK: Function: main: error: Entry function performs some operation that is incompatible with the shader stage or other entry properties. See other errors for details.
|
||||
; CHECK: Function: main: error: Function uses features incompatible with the shader model.
|
||||
|
||||
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"
|
||||
|
||||
%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
|
||||
%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
|
||||
%struct.SamplerState = type { i32 }
|
||||
%"class.RWBuffer<vector<float, 4> >" = type { <4 x float> }
|
||||
%dx.types.Handle = type { i8* }
|
||||
%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
|
||||
|
||||
@"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" = external constant %"class.Texture2D<vector<float, 4> >", align 4
|
||||
@"\01?S@@3USamplerState@@A" = external constant %struct.SamplerState, align 4
|
||||
@"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" = external constant %"class.RWBuffer<vector<float, 4> >", align 4
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> %value) #0 {
|
||||
%1 = load %"class.RWBuffer<vector<float, 4> >", %"class.RWBuffer<vector<float, 4> >"* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A", align 4
|
||||
%2 = extractelement <4 x float> %value, i32 0
|
||||
%3 = fptoui float %2 to i32
|
||||
%4 = call %dx.types.Handle @"dx.op.createHandleForLib.class.RWBuffer<vector<float, 4> >"(i32 160, %"class.RWBuffer<vector<float, 4> >" %1) ; CreateHandleForLib(Resource)
|
||||
%5 = extractelement <4 x float> %value, i64 0
|
||||
%6 = extractelement <4 x float> %value, i64 1
|
||||
%7 = extractelement <4 x float> %value, i64 2
|
||||
%8 = extractelement <4 x float> %value, i64 3
|
||||
call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %4, i32 %3, i32 undef, float %5, float %6, float %7, float %8, i8 15) ; BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?fn_sample@@YAXXZ"() #0 {
|
||||
%1 = load %struct.SamplerState, %struct.SamplerState* @"\01?S@@3USamplerState@@A", align 4
|
||||
%2 = load %"class.Texture2D<vector<float, 4> >", %"class.Texture2D<vector<float, 4> >"* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A", align 4
|
||||
%3 = call %dx.types.Handle @"dx.op.createHandleForLib.class.Texture2D<vector<float, 4> >"(i32 160, %"class.Texture2D<vector<float, 4> >" %2) ; CreateHandleForLib(Resource)
|
||||
%4 = call %dx.types.Handle @dx.op.createHandleForLib.struct.SamplerState(i32 160, %struct.SamplerState %1) ; CreateHandleForLib(Resource)
|
||||
%5 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %3, %dx.types.Handle %4, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
|
||||
%6 = extractvalue %dx.types.ResRet.f32 %5, 0
|
||||
%7 = insertelement <4 x float> undef, float %6, i64 0
|
||||
%8 = extractvalue %dx.types.ResRet.f32 %5, 1
|
||||
%9 = insertelement <4 x float> %7, float %8, i64 1
|
||||
%10 = extractvalue %dx.types.ResRet.f32 %5, 2
|
||||
%11 = insertelement <4 x float> %9, float %10, i64 2
|
||||
%12 = extractvalue %dx.types.ResRet.f32 %5, 3
|
||||
%13 = insertelement <4 x float> %11, float %12, i64 3
|
||||
call void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> %13)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>)
|
||||
call void @"\01?fn_sample@@YAXXZ"()
|
||||
call void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #1 {
|
||||
call void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8) #1
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @"dx.op.createHandleForLib.class.RWBuffer<vector<float, 4> >"(i32, %"class.RWBuffer<vector<float, 4> >") #2
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @"dx.op.createHandleForLib.class.Texture2D<vector<float, 4> >"(i32, %"class.Texture2D<vector<float, 4> >") #2
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @dx.op.createHandleForLib.struct.SamplerState(i32, %struct.SamplerState) #2
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind readonly }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!2}
|
||||
!dx.shaderModel = !{!3}
|
||||
!dx.resources = !{!4}
|
||||
!dx.typeAnnotations = !{!12}
|
||||
!dx.entryPoints = !{!19, !20}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4482 (val-compat-calls, 055b660e4)"}
|
||||
!1 = !{i32 1, i32 5}
|
||||
!2 = !{i32 1, i32 8}
|
||||
!3 = !{!"lib", i32 6, i32 5}
|
||||
!4 = !{!5, !8, null, !10}
|
||||
!5 = !{!6}
|
||||
!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A", !"T", i32 0, i32 0, i32 1, i32 2, i32 0, !7}
|
||||
!7 = !{i32 0, i32 9}
|
||||
!8 = !{!9}
|
||||
!9 = !{i32 0, %"class.RWBuffer<vector<float, 4> >"* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A", !"Buf", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !7}
|
||||
!10 = !{!11}
|
||||
!11 = !{i32 0, %struct.SamplerState* @"\01?S@@3USamplerState@@A", !"S", i32 0, i32 0, i32 1, i32 0, null}
|
||||
!12 = !{i32 1, void (<4 x float>)* @"\01?write_value@@YAXV?$vector@M$03@@@Z", !13, void ()* @"\01?fn_sample@@YAXXZ", !18, void ()* @"\01?intermediate@@YAXXZ", !18, void ()* @main, !18}
|
||||
!13 = !{!14, !16}
|
||||
!14 = !{i32 1, !15, !15}
|
||||
!15 = !{}
|
||||
!16 = !{i32 0, !17, !15}
|
||||
!17 = !{i32 7, i32 9}
|
||||
!18 = !{!14}
|
||||
!19 = !{null, !"", null, !4, null}
|
||||
!20 = !{void ()* @main, !"main", null, null, !21}
|
||||
!21 = !{i32 8, i32 5, i32 4, !22, i32 5, !23}
|
||||
!22 = !{i32 8, i32 8, i32 1}
|
||||
!23 = !{i32 0}
|
|
@ -0,0 +1,110 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Verify that Sample called from compute shader is not allowed when thread
|
||||
; group size is not compatible with derivatives.
|
||||
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function uses derivatives in compute-model shader with NumThreads (17, 1, 1); derivatives require NumThreads to be 1D and a multiple of 4, or 2D/3D with X and Y both being a multiple of 2.
|
||||
|
||||
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 }
|
||||
%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
|
||||
%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
|
||||
%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
|
||||
%"class.RWBuffer<vector<float, 4> >" = type { <4 x float> }
|
||||
%struct.SamplerState = type { i32 }
|
||||
|
||||
@"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" = external constant %dx.types.Handle, align 4
|
||||
@"\01?S@@3USamplerState@@A" = external constant %dx.types.Handle, align 4
|
||||
@"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" = external constant %dx.types.Handle, align 4
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?write_value@@YAXM@Z"(float %value) #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A", align 4
|
||||
%2 = fptoui float %value to i32
|
||||
%3 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
|
||||
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 4106, i32 1033 }) ; AnnotateHandle(res,props) resource: RWTypedBuffer<4xF32>
|
||||
call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %4, i32 %2, i32 undef, float %value, float %value, float %value, float %value, i8 15) ; BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?fn_sample@@YAXXZ"() #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?S@@3USamplerState@@A", align 4
|
||||
%2 = load %dx.types.Handle, %dx.types.Handle* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A", align 4
|
||||
%3 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %2) ; CreateHandleForLib(Resource)
|
||||
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 2, i32 1033 }) ; AnnotateHandle(res,props) resource: Texture2D<4xF32>
|
||||
%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 14, i32 0 }) ; AnnotateHandle(res,props) resource: SamplerState
|
||||
%7 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %4, %dx.types.Handle %6, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
|
||||
%8 = extractvalue %dx.types.ResRet.f32 %7, 0
|
||||
call void @"\01?write_value@@YAXM@Z"(float %8)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call void @"\01?write_value@@YAXM@Z"(float 1.000000e+00)
|
||||
call void @"\01?fn_sample@@YAXXZ"()
|
||||
call void @"\01?write_value@@YAXM@Z"(float 2.000000e+00)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #1 {
|
||||
call void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8) #1
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #3
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32, %dx.types.Handle) #2
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind readonly }
|
||||
attributes #3 = { nounwind readnone }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!2}
|
||||
!dx.shaderModel = !{!3}
|
||||
!dx.resources = !{!4}
|
||||
!dx.typeAnnotations = !{!12}
|
||||
!dx.entryPoints = !{!19, !20}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4484 (val-compat-calls, 9e4ee71a0)"}
|
||||
!1 = !{i32 1, i32 6}
|
||||
!2 = !{i32 1, i32 8}
|
||||
!3 = !{!"lib", i32 6, i32 6}
|
||||
!4 = !{!5, !8, null, !10}
|
||||
!5 = !{!6}
|
||||
!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* bitcast (%dx.types.Handle* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" to %"class.Texture2D<vector<float, 4> >"*), !"T", i32 0, i32 0, i32 1, i32 2, i32 0, !7}
|
||||
!7 = !{i32 0, i32 9}
|
||||
!8 = !{!9}
|
||||
!9 = !{i32 0, %"class.RWBuffer<vector<float, 4> >"* bitcast (%dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" to %"class.RWBuffer<vector<float, 4> >"*), !"Buf", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !7}
|
||||
!10 = !{!11}
|
||||
!11 = !{i32 0, %struct.SamplerState* bitcast (%dx.types.Handle* @"\01?S@@3USamplerState@@A" to %struct.SamplerState*), !"S", i32 0, i32 0, i32 1, i32 0, null}
|
||||
!12 = !{i32 1, void (float)* @"\01?write_value@@YAXM@Z", !13, void ()* @"\01?fn_sample@@YAXXZ", !18, void ()* @"\01?intermediate@@YAXXZ", !18, void ()* @main, !18}
|
||||
!13 = !{!14, !16}
|
||||
!14 = !{i32 1, !15, !15}
|
||||
!15 = !{}
|
||||
!16 = !{i32 0, !17, !15}
|
||||
!17 = !{i32 7, i32 9}
|
||||
!18 = !{!14}
|
||||
!19 = !{null, !"", null, !4, null}
|
||||
!20 = !{void ()* @main, !"main", null, null, !21}
|
||||
!21 = !{i32 8, i32 5, i32 4, !22, i32 5, !23}
|
||||
!22 = !{i32 17, i32 1, i32 1}
|
||||
!23 = !{i32 0}
|
|
@ -0,0 +1,92 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Verify that Sample called from compute shader is not allowed when shader
|
||||
; model is less than 6.6 when compiled to cs_6_5 non-library target.
|
||||
; Opcode validation fails because for non-lib shader models, all functions are
|
||||
; validated assuming the same stage. This verifies that the call graph
|
||||
; validation is still applied.
|
||||
; test generated from deriv-in-nested-fn-cs-lib65.hlsl with -T cs_6_5
|
||||
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: opcode 'Derivatives in CS/MS/AS' should only be used in 'Shader Model 6.6+'.
|
||||
; CHECK: note: at '%3 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %1, %dx.types.Handle %2, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef)' in block '#0' of function '{{.*}}fn_sample{{.*}}'.
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function uses derivatives in compute-model shader, which is only supported in shader model 6.6 and above.
|
||||
; CHECK: Function: main: error: Entry function performs some operation that is incompatible with the shader stage or other entry properties. See other errors for details.
|
||||
; CHECK: Function: main: error: Function uses features incompatible with the shader model.
|
||||
|
||||
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.ResRet.f32 = type { float, float, float, float, i32 }
|
||||
%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
|
||||
%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
|
||||
%"class.RWBuffer<vector<float, 4> >" = type { <4 x float> }
|
||||
%struct.SamplerState = type { i32 }
|
||||
|
||||
define void @main() {
|
||||
call fastcc void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define internal fastcc void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call fastcc void @"\01?write_value@@YAXM@Z"(float 1.000000e+00)
|
||||
call fastcc void @"\01?fn_sample@@YAXXZ"()
|
||||
call fastcc void @"\01?write_value@@YAXM@Z"(float 2.000000e+00)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define internal fastcc void @"\01?write_value@@YAXM@Z"(float %x) #0 {
|
||||
%1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
|
||||
%2 = fptoui float %x to i32
|
||||
call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %1, i32 %2, i32 undef, float %x, float %x, float %x, float %x, i8 15) ; BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define internal fastcc void @"\01?fn_sample@@YAXXZ"() #0 {
|
||||
%1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
|
||||
%2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
|
||||
%3 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %1, %dx.types.Handle %2, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
|
||||
%4 = extractvalue %dx.types.ResRet.f32 %3, 0
|
||||
call fastcc void @"\01?write_value@@YAXM@Z"(float %4)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8) #1
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind readonly }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!2}
|
||||
!dx.shaderModel = !{!3}
|
||||
!dx.resources = !{!4}
|
||||
!dx.entryPoints = !{!12}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4482 (val-compat-calls, 055b660e4)"}
|
||||
!1 = !{i32 1, i32 0}
|
||||
!2 = !{i32 1, i32 8}
|
||||
!3 = !{!"cs", i32 6, i32 0}
|
||||
!4 = !{!5, !8, null, !10}
|
||||
!5 = !{!6}
|
||||
!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* undef, !"", i32 0, i32 0, i32 1, i32 2, i32 0, !7}
|
||||
!7 = !{i32 0, i32 9}
|
||||
!8 = !{!9}
|
||||
!9 = !{i32 0, %"class.RWBuffer<vector<float, 4> >"* undef, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !7}
|
||||
!10 = !{!11}
|
||||
!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 0, i32 0, i32 1, i32 0, null}
|
||||
!12 = !{void ()* @main, !"main", null, !4, !13}
|
||||
!13 = !{i32 4, !14}
|
||||
!14 = !{i32 8, i32 8, i32 1}
|
|
@ -0,0 +1,93 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Verify that Sample called from compute shader is not allowed when thread
|
||||
; group size is not compatible with derivatives.
|
||||
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function uses derivatives in compute-model shader with NumThreads (8, 7, 1); derivatives require NumThreads to be 1D and a multiple of 4, or 2D/3D with X and Y both being a multiple of 2.
|
||||
|
||||
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.f32 = type { float, float, float, float, i32 }
|
||||
%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
|
||||
%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
|
||||
%"class.RWBuffer<vector<float, 4> >" = type { <4 x float> }
|
||||
%struct.SamplerState = type { i32 }
|
||||
|
||||
define void @main() {
|
||||
call fastcc void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define internal fastcc void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call fastcc void @"\01?write_value@@YAXM@Z"(float 1.000000e+00)
|
||||
call fastcc void @"\01?fn_sample@@YAXXZ"()
|
||||
call fastcc void @"\01?write_value@@YAXM@Z"(float 2.000000e+00)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define internal fastcc void @"\01?write_value@@YAXM@Z"(float %value) #0 {
|
||||
%1 = 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)
|
||||
%2 = fptoui float %value to i32
|
||||
%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %1, %dx.types.ResourceProperties { i32 4106, i32 1033 }) ; AnnotateHandle(res,props) resource: RWTypedBuffer<4xF32>
|
||||
call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %3, i32 %2, i32 undef, float %value, float %value, float %value, float %value, i8 15) ; BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define internal fastcc void @"\01?fn_sample@@YAXXZ"() #0 {
|
||||
%1 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind zeroinitializer, i32 0, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex)
|
||||
%2 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 0, i32 0, i8 3 }, i32 0, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex)
|
||||
%3 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %1, %dx.types.ResourceProperties { i32 2, i32 1033 }) ; AnnotateHandle(res,props) resource: Texture2D<4xF32>
|
||||
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %2, %dx.types.ResourceProperties { i32 14, i32 0 }) ; AnnotateHandle(res,props) resource: SamplerState
|
||||
%5 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %3, %dx.types.Handle %4, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
|
||||
%6 = extractvalue %dx.types.ResRet.f32 %5, 0
|
||||
call fastcc void @"\01?write_value@@YAXM@Z"(float %6)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8) #1
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #3
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare %dx.types.Handle @dx.op.createHandleFromBinding(i32, %dx.types.ResBind, i32, i1) #3
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind readonly }
|
||||
attributes #3 = { nounwind readnone }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!2}
|
||||
!dx.shaderModel = !{!3}
|
||||
!dx.resources = !{!4}
|
||||
!dx.entryPoints = !{!12}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4484 (val-compat-calls, 9e4ee71a0)"}
|
||||
!1 = !{i32 1, i32 6}
|
||||
!2 = !{i32 1, i32 8}
|
||||
!3 = !{!"cs", i32 6, i32 6}
|
||||
!4 = !{!5, !8, null, !10}
|
||||
!5 = !{!6}
|
||||
!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* undef, !"", i32 0, i32 0, i32 1, i32 2, i32 0, !7}
|
||||
!7 = !{i32 0, i32 9}
|
||||
!8 = !{!9}
|
||||
!9 = !{i32 0, %"class.RWBuffer<vector<float, 4> >"* undef, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !7}
|
||||
!10 = !{!11}
|
||||
!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 0, i32 0, i32 1, i32 0, null}
|
||||
!12 = !{void ()* @main, !"main", null, !4, !13}
|
||||
!13 = !{i32 4, !14}
|
||||
!14 = !{i32 8, i32 7, i32 1}
|
|
@ -0,0 +1,60 @@
|
|||
// RUN: %dxilver 1.8 | %dxc -T lib_6_8 -Vd %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
|
||||
|
||||
// Check that ShaderCompatInfo in RDAT has expected flags for scenario with
|
||||
// thread launch node calling a function using derivatives (through Sample()).
|
||||
// Validation is disabled to allow this to produce the RDAT blob to check.
|
||||
// Used to generate deriv-in-nested-fn-node-lib68-launch.ll
|
||||
|
||||
// RDAT: FunctionTable[{{.*}}] = {
|
||||
|
||||
Texture2D<float4> T : register(t0);
|
||||
SamplerState S : register(s0);
|
||||
RWBuffer<float4> Buf : register(u0);
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "write_value"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: 0
|
||||
// RDAT: ShaderStageFlag: (Pixel | Vertex | Geometry | Hull | Domain | Compute | Library | RayGeneration | Intersection | AnyHit | ClosestHit | Miss | Callable | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void write_value(float value) {
|
||||
Buf[uint(value)] = value;
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "fn_sample"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Pixel | Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void fn_sample() {
|
||||
write_value(T.Sample(S, float2(0, 0)).x);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "intermediate"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Pixel | Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void intermediate() {
|
||||
write_value(1);
|
||||
fn_sample();
|
||||
write_value(2);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "main"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Node)
|
||||
// RDAT: MinShaderTarget: 0xf0068
|
||||
// RDAT: LaunchType: Thread
|
||||
|
||||
[shader("node")]
|
||||
[NodeLaunch("thread")]
|
||||
void main() {
|
||||
intermediate();
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Sample called from node shader is not allowed with thread launch.
|
||||
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function called from Thread launch node shader uses derivatives; only broadcasting launch supports derivatives.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function uses derivatives in compute-model shader with NumThreads (1, 1, 1); derivatives require NumThreads to be 1D and a multiple of 4, or 2D/3D with X and Y both being a multiple of 2.
|
||||
|
||||
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 }
|
||||
%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
|
||||
%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
|
||||
%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
|
||||
%"class.RWBuffer<vector<float, 4> >" = type { <4 x float> }
|
||||
%struct.SamplerState = type { i32 }
|
||||
|
||||
@"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" = external constant %dx.types.Handle, align 4
|
||||
@"\01?S@@3USamplerState@@A" = external constant %dx.types.Handle, align 4
|
||||
@"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" = external constant %dx.types.Handle, align 4
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?write_value@@YAXM@Z"(float %value) #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A", align 4
|
||||
%2 = fptoui float %value to i32
|
||||
%3 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
|
||||
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 4106, i32 1033 }) ; AnnotateHandle(res,props) resource: RWTypedBuffer<4xF32>
|
||||
call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %4, i32 %2, i32 undef, float %value, float %value, float %value, float %value, i8 15) ; BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?fn_sample@@YAXXZ"() #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?S@@3USamplerState@@A", align 4
|
||||
%2 = load %dx.types.Handle, %dx.types.Handle* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A", align 4
|
||||
%3 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %2) ; CreateHandleForLib(Resource)
|
||||
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 2, i32 1033 }) ; AnnotateHandle(res,props) resource: Texture2D<4xF32>
|
||||
%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 14, i32 0 }) ; AnnotateHandle(res,props) resource: SamplerState
|
||||
%7 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %4, %dx.types.Handle %6, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
|
||||
%8 = extractvalue %dx.types.ResRet.f32 %7, 0
|
||||
call void @"\01?write_value@@YAXM@Z"(float %8)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call void @"\01?write_value@@YAXM@Z"(float 1.000000e+00)
|
||||
call void @"\01?fn_sample@@YAXXZ"()
|
||||
call void @"\01?write_value@@YAXM@Z"(float 2.000000e+00)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #1 {
|
||||
call void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8) #1
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #3
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32, %dx.types.Handle) #2
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind readonly }
|
||||
attributes #3 = { nounwind readnone }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!1}
|
||||
!dx.shaderModel = !{!2}
|
||||
!dx.resources = !{!3}
|
||||
!dx.typeAnnotations = !{!11}
|
||||
!dx.entryPoints = !{!18, !20}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4484 (val-compat-calls, 9e4ee71a0)"}
|
||||
!1 = !{i32 1, i32 8}
|
||||
!2 = !{!"lib", i32 6, i32 8}
|
||||
!3 = !{!4, !7, null, !9}
|
||||
!4 = !{!5}
|
||||
!5 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* bitcast (%dx.types.Handle* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" to %"class.Texture2D<vector<float, 4> >"*), !"T", i32 0, i32 0, i32 1, i32 2, i32 0, !6}
|
||||
!6 = !{i32 0, i32 9}
|
||||
!7 = !{!8}
|
||||
!8 = !{i32 0, %"class.RWBuffer<vector<float, 4> >"* bitcast (%dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" to %"class.RWBuffer<vector<float, 4> >"*), !"Buf", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !6}
|
||||
!9 = !{!10}
|
||||
!10 = !{i32 0, %struct.SamplerState* bitcast (%dx.types.Handle* @"\01?S@@3USamplerState@@A" to %struct.SamplerState*), !"S", i32 0, i32 0, i32 1, i32 0, null}
|
||||
!11 = !{i32 1, void (float)* @"\01?write_value@@YAXM@Z", !12, void ()* @"\01?fn_sample@@YAXXZ", !17, void ()* @"\01?intermediate@@YAXXZ", !17, void ()* @main, !17}
|
||||
!12 = !{!13, !15}
|
||||
!13 = !{i32 1, !14, !14}
|
||||
!14 = !{}
|
||||
!15 = !{i32 0, !16, !14}
|
||||
!16 = !{i32 7, i32 9}
|
||||
!17 = !{!13}
|
||||
!18 = !{null, !"", null, !3, !19}
|
||||
!19 = !{i32 0, i64 8589934592}
|
||||
!20 = !{void ()* @main, !"main", null, null, !21}
|
||||
!21 = !{i32 8, i32 15, i32 13, i32 3, i32 15, !22, i32 16, i32 -1, i32 4, !23, i32 5, !24}
|
||||
!22 = !{!"main", i32 0}
|
||||
!23 = !{i32 1, i32 1, i32 1}
|
||||
!24 = !{i32 0}
|
|
@ -0,0 +1,61 @@
|
|||
// RUN: %dxc -T lib_6_8 -Vd %s | %D3DReflect %s | %FileCheck %s -check-prefixes=RDAT
|
||||
|
||||
// Check that ShaderCompatInfo in RDAT has expected flags for scenario with
|
||||
// verttex entry point calling a function using derivatives (through Sample()).
|
||||
// Validation is disabled to allow this to produce the RDAT blob to check.
|
||||
// Used to generate deriv-in-nested-fn-vs.ll
|
||||
|
||||
// RDAT: FunctionTable[{{.*}}] = {
|
||||
|
||||
Texture2D<float4> T : register(t0);
|
||||
SamplerState S : register(s0);
|
||||
RWBuffer<float4> Buf : register(u0);
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "write_value"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: 0
|
||||
// RDAT: ShaderStageFlag: (Pixel | Vertex | Geometry | Hull | Domain | Compute | Library | RayGeneration | Intersection | AnyHit | ClosestHit | Miss | Callable | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void write_value(float4 value) {
|
||||
Buf[uint(value.x)] = value;
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "fn_sample"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Pixel | Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void fn_sample() {
|
||||
write_value(T.Sample(S, float2(0, 0)));
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "intermediate"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// RDAT: ShaderStageFlag: (Pixel | Compute | Library | Mesh | Amplification | Node)
|
||||
// RDAT: MinShaderTarget: 0x60060
|
||||
|
||||
[noinline] export
|
||||
void intermediate() {
|
||||
write_value(1);
|
||||
fn_sample();
|
||||
write_value(2);
|
||||
}
|
||||
|
||||
// RDAT-LABEL: UnmangledName: "main"
|
||||
// RDAT: FeatureInfo1: 0
|
||||
// RDAT: FeatureInfo2: (Opt_UsesDerivatives)
|
||||
// ShaderStageFlag indicates no compatible entry type after masking for vertex.
|
||||
// RDAT: ShaderStageFlag: 0
|
||||
// MinShaderTarget still indicates vertex shader.
|
||||
// RDAT: MinShaderTarget: 0x10060
|
||||
|
||||
//[numthreads(8, 8, 1)]
|
||||
[shader("vertex")]
|
||||
void main() {
|
||||
intermediate();
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s
|
||||
|
||||
; Verify that Sample called from vertex shader is not allowed.
|
||||
; test generated from deriv-in-nested-fn-vs.hlsl
|
||||
|
||||
; CHECK: Function: main: error: Entry function calls one or more functions using incompatible features. See other errors for details.
|
||||
; CHECK: Function: {{.*}}fn_sample{{.*}}: error: Function uses features incompatible with the shader stage (vs) of the entry function.
|
||||
|
||||
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 }
|
||||
%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
|
||||
%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
|
||||
%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
|
||||
%"class.RWBuffer<vector<float, 4> >" = type { <4 x float> }
|
||||
%struct.SamplerState = type { i32 }
|
||||
|
||||
@"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" = external constant %dx.types.Handle, align 4
|
||||
@"\01?S@@3USamplerState@@A" = external constant %dx.types.Handle, align 4
|
||||
@"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" = external constant %dx.types.Handle, align 4
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> %value) #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A", align 4
|
||||
%2 = extractelement <4 x float> %value, i32 0
|
||||
%3 = fptoui float %2 to i32
|
||||
%4 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %1) ; CreateHandleForLib(Resource)
|
||||
%5 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %4, %dx.types.ResourceProperties { i32 4106, i32 1033 }) ; AnnotateHandle(res,props) resource: RWTypedBuffer<4xF32>
|
||||
%6 = extractelement <4 x float> %value, i64 0
|
||||
%7 = extractelement <4 x float> %value, i64 1
|
||||
%8 = extractelement <4 x float> %value, i64 2
|
||||
%9 = extractelement <4 x float> %value, i64 3
|
||||
call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %5, i32 %3, i32 undef, float %6, float %7, float %8, float %9, i8 15) ; BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?fn_sample@@YAXXZ"() #0 {
|
||||
%1 = load %dx.types.Handle, %dx.types.Handle* @"\01?S@@3USamplerState@@A", align 4
|
||||
%2 = load %dx.types.Handle, %dx.types.Handle* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A", align 4
|
||||
%3 = call %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32 160, %dx.types.Handle %2) ; CreateHandleForLib(Resource)
|
||||
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 2, i32 1033 }) ; AnnotateHandle(res,props) resource: Texture2D<4xF32>
|
||||
%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 14, i32 0 }) ; AnnotateHandle(res,props) resource: SamplerState
|
||||
%7 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %4, %dx.types.Handle %6, float 0.000000e+00, float 0.000000e+00, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
|
||||
%8 = extractvalue %dx.types.ResRet.f32 %7, 0
|
||||
%9 = insertelement <4 x float> undef, float %8, i64 0
|
||||
%10 = extractvalue %dx.types.ResRet.f32 %7, 1
|
||||
%11 = insertelement <4 x float> %9, float %10, i64 1
|
||||
%12 = extractvalue %dx.types.ResRet.f32 %7, 2
|
||||
%13 = insertelement <4 x float> %11, float %12, i64 2
|
||||
%14 = extractvalue %dx.types.ResRet.f32 %7, 3
|
||||
%15 = insertelement <4 x float> %13, float %14, i64 3
|
||||
call void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> %15)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind
|
||||
define void @"\01?intermediate@@YAXXZ"() #0 {
|
||||
call void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>)
|
||||
call void @"\01?fn_sample@@YAXXZ"()
|
||||
call void @"\01?write_value@@YAXV?$vector@M$03@@@Z"(<4 x float> <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #1 {
|
||||
call void @"\01?intermediate@@YAXXZ"()
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8) #1
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #3
|
||||
|
||||
; Function Attrs: nounwind readonly
|
||||
declare %dx.types.Handle @dx.op.createHandleForLib.dx.types.Handle(i32, %dx.types.Handle) #2
|
||||
|
||||
attributes #0 = { noinline nounwind }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind readonly }
|
||||
attributes #3 = { nounwind readnone }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
!dx.version = !{!1}
|
||||
!dx.valver = !{!1}
|
||||
!dx.shaderModel = !{!2}
|
||||
!dx.resources = !{!3}
|
||||
!dx.typeAnnotations = !{!11}
|
||||
!dx.entryPoints = !{!18, !20}
|
||||
|
||||
!0 = !{!"dxc(private) 1.8.0.4482 (val-compat-calls, 055b660e4)"}
|
||||
!1 = !{i32 1, i32 8}
|
||||
!2 = !{!"lib", i32 6, i32 8}
|
||||
!3 = !{!4, !7, null, !9}
|
||||
!4 = !{!5}
|
||||
!5 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* bitcast (%dx.types.Handle* @"\01?T@@3V?$Texture2D@V?$vector@M$03@@@@A" to %"class.Texture2D<vector<float, 4> >"*), !"T", i32 0, i32 0, i32 1, i32 2, i32 0, !6}
|
||||
!6 = !{i32 0, i32 9}
|
||||
!7 = !{!8}
|
||||
!8 = !{i32 0, %"class.RWBuffer<vector<float, 4> >"* bitcast (%dx.types.Handle* @"\01?Buf@@3V?$RWBuffer@V?$vector@M$03@@@@A" to %"class.RWBuffer<vector<float, 4> >"*), !"Buf", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, !6}
|
||||
!9 = !{!10}
|
||||
!10 = !{i32 0, %struct.SamplerState* bitcast (%dx.types.Handle* @"\01?S@@3USamplerState@@A" to %struct.SamplerState*), !"S", i32 0, i32 0, i32 1, i32 0, null}
|
||||
!11 = !{i32 1, void (<4 x float>)* @"\01?write_value@@YAXV?$vector@M$03@@@Z", !12, void ()* @"\01?fn_sample@@YAXXZ", !17, void ()* @"\01?intermediate@@YAXXZ", !17, void ()* @main, !17}
|
||||
!12 = !{!13, !15}
|
||||
!13 = !{i32 1, !14, !14}
|
||||
!14 = !{}
|
||||
!15 = !{i32 0, !16, !14}
|
||||
!16 = !{i32 7, i32 9, i32 13, i32 4}
|
||||
!17 = !{!13}
|
||||
!18 = !{null, !"", null, !3, !19}
|
||||
!19 = !{i32 0, i64 8589934592}
|
||||
!20 = !{void ()* @main, !"main", null, null, !21}
|
||||
!21 = !{i32 8, i32 1, i32 5, !22}
|
||||
!22 = !{i32 0}
|
|
@ -7589,7 +7589,7 @@ class db_dxil(object):
|
|||
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"
|
||||
"Call to DXIL intrinsic %0 (%1) is not allowed in node shader launch type %2",
|
||||
)
|
||||
self.add_valrule("Instr.AtomicConst", "Constant destination to atomic.")
|
||||
|
||||
|
@ -8081,6 +8081,56 @@ class db_dxil(object):
|
|||
"%0 node shader '%1' has incompatible input record type (should be %2)",
|
||||
)
|
||||
|
||||
# These errors are emitted from ShaderCompatInfo validation.
|
||||
# If a called function is identifiable as a potential source of the
|
||||
# incompatibility, you get Sm.IncompatibleCallInEntry,
|
||||
# otherwise you get Sm.IncompatibleOperation.
|
||||
# You also get the specific incompatibilities found with one function
|
||||
# introducing each problem.
|
||||
# These may be emitted in addition to another specific operation
|
||||
# validation error that identifies the root cause, but is meant to
|
||||
# catch cases currently missed by other validation.
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleCallInEntry",
|
||||
"Features used in internal function calls must be compatible with entry",
|
||||
"Entry function calls one or more functions using incompatible features. See other errors for details.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleOperation",
|
||||
"Operations used in entry function must be compatible with shader stage and other properties",
|
||||
"Entry function performs some operation that is incompatible with the shader stage or other entry properties. See other errors for details.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleStage",
|
||||
"Functions may only use features available in the entry function's stage",
|
||||
"Function uses features incompatible with the shader stage (%0) of the entry function.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleShaderModel",
|
||||
"Functions may only use features available in the current shader model",
|
||||
"Function uses features incompatible with the shader model.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleThreadGroupDim",
|
||||
"When derivatives are used in compute-model shaders, the thread group dimensions must be compatible",
|
||||
"Function uses derivatives in compute-model shader with NumThreads (%0, %1, %2); derivatives require NumThreads to be 1D and a multiple of 4, or 2D/3D with X and Y both being a multiple of 2.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleDerivInComputeShaderModel",
|
||||
"Derivatives in compute-model shaders require shader model 6.6 and above",
|
||||
"Function uses derivatives in compute-model shader, which is only supported in shader model 6.6 and above.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleRequiresGroup",
|
||||
"Functions requiring groupshared memory must be called from shaders with a visible group",
|
||||
"Function requires a visible group, but is called from a shader without one.",
|
||||
)
|
||||
self.add_valrule_msg(
|
||||
"Sm.IncompatibleDerivLaunch",
|
||||
"Node shaders only support derivatives in broadcasting launch mode",
|
||||
"Function called from %0 launch node shader uses derivatives; only broadcasting launch supports derivatives.",
|
||||
)
|
||||
|
||||
# Assign sensible category names and build up an enumeration description
|
||||
cat_names = {
|
||||
"CONTAINER": "Container",
|
||||
|
|
Загрузка…
Ссылка в новой задаче