Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3418,6 +3418,7 @@ SM.RESOURCERANGEOVERLAP Resource ranges must not o
SM.ROVONLYINPS RasterizerOrdered objects are only allowed in 5.0+ pixel shaders.
SM.SAMPLECOUNTONLYON2DMS Only Texture2DMS/2DMSArray could has sample count.
SM.SEMANTIC Semantic must be defined in target shader model
SM.SHADERSTAGE Shader stage must be supported by the target shader model
SM.STREAMINDEXRANGE Stream index (%0) must between 0 and %1.
SM.TESSFACTORFORDOMAIN Required TessFactor for domain not found declared anywhere in Patch Constant data.
SM.TESSFACTORSIZEMATCHDOMAIN TessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column.
Expand Down
3 changes: 2 additions & 1 deletion docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ first shipped in the 1.10.2605 preview.
- Restricted the component types allowed in LinAlg matrices
[#8608](https://github.com/microsoft/DirectXShaderCompiler/pull/8608).
- Added `BFloat16` to the ComponentType enum in DxilConstants and the linalg
header [#8722](https://github.com/microsoft/DirectXShaderCompiler/issues/8722)
header [#8722](https://github.com/microsoft/DirectXShaderCompiler/issues/8722).
- Removed work graph support from Shader Model 6.10, and DXIL 1.10 [microsoft/hlsl-specs#915](https://github.com/microsoft/hlsl-specs/issues/915).

### Version 1.9.2607

Expand Down
2 changes: 1 addition & 1 deletion lib/DXIL/DxilOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4001,7 +4001,7 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
if ((2147483649 <= op && op <= 2147483650)) {
major = 6;
minor = 10;
mask = SFLAG(Compute) | SFLAG(Mesh) | SFLAG(Amplification) | SFLAG(Node);
mask = SFLAG(Compute) | SFLAG(Mesh) | SFLAG(Amplification);
return;
}
// Instructions: ClusterID=2147483651, TriangleObjectPosition=2147483655
Expand Down
6 changes: 6 additions & 0 deletions lib/DxilValidation/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6663,6 +6663,12 @@ static void ValidateEntryProps(ValidationContext &ValCtx,

ValidateWaveSize(ValCtx, EntryProps, F);

const ShaderModel *SM = ValCtx.DxilMod.GetShaderModel();
if (Props.IsNode() && SM->IsSM610Plus())
ValCtx.EmitFnFormatError(
F, ValidationRule::SmShaderStage,
{ShaderModel::GetKindName(ShaderType), SM->GetName()});

if (ShaderType == DXIL::ShaderKind::Compute || Props.IsNode()) {
unsigned X = Props.numThreads[0];
unsigned Y = Props.numThreads[1];
Expand Down
37 changes: 37 additions & 0 deletions tools/clang/test/LitDXILValidation/node-shader-sm-6-10.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
; REQUIRES: dxil-1-10
; RUN: not %dxv %s 2>&1 | FileCheck %s

; Node shaders are not valid in shader model 6.10, even when the entry point
; contains no DXIL calls.

; CHECK: Function: Node: error: Shader stage 'node' not valid in shader model lib_6_10.
; CHECK: Validation failed.

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"

define void @Node() {
ret void
}

!llvm.ident = !{!0}
!dx.version = !{!1}
!dx.valver = !{!1}
!dx.shaderModel = !{!2}
!dx.typeAnnotations = !{!3}
!dx.entryPoints = !{!7, !9}

!0 = !{!"custom IR"}
!1 = !{i32 1, i32 10}
!2 = !{!"lib", i32 6, i32 10}
!3 = !{i32 1, void ()* @Node, !4}
!4 = !{!5}
!5 = !{i32 0, !6, !6}
!6 = !{}
!7 = !{null, !"", null, null, !8}
!8 = !{i32 0, i64 524288}
!9 = !{void ()* @Node, !"Node", null, null, !10}
!10 = !{i32 8, i32 15, i32 13, i32 1, i32 15, !11, i32 16, i32 -1, i32 4, !12, i32 5, !13}
!11 = !{!"Node", i32 0}
!12 = !{i32 1, i32 1, i32 1}
!13 = !{i32 0}
90 changes: 90 additions & 0 deletions tools/clang/test/LitDXILValidation/work-graph-opcodes-sm-6-10.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
; REQUIRES: dxil-1-10
; RUN: not %dxv %s 2>&1 | FileCheck %s

; Work graph opcodes are not valid in shader model 6.10.

; CHECK-DAG: error: Opcode AllocateNodeOutputRecords not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode GetNodeRecordPtr not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode IncrementOutputCount not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode OutputComplete not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode GetInputRecordCount not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode FinishedCrossGroupSharing not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode BarrierByNodeRecordHandle not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode CreateNodeOutputHandle not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode IndexNodeHandle not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode AnnotateNodeHandle not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode CreateNodeInputRecordHandle not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode AnnotateNodeRecordHandle not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode NodeOutputIsValid not valid in shader model lib_6_10(node).
; CHECK-DAG: error: Opcode GetRemainingRecursionLevels not valid in shader model lib_6_10(node).
; CHECK: Validation failed.

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.NodeHandle = type { i8* }
%dx.types.NodeInfo = type { i32, i32 }
%dx.types.NodeRecordHandle = type { i8* }
%dx.types.NodeRecordInfo = type { i32, i32 }
%struct.Record = type { i32 }

define void @Node() {
%output = call %dx.types.NodeHandle @dx.op.createNodeOutputHandle(i32 247, i32 0)
%indexed = call %dx.types.NodeHandle @dx.op.indexNodeHandle(i32 248, %dx.types.NodeHandle %output, i32 0)
%annotatedOutput = call %dx.types.NodeHandle @dx.op.annotateNodeHandle(i32 249, %dx.types.NodeHandle %indexed, %dx.types.NodeInfo { i32 6, i32 4 })
%outputRecord = call %dx.types.NodeRecordHandle @dx.op.allocateNodeOutputRecords(i32 238, %dx.types.NodeHandle %annotatedOutput, i32 1, i1 true)
%annotatedOutputRecord = call %dx.types.NodeRecordHandle @dx.op.annotateNodeRecordHandle(i32 251, %dx.types.NodeRecordHandle %outputRecord, %dx.types.NodeRecordInfo { i32 38, i32 4 })
%recordPtr = call %struct.Record addrspace(6)* @dx.op.getNodeRecordPtr.struct.Record(i32 239, %dx.types.NodeRecordHandle %annotatedOutputRecord, i32 0)
call void @dx.op.incrementOutputCount(i32 240, %dx.types.NodeHandle %annotatedOutput, i32 1, i1 true)
call void @dx.op.outputComplete(i32 241, %dx.types.NodeRecordHandle %annotatedOutputRecord)
%inputRecord = call %dx.types.NodeRecordHandle @dx.op.createNodeInputRecordHandle(i32 250, i32 0)
%inputCount = call i32 @dx.op.getInputRecordCount(i32 242, %dx.types.NodeRecordHandle %inputRecord)
%finished = call i1 @dx.op.finishedCrossGroupSharing(i32 243, %dx.types.NodeRecordHandle %inputRecord)
call void @dx.op.barrierByNodeRecordHandle(i32 246, %dx.types.NodeRecordHandle %inputRecord, i32 0)
%valid = call i1 @dx.op.nodeOutputIsValid(i32 252, %dx.types.NodeHandle %annotatedOutput)
%levels = call i32 @dx.op.getRemainingRecursionLevels(i32 253)
ret void
}

declare %dx.types.NodeRecordHandle @dx.op.allocateNodeOutputRecords(i32, %dx.types.NodeHandle, i32, i1)
declare %struct.Record addrspace(6)* @dx.op.getNodeRecordPtr.struct.Record(i32, %dx.types.NodeRecordHandle, i32)
declare void @dx.op.incrementOutputCount(i32, %dx.types.NodeHandle, i32, i1)
declare void @dx.op.outputComplete(i32, %dx.types.NodeRecordHandle)
declare i32 @dx.op.getInputRecordCount(i32, %dx.types.NodeRecordHandle)
declare i1 @dx.op.finishedCrossGroupSharing(i32, %dx.types.NodeRecordHandle)
declare void @dx.op.barrierByNodeRecordHandle(i32, %dx.types.NodeRecordHandle, i32)
declare %dx.types.NodeHandle @dx.op.createNodeOutputHandle(i32, i32)
declare %dx.types.NodeHandle @dx.op.indexNodeHandle(i32, %dx.types.NodeHandle, i32)
declare %dx.types.NodeHandle @dx.op.annotateNodeHandle(i32, %dx.types.NodeHandle, %dx.types.NodeInfo)
declare %dx.types.NodeRecordHandle @dx.op.createNodeInputRecordHandle(i32, i32)
declare %dx.types.NodeRecordHandle @dx.op.annotateNodeRecordHandle(i32, %dx.types.NodeRecordHandle, %dx.types.NodeRecordInfo)
declare i1 @dx.op.nodeOutputIsValid(i32, %dx.types.NodeHandle)
declare i32 @dx.op.getRemainingRecursionLevels(i32)

!llvm.ident = !{!0}
!dx.version = !{!1}
!dx.valver = !{!1}
!dx.shaderModel = !{!2}
!dx.typeAnnotations = !{!3}
!dx.entryPoints = !{!7, !9}

!0 = !{!"custom IR"}
!1 = !{i32 1, i32 10}
!2 = !{!"lib", i32 6, i32 10}
!3 = !{i32 1, void ()* @Node, !4}
!4 = !{!5}
!5 = !{i32 0, !6, !6}
!6 = !{}
!7 = !{null, !"", null, null, !8}
!8 = !{i32 0, i64 524288}
!9 = !{void ()* @Node, !"Node", null, null, !10}
!10 = !{i32 8, i32 15, i32 13, i32 3, i32 15, !11, i32 16, i32 -1, i32 20, !12, i32 21, !15, i32 4, !18, i32 5, !19}
!11 = !{!"Node", i32 0}
!12 = !{!13}
!13 = !{i32 1, i32 37, i32 2, !14}
!14 = !{i32 0, i32 4, i32 2, i32 4}
!15 = !{!16}
!16 = !{i32 1, i32 6, i32 2, !14, i32 3, i32 1, i32 0, !17}
!17 = !{!"output", i32 0}
!18 = !{i32 1, i32 1, i32 1}
!19 = !{i32 0}
12 changes: 11 additions & 1 deletion utils/hct/hctdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def __init__(self, name, **kwargs):
self.is_barrier = False # whether this is a barrier operation
self.shader_stages = () # shader stages to which this applies, empty for all.
self.shader_model = 6, 0 # minimum shader model required
self.shader_model_max = () # maximum shader model allowed, empty for no maximum
self.inst_helper_prefix = None
self.fully_qualified_name_prefix = "hlsl::OP::OpCode"
self.shader_model_translated = () # minimum shader model required with translation by linker
Expand Down Expand Up @@ -1037,6 +1038,10 @@ def populate_categories_and_models(self):
self.name_idx[i].category = "Work Graph intrinsics"
self.name_idx[i].shader_model = 6, 8
self.name_idx[i].shader_stages = ("node",)
for i in (
"AllocateNodeOutputRecords,GetNodeRecordPtr,IncrementOutputCount,OutputComplete,GetInputRecordCount,FinishedCrossGroupSharing,BarrierByNodeRecordHandle,CreateNodeOutputHandle,IndexNodeHandle,AnnotateNodeHandle,CreateNodeInputRecordHandle,AnnotateNodeRecordHandle,NodeOutputIsValid,GetRemainingRecursionLevels"
).split(","):
self.name_idx[i].shader_model_max = 6, 9
Comment on lines +1041 to +1044
# All barrier ops:
for i in "Barrier".split(","):
self.name_idx[i].category = "Synchronization"
Expand Down Expand Up @@ -1110,7 +1115,7 @@ def populate_categories_and_models_ExperimentalOps(self):
for i in insts("GetGroupWaveIndex,GetGroupWaveCount"):
i.category = "Group Wave Ops"
i.shader_model = experimental_sm
i.shader_stages = ("compute", "mesh", "amplification", "node")
i.shader_stages = ("compute", "mesh", "amplification")
i.is_wave = True

# Clustered Geometry
Expand Down Expand Up @@ -8790,6 +8795,11 @@ def build_valrules(self):
"Opcode must be defined in target shader model",
"Opcode %0 not valid in shader model %1.",
)
self.add_valrule_msg(
"Sm.ShaderStage",
"Shader stage must be supported by the target shader model",
"Shader stage '%0' not valid in shader model %1.",
)
self.add_valrule(
"Sm.Operand", "Operand must be defined in target shader model."
)
Expand Down
40 changes: 32 additions & 8 deletions utils/hct/hctdb_instrhelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1609,14 +1609,21 @@ def flush_instrs(grouped_instrs, last_model, last_model_translated, last_stage):
def get_valopcode_sm_text():
db = get_db_dxil()
instrs = sorted(
db.get_dxil_ops(), key=lambda v: (v.shader_model, v.shader_stages, v.dxil_opid)
db.get_dxil_ops(),
key=lambda v: (
v.shader_model,
v.shader_model_max,
v.shader_stages,
v.dxil_opid,
),
)
last_model = None
last_model_max = None
last_stage = None
grouped_instrs = []
code = ""

def flush_instrs(grouped_instrs, last_model, last_stage):
def flush_instrs(grouped_instrs, last_model, last_model_max, last_stage):
if len(grouped_instrs) == 0:
return ""
result = format_comment(
Expand All @@ -1631,34 +1638,51 @@ def flush_instrs(grouped_instrs, last_model, last_stage):
)
result += " return "

model_cond = stage_cond = None
model_cond = model_max_cond = stage_cond = None
if last_model != (6, 0):
model_cond = "major > %d || (major == %d && minor >= %d)" % (
last_model[0],
last_model[0],
last_model[1],
)
if last_model_max:
model_max_cond = "major < %d || (major == %d && minor <= %d)" % (
last_model_max[0],
last_model_max[0],
last_model_max[1],
)
if last_stage:
stage_cond = " || ".join(
[check_pSM_for_shader_stage[c] for c in last_stage]
)
if model_cond or stage_cond:
if model_cond or model_max_cond or stage_cond:
result += "\n && ".join(
["(%s)" % expr for expr in (model_cond, stage_cond) if expr]
[
"(%s)" % expr
for expr in (model_cond, model_max_cond, stage_cond)
if expr
]
)
return result + ";\n"
else:
# don't write these out, instead fall through
return ""

for i in instrs:
if (i.shader_model, i.shader_stages) != (last_model, last_stage):
code += flush_instrs(grouped_instrs, last_model, last_stage)
if (i.shader_model, i.shader_model_max, i.shader_stages) != (
last_model,
last_model_max,
last_stage,
):
code += flush_instrs(
grouped_instrs, last_model, last_model_max, last_stage
)
grouped_instrs = []
last_model = i.shader_model
last_model_max = i.shader_model_max
last_stage = i.shader_stages
grouped_instrs.append(i)
code += flush_instrs(grouped_instrs, last_model, last_stage)
code += flush_instrs(grouped_instrs, last_model, last_model_max, last_stage)
code += "return true;\n"
return code

Expand Down
Loading