From b1ceaabf7ab1f50c958cf2a387ab61f463513053 Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Mon, 4 May 2026 18:55:06 -0700 Subject: [PATCH 1/3] [mlir][dxsa] Add dcl_input and dcl_output instructions Example: dxsa.dcl_input %v0 dxsa.dcl_output %o0 Signed-off-by: Vladimir Shiryaev --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 37 +++++++++++++++++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 28 ++++++++++++++ mlir/test/Target/DXSA/dcl_input.mlir | 13 +++++++ mlir/test/Target/DXSA/dcl_output.mlir | 13 +++++++ mlir/test/Target/DXSA/inputs/dcl_input.bin | Bin 0 -> 20 bytes mlir/test/Target/DXSA/inputs/dcl_output.bin | Bin 0 -> 20 bytes 6 files changed, 91 insertions(+) create mode 100644 mlir/test/Target/DXSA/dcl_input.mlir create mode 100644 mlir/test/Target/DXSA/dcl_output.mlir create mode 100644 mlir/test/Target/DXSA/inputs/dcl_input.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_output.bin diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 74b850a7ed7c..c538b9224be9 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -534,4 +534,41 @@ def DXSA_DclInputPsSgv : DXSA_Op<"dcl_input_ps_sgv"> { let assemblyFormat = "$operand `,` $name attr-dict"; } +def DXSA_DclInput : DXSA_Op<"dcl_input"> { + let summary = "declares a shader input register"; + let description = [{ + The `dxsa.dcl_input` operation declares a shader input register. + + The register operand can be either an indexed input register + or a special scalar input. + + Example: + + ```mlir + + dxsa.dcl_input %v0 + ``` + }]; + let arguments = (ins DXSA_OperandType:$operand); + let assemblyFormat = "$operand attr-dict"; +} + +def DXSA_DclOutput : DXSA_Op<"dcl_output"> { + let summary = "declares a shader output register"; + let description = [{ + The `dxsa.dcl_output` operation declares a shader output register. + + The register operand can be either an indexed output register + or a special scalar output. + + Example: + + ```mlir + dxsa.dcl_output %o0 + ``` + }]; + let arguments = (ins DXSA_OperandType:$operand); + let assemblyFormat = "$operand attr-dict"; +} + #endif // DXSA_OPS diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index c45a616a5648..406ff57af913 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -597,6 +597,14 @@ class DXBuilder { systemValueNameAttr); } + Instruction buildDclInput(Operand operand, Location loc) { + return dxsa::DclInput::create(builder, loc, operand); + } + + Instruction buildDclOutput(Operand operand, Location loc) { + return dxsa::DclOutput::create(builder, loc, operand); + } + private: MLIRContext *context; ModuleOp module; @@ -1076,6 +1084,20 @@ class Parser { return builder.buildDclInputPsSgv(*operand, *systemValueName, loc); } + FailureOr parseDclInput(Location loc) { + auto operand = parseOperand(); + if (failed(operand)) + return failure(); + return builder.buildDclInput(*operand, loc); + } + + FailureOr parseDclOutput(Location loc) { + auto operand = parseOperand(); + if (failed(operand)) + return failure(); + return builder.buildDclOutput(*operand, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -1116,6 +1138,12 @@ class Parser { case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV: result = parseDclInputPsSgv(loc); break; + case D3D10_SB_OPCODE_DCL_INPUT: + result = parseDclInput(loc); + break; + case D3D10_SB_OPCODE_DCL_OUTPUT: + result = parseDclOutput(loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_input.mlir b/mlir/test/Target/DXSA/dcl_input.mlir new file mode 100644 index 000000000000..34e238bc8fc4 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_input.mlir @@ -0,0 +1,13 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_input.bin | FileCheck %s + +// CHECK-LABEL: module +module { + // dcl_input v0.x + // CHECK: %0 = dxsa.index.imm {imm = 0 : i32} + // CHECK-NEXT: %1 = dxsa.operand %0 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} + // CHECK-NEXT: dxsa.dcl_input %1 + + // dcl_input vOutputControlPointID + // CHECK-NEXT: %2 = dxsa.operand {num_components = 1 : i32, type = 22 : i32} + // CHECK-NEXT: dxsa.dcl_input %2 +} diff --git a/mlir/test/Target/DXSA/dcl_output.mlir b/mlir/test/Target/DXSA/dcl_output.mlir new file mode 100644 index 000000000000..6825a9af7de8 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_output.mlir @@ -0,0 +1,13 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_output.bin | FileCheck %s + +// CHECK-LABEL: module +module { + // dcl_output o0.xyzw + // CHECK: %0 = dxsa.index.imm {imm = 0 : i32} + // CHECK-NEXT: %1 = dxsa.operand %0 {mask = 240 : i32, num_components = 4 : i32, type = 2 : i32} + // CHECK-NEXT: dxsa.dcl_output %1 + + // dcl_output oDepth + // CHECK-NEXT: %2 = dxsa.operand {num_components = 1 : i32, type = 12 : i32} + // CHECK-NEXT: dxsa.dcl_output %2 +} diff --git a/mlir/test/Target/DXSA/inputs/dcl_input.bin b/mlir/test/Target/DXSA/inputs/dcl_input.bin new file mode 100644 index 0000000000000000000000000000000000000000..8313032954325faa5588278cb926b415c64ff825 GIT binary patch literal 20 Ycma!NU|<#!5MTg-cm@V0#so$N01nFmSO5S3 literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_output.bin b/mlir/test/Target/DXSA/inputs/dcl_output.bin new file mode 100644 index 0000000000000000000000000000000000000000..2757d4b80f656d7fbd45bd0e6511d0d2b31d2a07 GIT binary patch literal 20 YcmYdgU|{~FAiw|usSFHEj0YGP03U$@vj6}9 literal 0 HcmV?d00001 From bae2b2ce402ff65b5190bfd9aa5fada4c6d17069 Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Sun, 17 May 2026 09:20:43 -0700 Subject: [PATCH 2/3] [mlir][dxsa] Refine dcl_input and dcl_output instructions Encode the operand as an inline attribute instead of separate SSA values. Example: dxsa.dcl_input , index = [0]> dxsa.dcl_output , index = [0]> Signed-off-by: Vladimir Shiryaev --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 158 ++++++++++++++++++- mlir/lib/Target/DXSA/BinaryParser.cpp | 92 ++++++++++- mlir/test/Target/DXSA/dcl_input.mlir | 7 +- mlir/test/Target/DXSA/dcl_output.mlir | 7 +- 4 files changed, 241 insertions(+), 23 deletions(-) diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index c538b9224be9..ed5a295a38db 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -11,6 +11,8 @@ include "mlir/Dialect/DXSA/IR/DXSADialect.td" include "mlir/Dialect/DXSA/IR/DXSATypes.td" +include "mlir/IR/AttrTypeBase.td" +include "mlir/IR/BuiltinAttributeInterfaces.td" include "mlir/IR/EnumAttr.td" //===----------------------------------------------------------------------===// @@ -253,6 +255,32 @@ def DXSA_SystemValueNameAttr : let assemblyFormat = "$value"; } +//===----------------------------------------------------------------------===// +// DXSA ComponentMask bit-enum (mask field of operand, normalized to bits 0..3) +//===----------------------------------------------------------------------===// + +def DXSA_ComponentMask_X : I32BitEnumAttrCaseBit<"x", 0>; +def DXSA_ComponentMask_Y : I32BitEnumAttrCaseBit<"y", 1>; +def DXSA_ComponentMask_Z : I32BitEnumAttrCaseBit<"z", 2>; +def DXSA_ComponentMask_W : I32BitEnumAttrCaseBit<"w", 3>; + +def DXSA_ComponentMask : I32BitEnumAttr< + "ComponentMask", "component mask (subset of x, y, z, w)", [ + DXSA_ComponentMask_X, + DXSA_ComponentMask_Y, + DXSA_ComponentMask_Z, + DXSA_ComponentMask_W + ]> { + let separator = ", "; + let cppNamespace = "::mlir::dxsa"; + let genSpecializedAttr = 0; +} + +def DXSA_ComponentMaskAttr : + EnumAttr { + let assemblyFormat = "`<` $value `>`"; +} + //===----------------------------------------------------------------------===// // DXSA op definitions //===----------------------------------------------------------------------===// @@ -335,6 +363,127 @@ def DXSA_Instruction : DXSA_Op<"instruction"> { let assemblyFormat = "$mnemonic $operands attr-dict"; } +def DXSA_InlineOperandType_Temp : I32EnumAttrCase<"temp", 0>; +def DXSA_InlineOperandType_Input : I32EnumAttrCase<"input", 1>; +def DXSA_InlineOperandType_Output : I32EnumAttrCase<"output", 2>; +def DXSA_InlineOperandType_IndexableTemp : I32EnumAttrCase<"indexable_temp", 3>; +def DXSA_InlineOperandType_Immediate32 : I32EnumAttrCase<"immediate32", 4>; +def DXSA_InlineOperandType_Immediate64 : I32EnumAttrCase<"immediate64", 5>; +def DXSA_InlineOperandType_Sampler : I32EnumAttrCase<"sampler", 6>; +def DXSA_InlineOperandType_Resource : I32EnumAttrCase<"resource", 7>; +def DXSA_InlineOperandType_ConstantBuffer : I32EnumAttrCase<"constant_buffer", 8>; +def DXSA_InlineOperandType_ImmediateConstantBuffer : I32EnumAttrCase<"immediate_constant_buffer", 9>; +def DXSA_InlineOperandType_Label : I32EnumAttrCase<"label", 10>; +def DXSA_InlineOperandType_InputPrimitiveId : I32EnumAttrCase<"input_primitive_id", 11>; +def DXSA_InlineOperandType_OutputDepth : I32EnumAttrCase<"output_depth", 12>; +def DXSA_InlineOperandType_Null : I32EnumAttrCase<"null", 13>; +def DXSA_InlineOperandType_Rasterizer : I32EnumAttrCase<"rasterizer", 14>; +def DXSA_InlineOperandType_OutputCoverageMask : I32EnumAttrCase<"output_coverage_mask", 15>; +def DXSA_InlineOperandType_Stream : I32EnumAttrCase<"stream", 16>; +def DXSA_InlineOperandType_FunctionBody : I32EnumAttrCase<"function_body", 17>; +def DXSA_InlineOperandType_FunctionTable : I32EnumAttrCase<"function_table", 18>; +def DXSA_InlineOperandType_Interface : I32EnumAttrCase<"interface", 19>; +def DXSA_InlineOperandType_FunctionInput : I32EnumAttrCase<"function_input", 20>; +def DXSA_InlineOperandType_FunctionOutput : I32EnumAttrCase<"function_output", 21>; +def DXSA_InlineOperandType_OutputControlPointId : I32EnumAttrCase<"output_control_point_id", 22>; +def DXSA_InlineOperandType_InputForkInstanceId : I32EnumAttrCase<"input_fork_instance_id", 23>; +def DXSA_InlineOperandType_InputJoinInstanceId : I32EnumAttrCase<"input_join_instance_id", 24>; +def DXSA_InlineOperandType_InputControlPoint : I32EnumAttrCase<"input_control_point", 25>; +def DXSA_InlineOperandType_OutputControlPoint : I32EnumAttrCase<"output_control_point", 26>; +def DXSA_InlineOperandType_InputPatchConstant : I32EnumAttrCase<"input_patch_constant", 27>; +def DXSA_InlineOperandType_InputDomainPoint : I32EnumAttrCase<"input_domain_point", 28>; +def DXSA_InlineOperandType_ThisPointer : I32EnumAttrCase<"this_pointer", 29>; +def DXSA_InlineOperandType_Uav : I32EnumAttrCase<"uav", 30>; +def DXSA_InlineOperandType_ThreadGroupSharedMemory : I32EnumAttrCase<"thread_group_shared_memory", 31>; +def DXSA_InlineOperandType_InputThreadId : I32EnumAttrCase<"input_thread_id", 32>; +def DXSA_InlineOperandType_InputThreadGroupId : I32EnumAttrCase<"input_thread_group_id", 33>; +def DXSA_InlineOperandType_InputThreadIdInGroup : I32EnumAttrCase<"input_thread_id_in_group", 34>; +def DXSA_InlineOperandType_InputCoverageMask : I32EnumAttrCase<"input_coverage_mask", 35>; +def DXSA_InlineOperandType_InputThreadIdInGroupFlattened : I32EnumAttrCase<"input_thread_id_in_group_flattened", 36>; +def DXSA_InlineOperandType_InputGsInstanceId : I32EnumAttrCase<"input_gs_instance_id", 37>; +def DXSA_InlineOperandType_OutputDepthGe : I32EnumAttrCase<"output_depth_ge", 38>; +def DXSA_InlineOperandType_OutputDepthLe : I32EnumAttrCase<"output_depth_le", 39>; +def DXSA_InlineOperandType_CycleCounter : I32EnumAttrCase<"cycle_counter", 40>; +def DXSA_InlineOperandType_OutputStencilRef : I32EnumAttrCase<"output_stencil_ref", 41>; +def DXSA_InlineOperandType_InnerCoverage : I32EnumAttrCase<"inner_coverage", 42>; + +def DXSA_InlineOperandType : I32EnumAttr< + "InlineOperandType", "operand type", [ + DXSA_InlineOperandType_Temp, + DXSA_InlineOperandType_Input, + DXSA_InlineOperandType_Output, + DXSA_InlineOperandType_IndexableTemp, + DXSA_InlineOperandType_Immediate32, + DXSA_InlineOperandType_Immediate64, + DXSA_InlineOperandType_Sampler, + DXSA_InlineOperandType_Resource, + DXSA_InlineOperandType_ConstantBuffer, + DXSA_InlineOperandType_ImmediateConstantBuffer, + DXSA_InlineOperandType_Label, + DXSA_InlineOperandType_InputPrimitiveId, + DXSA_InlineOperandType_OutputDepth, + DXSA_InlineOperandType_Null, + DXSA_InlineOperandType_Rasterizer, + DXSA_InlineOperandType_OutputCoverageMask, + DXSA_InlineOperandType_Stream, + DXSA_InlineOperandType_FunctionBody, + DXSA_InlineOperandType_FunctionTable, + DXSA_InlineOperandType_Interface, + DXSA_InlineOperandType_FunctionInput, + DXSA_InlineOperandType_FunctionOutput, + DXSA_InlineOperandType_OutputControlPointId, + DXSA_InlineOperandType_InputForkInstanceId, + DXSA_InlineOperandType_InputJoinInstanceId, + DXSA_InlineOperandType_InputControlPoint, + DXSA_InlineOperandType_OutputControlPoint, + DXSA_InlineOperandType_InputPatchConstant, + DXSA_InlineOperandType_InputDomainPoint, + DXSA_InlineOperandType_ThisPointer, + DXSA_InlineOperandType_Uav, + DXSA_InlineOperandType_ThreadGroupSharedMemory, + DXSA_InlineOperandType_InputThreadId, + DXSA_InlineOperandType_InputThreadGroupId, + DXSA_InlineOperandType_InputThreadIdInGroup, + DXSA_InlineOperandType_InputCoverageMask, + DXSA_InlineOperandType_InputThreadIdInGroupFlattened, + DXSA_InlineOperandType_InputGsInstanceId, + DXSA_InlineOperandType_OutputDepthGe, + DXSA_InlineOperandType_OutputDepthLe, + DXSA_InlineOperandType_CycleCounter, + DXSA_InlineOperandType_OutputStencilRef, + DXSA_InlineOperandType_InnerCoverage + ]> { + let cppNamespace = "::mlir::dxsa"; + let genSpecializedAttr = 0; +} + +def DXSA_InlineOperandAttr : AttrDef { + let mnemonic = "inline_operand"; + let summary = "inline operand of an instruction"; + let description = [{ + The `#dxsa.inline_operand` attribute carries a fully decoded operand token + + Example: + + ```mlir + dxsa.dcl_output , index = [0]> + dxsa.dcl_output + ``` + }]; + let parameters = (ins + EnumParameter:$type, + "uint32_t":$components, + OptionalParameter<"::mlir::dxsa::ComponentMaskAttr">:$mask, + OptionalParameter<"::mlir::DenseI64ArrayAttr">:$index); + let assemblyFormat = [{ + `<` `type` `=` $type + `,` `components` `=` $components + (`,` `mask` `=` $mask^)? + (`,` `index` `=` $index^)? + `>` + }]; +} + def DXSA_DclGlobalFlags : DXSA_Op<"dcl_global_flags"> { let summary = "declares global shader flags"; let description = [{ @@ -545,11 +694,10 @@ def DXSA_DclInput : DXSA_Op<"dcl_input"> { Example: ```mlir - - dxsa.dcl_input %v0 + dxsa.dcl_input , index = [0]> ``` }]; - let arguments = (ins DXSA_OperandType:$operand); + let arguments = (ins DXSA_InlineOperandAttr:$operand); let assemblyFormat = "$operand attr-dict"; } @@ -564,10 +712,10 @@ def DXSA_DclOutput : DXSA_Op<"dcl_output"> { Example: ```mlir - dxsa.dcl_output %o0 + dxsa.dcl_output , index = [0]> ``` }]; - let arguments = (ins DXSA_OperandType:$operand); + let arguments = (ins DXSA_InlineOperandAttr:$operand); let assemblyFormat = "$operand attr-dict"; } diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 406ff57af913..f1c860c758a2 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -30,6 +30,10 @@ using UINT = unsigned int; using namespace mlir; using namespace llvm; +#define FAILURE_IF_FAILED(RES) \ + if (failed(RES)) \ + return failure(); + enum OpcodeClass { D3D10_SB_FLOAT_OP, D3D10_SB_INT_OP, @@ -400,6 +404,19 @@ struct OperandComponents { }; }; +static dxsa::ComponentMask decodeComponentMask(uint32_t rawComponentMask) { + auto componentMask = static_cast(0); + if (rawComponentMask & D3D10_SB_OPERAND_4_COMPONENT_MASK_X) + componentMask |= dxsa::ComponentMask::x; + if (rawComponentMask & D3D10_SB_OPERAND_4_COMPONENT_MASK_Y) + componentMask |= dxsa::ComponentMask::y; + if (rawComponentMask & D3D10_SB_OPERAND_4_COMPONENT_MASK_Z) + componentMask |= dxsa::ComponentMask::z; + if (rawComponentMask & D3D10_SB_OPERAND_4_COMPONENT_MASK_W) + componentMask |= dxsa::ComponentMask::w; + return componentMask; +} + class DXBuilder { public: DXBuilder(MLIRContext *context, StringAttr name) @@ -597,11 +614,24 @@ class DXBuilder { systemValueNameAttr); } - Instruction buildDclInput(Operand operand, Location loc) { + dxsa::InlineOperandAttr buildInlineOperandAttr( + dxsa::InlineOperandType operandType, uint32_t components, + std::optional mask, ArrayRef indexArray) { + auto *ctx = builder.getContext(); + auto maskAttr = mask ? dxsa::ComponentMaskAttr::get(ctx, *mask) + : dxsa::ComponentMaskAttr(); + auto indexAttr = indexArray.empty() + ? DenseI64ArrayAttr() + : DenseI64ArrayAttr::get(ctx, indexArray); + return dxsa::InlineOperandAttr::get(ctx, operandType, components, maskAttr, + indexAttr); + } + + Instruction buildDclInput(dxsa::InlineOperandAttr operand, Location loc) { return dxsa::DclInput::create(builder, loc, operand); } - Instruction buildDclOutput(Operand operand, Location loc) { + Instruction buildDclOutput(dxsa::InlineOperandAttr operand, Location loc) { return dxsa::DclOutput::create(builder, loc, operand); } @@ -1084,17 +1114,63 @@ class Parser { return builder.buildDclInputPsSgv(*operand, *systemValueName, loc); } + FailureOr parseInlineOperand() { + auto token = parseToken(); + FAILURE_IF_FAILED(token); + + auto rawOperandType = DECODE_D3D10_SB_OPERAND_TYPE(*token); + auto isExtended = DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*token); + auto loc = getLocation(); + + if (isImmOperand(*token)) + return emitError(loc, "immediate operand is not supported yet"); + + auto type = dxsa::symbolizeInlineOperandType(rawOperandType); + if (!type) + return emitError(loc, "unknown operand type: ") << rawOperandType; + + auto components = parseOperandComponents(*token); + FAILURE_IF_FAILED(components); + + auto indexTypes = parseOperandIndexTypes(*token); + FAILURE_IF_FAILED(indexTypes); + + if (isExtended) + return emitError(loc, "extended operand tokens are not yet supported in " + "inline operand attribute"); + + if (components->kind == OperandComponentsKind::Swizzle || + components->kind == OperandComponentsKind::One) + return emitError(loc, "swizzled / single-component operand selection is " + "not supported in inline operand attribute"); + + std::optional mask; + if (components->kind == OperandComponentsKind::Mask) + mask = decodeComponentMask(components->mask); + + SmallVector indices; + for (auto indexType : *indexTypes) { + if (indexType != D3D10_SB_OPERAND_INDEX_IMMEDIATE32) + return emitError(getLocation(), "unsupported index representation: ") + << indexType; + auto value = parseToken(); + FAILURE_IF_FAILED(value); + indices.push_back(static_cast(*value)); + } + + return builder.buildInlineOperandAttr(*type, components->num, mask, + indices); + } + FailureOr parseDclInput(Location loc) { - auto operand = parseOperand(); - if (failed(operand)) - return failure(); + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); return builder.buildDclInput(*operand, loc); } FailureOr parseDclOutput(Location loc) { - auto operand = parseOperand(); - if (failed(operand)) - return failure(); + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); return builder.buildDclOutput(*operand, loc); } diff --git a/mlir/test/Target/DXSA/dcl_input.mlir b/mlir/test/Target/DXSA/dcl_input.mlir index 34e238bc8fc4..4f42d4c31c14 100644 --- a/mlir/test/Target/DXSA/dcl_input.mlir +++ b/mlir/test/Target/DXSA/dcl_input.mlir @@ -3,11 +3,8 @@ // CHECK-LABEL: module module { // dcl_input v0.x - // CHECK: %0 = dxsa.index.imm {imm = 0 : i32} - // CHECK-NEXT: %1 = dxsa.operand %0 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input %1 + // CHECK: dxsa.dcl_input , index = [0]> // dcl_input vOutputControlPointID - // CHECK-NEXT: %2 = dxsa.operand {num_components = 1 : i32, type = 22 : i32} - // CHECK-NEXT: dxsa.dcl_input %2 + // CHECK-NEXT: dxsa.dcl_input } diff --git a/mlir/test/Target/DXSA/dcl_output.mlir b/mlir/test/Target/DXSA/dcl_output.mlir index 6825a9af7de8..6c5ff0eb0e59 100644 --- a/mlir/test/Target/DXSA/dcl_output.mlir +++ b/mlir/test/Target/DXSA/dcl_output.mlir @@ -3,11 +3,8 @@ // CHECK-LABEL: module module { // dcl_output o0.xyzw - // CHECK: %0 = dxsa.index.imm {imm = 0 : i32} - // CHECK-NEXT: %1 = dxsa.operand %0 {mask = 240 : i32, num_components = 4 : i32, type = 2 : i32} - // CHECK-NEXT: dxsa.dcl_output %1 + // CHECK: dxsa.dcl_output , index = [0]> // dcl_output oDepth - // CHECK-NEXT: %2 = dxsa.operand {num_components = 1 : i32, type = 12 : i32} - // CHECK-NEXT: dxsa.dcl_output %2 + // CHECK-NEXT: dxsa.dcl_output } From f593309f20a9274818109f3b42714e8837cc37bf Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Wed, 20 May 2026 17:01:48 -0700 Subject: [PATCH 3/3] [mlir][dxsa] Add dcl_constant_buffer, dcl_hs_fork_phase_instance_count, dcl_hs_join_phase_instance_count, dcl_hs_max_tessfactor, dcl_index_range, dcl_output_sgv, dcl_output_siv and dcl_tgsm_raw instructions Example: dxsa.dcl_constant_buffer , index = [0, 1]>, dxsa.dcl_hs_fork_phase_instance_count 4 dxsa.dcl_hs_join_phase_instance_count 2 dxsa.dcl_hs_max_tessfactor 6.400000e+01 dxsa.dcl_index_range , index = [4]>, 6 dxsa.dcl_output_sgv , index = [0]>, dxsa.dcl_output_siv , index = [0]>, dxsa.dcl_tgsm_raw , 1024 Signed-off-by: Vladimir Shiryaev --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 222 +++++++++++++++++- mlir/lib/Dialect/DXSA/IR/DXSA.cpp | 46 ++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 198 ++++++++++++++-- .../test/Target/DXSA/dcl_constant_buffer.mlir | 6 + .../dcl_hs_fork_phase_instance_count.mlir | 5 + .../dcl_hs_join_phase_instance_count.mlir | 5 + .../Target/DXSA/dcl_hs_max_tessfactor.mlir | 5 + .../DXSA/dcl_hs_max_tessfactor_invalid.mlir | 29 +++ mlir/test/Target/DXSA/dcl_index_range.mlir | 7 + mlir/test/Target/DXSA/dcl_input_ps_sgv.mlir | 6 +- mlir/test/Target/DXSA/dcl_input_ps_siv.mlir | 10 +- mlir/test/Target/DXSA/dcl_output_sgv.mlir | 7 + mlir/test/Target/DXSA/dcl_output_siv.mlir | 11 + mlir/test/Target/DXSA/dcl_tgsm_raw.mlir | 7 + .../Target/DXSA/dcl_tgsm_raw_invalid.mlir | 14 ++ .../Target/DXSA/inline_operand_invalid.mlir | 19 ++ .../Target/DXSA/inline_operand_roundtrip.mlir | 13 + .../DXSA/inputs/dcl_constant_buffer.bin | Bin 0 -> 32 bytes .../dcl_hs_fork_phase_instance_count.bin | Bin 0 -> 8 bytes .../dcl_hs_join_phase_instance_count.bin | Bin 0 -> 8 bytes .../DXSA/inputs/dcl_hs_max_tessfactor.bin | Bin 0 -> 8 bytes .../Target/DXSA/inputs/dcl_index_range.bin | Bin 0 -> 48 bytes .../Target/DXSA/inputs/dcl_output_sgv.bin | Bin 0 -> 48 bytes .../Target/DXSA/inputs/dcl_output_siv.bin | Bin 0 -> 112 bytes mlir/test/Target/DXSA/inputs/dcl_tgsm_raw.bin | Bin 0 -> 48 bytes 25 files changed, 568 insertions(+), 42 deletions(-) create mode 100644 mlir/test/Target/DXSA/dcl_constant_buffer.mlir create mode 100644 mlir/test/Target/DXSA/dcl_hs_fork_phase_instance_count.mlir create mode 100644 mlir/test/Target/DXSA/dcl_hs_join_phase_instance_count.mlir create mode 100644 mlir/test/Target/DXSA/dcl_hs_max_tessfactor.mlir create mode 100644 mlir/test/Target/DXSA/dcl_hs_max_tessfactor_invalid.mlir create mode 100644 mlir/test/Target/DXSA/dcl_index_range.mlir create mode 100644 mlir/test/Target/DXSA/dcl_output_sgv.mlir create mode 100644 mlir/test/Target/DXSA/dcl_output_siv.mlir create mode 100644 mlir/test/Target/DXSA/dcl_tgsm_raw.mlir create mode 100644 mlir/test/Target/DXSA/dcl_tgsm_raw_invalid.mlir create mode 100644 mlir/test/Target/DXSA/inline_operand_invalid.mlir create mode 100644 mlir/test/Target/DXSA/inline_operand_roundtrip.mlir create mode 100644 mlir/test/Target/DXSA/inputs/dcl_constant_buffer.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_hs_fork_phase_instance_count.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_hs_join_phase_instance_count.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_hs_max_tessfactor.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_index_range.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_output_sgv.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_output_siv.bin create mode 100644 mlir/test/Target/DXSA/inputs/dcl_tgsm_raw.bin diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index ed5a295a38db..fd43eefe605f 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -252,7 +252,7 @@ def DXSA_SystemValueName : I32EnumAttr< def DXSA_SystemValueNameAttr : EnumAttr { - let assemblyFormat = "$value"; + let assemblyFormat = "`<` $value `>`"; } //===----------------------------------------------------------------------===// @@ -281,6 +281,65 @@ def DXSA_ComponentMaskAttr : let assemblyFormat = "`<` $value `>`"; } +//===----------------------------------------------------------------------===// +// DXSA ComponentName enum (distinct from ComponentMask which is a bit mask) +//===----------------------------------------------------------------------===// + +def DXSA_ComponentName_X : I32EnumAttrCase<"x", 0>; +def DXSA_ComponentName_Y : I32EnumAttrCase<"y", 1>; +def DXSA_ComponentName_Z : I32EnumAttrCase<"z", 2>; +def DXSA_ComponentName_W : I32EnumAttrCase<"w", 3>; + +def DXSA_ComponentName : I32EnumAttr< + "ComponentName", "single x/y/z/w component", [ + DXSA_ComponentName_X, + DXSA_ComponentName_Y, + DXSA_ComponentName_Z, + DXSA_ComponentName_W + ]> { + let cppNamespace = "::mlir::dxsa"; + let genSpecializedAttr = 0; +} + +def DXSA_ComponentNameAttr : + EnumAttr { + let assemblyFormat = "`<` $value `>`"; +} + +//===----------------------------------------------------------------------===// +// DXSA ComponentSwizzle attribute — ordered component mapping +// (each component picks one of x/y/z/w from the source, components may repeat) +//===----------------------------------------------------------------------===// + +def DXSA_ComponentSwizzleAttr : AttrDef { + let mnemonic = "component_swizzle"; + let summary = "component swizzle (each component picks one of x, y, z, w)"; + let parameters = (ins + EnumParameter:$x, + EnumParameter:$y, + EnumParameter:$z, + EnumParameter:$w); + let assemblyFormat = "`<` $x `,` $y `,` $z `,` $w `>`"; +} + +def DXSA_ConstantBufferAccessPattern_ImmediateIndexed : I32EnumAttrCase<"immediateIndexed", 0>; +def DXSA_ConstantBufferAccessPattern_DynamicIndexed : I32EnumAttrCase<"dynamicIndexed", 1>; + +def DXSA_ConstantBufferAccessPattern : I32EnumAttr< + "ConstantBufferAccessPattern", "constant buffer access pattern", [ + DXSA_ConstantBufferAccessPattern_ImmediateIndexed, + DXSA_ConstantBufferAccessPattern_DynamicIndexed + ]> { + let cppNamespace = "::mlir::dxsa"; + let genSpecializedAttr = 0; +} + +def DXSA_ConstantBufferAccessPatternAttr : + EnumAttr { + let assemblyFormat = "`<` $value `>`"; +} + //===----------------------------------------------------------------------===// // DXSA op definitions //===----------------------------------------------------------------------===// @@ -461,12 +520,13 @@ def DXSA_InlineOperandAttr : AttrDef { let mnemonic = "inline_operand"; let summary = "inline operand of an instruction"; let description = [{ - The `#dxsa.inline_operand` attribute carries a fully decoded operand token + The `#dxsa.inline_operand` attribute carries a fully decoded operand token. - Example: + Examples: ```mlir dxsa.dcl_output , index = [0]> + dxsa.dcl_constant_buffer , index = [0, 1]>, dxsa.dcl_output ``` }]; @@ -474,14 +534,11 @@ def DXSA_InlineOperandAttr : AttrDef { EnumParameter:$type, "uint32_t":$components, OptionalParameter<"::mlir::dxsa::ComponentMaskAttr">:$mask, + OptionalParameter<"::mlir::dxsa::ComponentSwizzleAttr">:$swizzle, + OptionalParameter<"::mlir::dxsa::ComponentNameAttr">:$select, OptionalParameter<"::mlir::DenseI64ArrayAttr">:$index); - let assemblyFormat = [{ - `<` `type` `=` $type - `,` `components` `=` $components - (`,` `mask` `=` $mask^)? - (`,` `index` `=` $index^)? - `>` - }]; + let assemblyFormat = "`<` struct(params) `>`"; + let genVerifyDecl = 1; } def DXSA_DclGlobalFlags : DXSA_Op<"dcl_global_flags"> { @@ -657,7 +714,7 @@ def DXSA_DclInputPsSiv : DXSA_Op<"dcl_input_ps_siv"> { Example: ```mlir - dxsa.dcl_input_ps_siv linear %v0, position + dxsa.dcl_input_ps_siv linear %v0, ``` }]; let arguments = (ins DXSA_InterpolationModeAttr:$mode, @@ -675,7 +732,7 @@ def DXSA_DclInputPsSgv : DXSA_Op<"dcl_input_ps_sgv"> { Example: ```mlir - dxsa.dcl_input_ps_sgv %v0, sampleIndex + dxsa.dcl_input_ps_sgv %v0, ``` }]; let arguments = (ins DXSA_OperandType:$operand, @@ -719,4 +776,145 @@ def DXSA_DclOutput : DXSA_Op<"dcl_output"> { let assemblyFormat = "$operand attr-dict"; } +def DXSA_DclOutputSiv : DXSA_Op<"dcl_output_siv"> { + let summary = "declares a shader output carrying a System Interpreted Value"; + let description = [{ + The `dxsa.dcl_output_siv` operation declares an output register that + represents a System Interpreted Value (e.g. `position`, `clipDistance`). + + Example: + + ```mlir + dxsa.dcl_output_siv , index = [3]>, + ``` + }]; + let arguments = (ins DXSA_InlineOperandAttr:$operand, + DXSA_SystemValueNameAttr:$name); + let assemblyFormat = "$operand `,` $name attr-dict"; +} + +def DXSA_DclConstantBuffer : DXSA_Op<"dcl_constant_buffer"> { + let summary = "declares a constant buffer"; + let description = [{ + The `dxsa.dcl_constant_buffer` operation declares a constant buffer + together with its access pattern. + + Example: + + ```mlir + dxsa.dcl_constant_buffer , index = [3, 128]>, + ``` + }]; + let arguments = (ins DXSA_InlineOperandAttr:$operand, + DXSA_ConstantBufferAccessPatternAttr:$access_pattern); + let assemblyFormat = "$operand `,` $access_pattern attr-dict"; +} + +def DXSA_DclHsMaxTessfactor : DXSA_Op<"dcl_hs_max_tessfactor"> { + let summary = "declares the maximum tessellation factor for a hull shader"; + let description = [{ + The `dxsa.dcl_hs_max_tessfactor` operation declares the maximum + tessellation factor produced by the hull shader as a 32-bit float. + + Example: + + ```mlir + dxsa.dcl_hs_max_tessfactor 6.400000e+01 + ``` + }]; + let arguments = (ins F32Attr:$max_tess_factor); + let assemblyFormat = "$max_tess_factor attr-dict"; + let hasVerifier = 1; +} + +def DXSA_DclHsForkPhaseInstanceCount : + DXSA_Op<"dcl_hs_fork_phase_instance_count"> { + let summary = "declares the hull shader fork phase instance count"; + let description = [{ + The `dxsa.dcl_hs_fork_phase_instance_count` operation declares the + number of instances of the current hull shader fork phase program + to execute. + + Example: + + ```mlir + dxsa.dcl_hs_fork_phase_instance_count 4 + ``` + }]; + let arguments = (ins ConfinedAttr:$count); + let assemblyFormat = "$count attr-dict"; +} + +def DXSA_DclHsJoinPhaseInstanceCount : + DXSA_Op<"dcl_hs_join_phase_instance_count"> { + let summary = "declares the hull shader join phase instance count"; + let description = [{ + The `dxsa.dcl_hs_join_phase_instance_count` operation declares the + number of instances of the current hull shader join phase program + to execute. + + Example: + + ```mlir + dxsa.dcl_hs_join_phase_instance_count 2 + ``` + }]; + let arguments = (ins ConfinedAttr:$count); + let assemblyFormat = "$count attr-dict"; +} + +def DXSA_DclIndexRange : DXSA_Op<"dcl_index_range"> { + let summary = "declares a range of input/output registers to be indexed"; + let description = [{ + The `dxsa.dcl_index_range` operation declares a range of contiguous + input or output registers that may be referenced by dynamic indexing + in shader code. + + Example: + + ```mlir + dxsa.dcl_index_range , index = [1]>, 3 + ``` + }]; + let arguments = (ins DXSA_InlineOperandAttr:$operand, + ConfinedAttr:$count); + let assemblyFormat = "$operand `,` $count attr-dict"; +} + +def DXSA_DclTgsmRaw : DXSA_Op<"dcl_tgsm_raw"> { + let summary = "declares raw thread group shared memory"; + let description = [{ + The `dxsa.dcl_tgsm_raw` operation declares a region of untyped thread + group shared memory of the given byte count. + + Example: + + ```mlir + dxsa.dcl_tgsm_raw , 1024 + ``` + }]; + let arguments = (ins DXSA_InlineOperandAttr:$operand, + ConfinedAttr]>:$byte_count); + let assemblyFormat = "$operand `,` $byte_count attr-dict"; + let hasVerifier = 1; +} + +def DXSA_DclOutputSgv : DXSA_Op<"dcl_output_sgv"> { + let summary = "declares a shader output carrying a System Generated Value"; + let description = [{ + The `dxsa.dcl_output_sgv` operation declares an output register that + represents a System Generated Value. + + Example: + + ```mlir + dxsa.dcl_output_sgv , index = [4]>, + ``` + }]; + let arguments = (ins DXSA_InlineOperandAttr:$operand, + DXSA_SystemValueNameAttr:$name); + let assemblyFormat = "$operand `,` $name attr-dict"; +} + #endif // DXSA_OPS diff --git a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp index e5c94051e3a5..1478d2ee1168 100644 --- a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp +++ b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp @@ -41,6 +41,52 @@ void DXSADialect::initialize() { #define GET_OP_CLASSES #include "mlir/Dialect/DXSA/IR/DXSAOps.cpp.inc" +//===----------------------------------------------------------------------===// +// Op verifiers +//===----------------------------------------------------------------------===// + +LogicalResult DclTgsmRaw::verify() { + auto byteCount = getByteCount(); + if (byteCount % 4 != 0) + return emitOpError("byte count must be a multiple of 4, got ") << byteCount; + return success(); +} + +LogicalResult DclHsMaxTessfactor::verify() { + // Reject NaN, Inf, and anything outside [1.0, 64.0]. + auto value = getMaxTessFactorAttr().getValue(); + if (!value.isFinite() || value < llvm::APFloat(1.0f) || + value > llvm::APFloat(64.0f)) + return emitOpError("max tessellation factor must be in [1.0, 64.0], got ") + << value.convertToFloat(); + return success(); +} + +//===----------------------------------------------------------------------===// +// Attribute verifiers +//===----------------------------------------------------------------------===// + +LogicalResult +InlineOperandAttr::verify(function_ref emitError, + ::mlir::dxsa::InlineOperandType /*type*/, + uint32_t components, + ::mlir::dxsa::ComponentMaskAttr mask, + ::mlir::dxsa::ComponentSwizzleAttr swizzle, + ::mlir::dxsa::ComponentNameAttr select, + ::mlir::DenseI64ArrayAttr /*index*/) { + // mask / swizzle / select are the three mutually-exclusive 4-component + // selection modes. Operands with 0 or 1 components carry none of them. + auto set = (mask ? 1 : 0) + (swizzle ? 1 : 0) + (select ? 1 : 0); + if (set > 1) + return emitError() << "at most one of 'mask', 'swizzle', 'select' may " + "be set on an operand"; + if (components != 4 && set != 0) + return emitError() << "component selection mode is only valid on a " + "4-component operand, got " + << components << " components"; + return success(); +} + //===----------------------------------------------------------------------===// // TableGen'd attribute method definitions //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index f1c860c758a2..418b32b431e4 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -12,6 +12,7 @@ #include "mlir/IR/Location.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/bit.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DebugLog.h" #include "llvm/Support/Endian.h" @@ -419,9 +420,8 @@ static dxsa::ComponentMask decodeComponentMask(uint32_t rawComponentMask) { class DXBuilder { public: - DXBuilder(MLIRContext *context, StringAttr name) - : context(context), - module(ModuleOp::create(builder, FileLineColLoc::get(name, 0, 0))), + DXBuilder(MLIRContext * /*context*/, StringAttr name) + : module(ModuleOp::create(builder, FileLineColLoc::get(name, 0, 0))), builder(module.getRegion()) {} using Index = mlir::Value; @@ -614,17 +614,38 @@ class DXBuilder { systemValueNameAttr); } - dxsa::InlineOperandAttr buildInlineOperandAttr( - dxsa::InlineOperandType operandType, uint32_t components, - std::optional mask, ArrayRef indexArray) { + dxsa::InlineOperandAttr + buildInlineOperandAttr(dxsa::InlineOperandType operandType, + const OperandComponents &comp, + ArrayRef indexArray) { auto *ctx = builder.getContext(); - auto maskAttr = mask ? dxsa::ComponentMaskAttr::get(ctx, *mask) - : dxsa::ComponentMaskAttr(); + dxsa::ComponentMaskAttr maskAttr; + dxsa::ComponentSwizzleAttr swizzleAttr; + dxsa::ComponentNameAttr selectAttr; + switch (comp.kind) { + case OperandComponentsKind::None: + break; + case OperandComponentsKind::Mask: + maskAttr = + dxsa::ComponentMaskAttr::get(ctx, decodeComponentMask(comp.mask)); + break; + case OperandComponentsKind::Swizzle: + swizzleAttr = dxsa::ComponentSwizzleAttr::get( + ctx, static_cast(comp.swizzle[0]), + static_cast(comp.swizzle[1]), + static_cast(comp.swizzle[2]), + static_cast(comp.swizzle[3])); + break; + case OperandComponentsKind::One: + selectAttr = dxsa::ComponentNameAttr::get( + ctx, static_cast(comp.one)); + break; + } auto indexAttr = indexArray.empty() ? DenseI64ArrayAttr() : DenseI64ArrayAttr::get(ctx, indexArray); - return dxsa::InlineOperandAttr::get(ctx, operandType, components, maskAttr, - indexAttr); + return dxsa::InlineOperandAttr::get(ctx, operandType, comp.num, maskAttr, + swizzleAttr, selectAttr, indexAttr); } Instruction buildDclInput(dxsa::InlineOperandAttr operand, Location loc) { @@ -635,8 +656,62 @@ class DXBuilder { return dxsa::DclOutput::create(builder, loc, operand); } + Instruction + buildDclConstantBuffer(dxsa::InlineOperandAttr operand, + dxsa::ConstantBufferAccessPattern accessPattern, + Location loc) { + auto accessPatternAttr = dxsa::ConstantBufferAccessPatternAttr::get( + builder.getContext(), accessPattern); + return dxsa::DclConstantBuffer::create(builder, loc, operand, + accessPatternAttr); + } + + Instruction buildDclTgsmRaw(dxsa::InlineOperandAttr operand, + uint32_t byteCount, Location loc) { + return dxsa::DclTgsmRaw::create(builder, loc, operand, + builder.getI32IntegerAttr(byteCount)); + } + + Instruction buildDclIndexRange(dxsa::InlineOperandAttr operand, + uint32_t count, Location loc) { + return dxsa::DclIndexRange::create(builder, loc, operand, + builder.getI32IntegerAttr(count)); + } + + Instruction buildDclHsMaxTessfactor(float maxTessFactor, Location loc) { + return dxsa::DclHsMaxTessfactor::create( + builder, loc, builder.getF32FloatAttr(maxTessFactor)); + } + + Instruction buildDclHsForkPhaseInstanceCount(uint32_t count, Location loc) { + return dxsa::DclHsForkPhaseInstanceCount::create( + builder, loc, builder.getI32IntegerAttr(count)); + } + + Instruction buildDclHsJoinPhaseInstanceCount(uint32_t count, Location loc) { + return dxsa::DclHsJoinPhaseInstanceCount::create( + builder, loc, builder.getI32IntegerAttr(count)); + } + + Instruction buildDclOutputSiv(dxsa::InlineOperandAttr operand, + dxsa::SystemValueName systemValueName, + Location loc) { + auto systemValueNameAttr = + dxsa::SystemValueNameAttr::get(builder.getContext(), systemValueName); + return dxsa::DclOutputSiv::create(builder, loc, operand, + systemValueNameAttr); + } + + Instruction buildDclOutputSgv(dxsa::InlineOperandAttr operand, + dxsa::SystemValueName systemValueName, + Location loc) { + auto systemValueNameAttr = + dxsa::SystemValueNameAttr::get(builder.getContext(), systemValueName); + return dxsa::DclOutputSgv::create(builder, loc, operand, + systemValueNameAttr); + } + private: - MLIRContext *context; ModuleOp module; OpBuilder builder; }; @@ -1139,15 +1214,6 @@ class Parser { return emitError(loc, "extended operand tokens are not yet supported in " "inline operand attribute"); - if (components->kind == OperandComponentsKind::Swizzle || - components->kind == OperandComponentsKind::One) - return emitError(loc, "swizzled / single-component operand selection is " - "not supported in inline operand attribute"); - - std::optional mask; - if (components->kind == OperandComponentsKind::Mask) - mask = decodeComponentMask(components->mask); - SmallVector indices; for (auto indexType : *indexTypes) { if (indexType != D3D10_SB_OPERAND_INDEX_IMMEDIATE32) @@ -1158,8 +1224,7 @@ class Parser { indices.push_back(static_cast(*value)); } - return builder.buildInlineOperandAttr(*type, components->num, mask, - indices); + return builder.buildInlineOperandAttr(*type, *components, indices); } FailureOr parseDclInput(Location loc) { @@ -1174,6 +1239,71 @@ class Parser { return builder.buildDclOutput(*operand, loc); } + FailureOr parseDclConstantBuffer(uint32_t opcodeToken, + Location loc) { + auto rawAccessPattern = + DECODE_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(opcodeToken); + auto accessPattern = + dxsa::symbolizeConstantBufferAccessPattern(rawAccessPattern); + if (!accessPattern) + return emitError(loc, "unknown constant buffer access pattern: ") + << rawAccessPattern; + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); + return builder.buildDclConstantBuffer(*operand, *accessPattern, loc); + } + + FailureOr parseDclTgsmRaw(Location loc) { + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); + auto byteCount = parseToken(); + FAILURE_IF_FAILED(byteCount); + return builder.buildDclTgsmRaw(*operand, *byteCount, loc); + } + + FailureOr parseDclIndexRange(Location loc) { + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); + auto count = parseToken(); + FAILURE_IF_FAILED(count); + return builder.buildDclIndexRange(*operand, *count, loc); + } + + FailureOr parseDclHsMaxTessfactor(Location loc) { + auto token = parseToken(); + FAILURE_IF_FAILED(token); + float maxTessFactor = llvm::bit_cast(*token); + return builder.buildDclHsMaxTessfactor(maxTessFactor, loc); + } + + FailureOr parseDclHsForkPhaseInstanceCount(Location loc) { + auto count = parseToken(); + FAILURE_IF_FAILED(count); + return builder.buildDclHsForkPhaseInstanceCount(*count, loc); + } + + FailureOr parseDclHsJoinPhaseInstanceCount(Location loc) { + auto count = parseToken(); + FAILURE_IF_FAILED(count); + return builder.buildDclHsJoinPhaseInstanceCount(*count, loc); + } + + FailureOr parseDclOutputSiv(Location loc) { + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); + auto name = parseSystemValueName(getLocation()); + FAILURE_IF_FAILED(name); + return builder.buildDclOutputSiv(*operand, *name, loc); + } + + FailureOr parseDclOutputSgv(Location loc) { + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); + auto name = parseSystemValueName(getLocation()); + FAILURE_IF_FAILED(name); + return builder.buildDclOutputSgv(*operand, *name, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -1220,6 +1350,30 @@ class Parser { case D3D10_SB_OPCODE_DCL_OUTPUT: result = parseDclOutput(loc); break; + case D3D10_SB_OPCODE_DCL_OUTPUT_SIV: + result = parseDclOutputSiv(loc); + break; + case D3D10_SB_OPCODE_DCL_OUTPUT_SGV: + result = parseDclOutputSgv(loc); + break; + case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER: + result = parseDclConstantBuffer(opcodeToken, loc); + break; + case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + result = parseDclTgsmRaw(loc); + break; + case D3D10_SB_OPCODE_DCL_INDEX_RANGE: + result = parseDclIndexRange(loc); + break; + case D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR: + result = parseDclHsMaxTessfactor(loc); + break; + case D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + result = parseDclHsForkPhaseInstanceCount(loc); + break; + case D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: + result = parseDclHsJoinPhaseInstanceCount(loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_constant_buffer.mlir b/mlir/test/Target/DXSA/dcl_constant_buffer.mlir new file mode 100644 index 000000000000..b8ece9068315 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_constant_buffer.mlir @@ -0,0 +1,6 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_constant_buffer.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_constant_buffer , index = [0, 1]>, +// CHECK-NEXT: dxsa.dcl_constant_buffer , index = [3, 128]>, +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_hs_fork_phase_instance_count.mlir b/mlir/test/Target/DXSA/dcl_hs_fork_phase_instance_count.mlir new file mode 100644 index 000000000000..0f4d10af5cc1 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_hs_fork_phase_instance_count.mlir @@ -0,0 +1,5 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_hs_fork_phase_instance_count.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_hs_fork_phase_instance_count 4 +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_hs_join_phase_instance_count.mlir b/mlir/test/Target/DXSA/dcl_hs_join_phase_instance_count.mlir new file mode 100644 index 000000000000..7f01bd3d809c --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_hs_join_phase_instance_count.mlir @@ -0,0 +1,5 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_hs_join_phase_instance_count.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_hs_join_phase_instance_count 2 +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_hs_max_tessfactor.mlir b/mlir/test/Target/DXSA/dcl_hs_max_tessfactor.mlir new file mode 100644 index 000000000000..7b8f5fda1e8f --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_hs_max_tessfactor.mlir @@ -0,0 +1,5 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_hs_max_tessfactor.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_hs_max_tessfactor 1.550000e+01 +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_hs_max_tessfactor_invalid.mlir b/mlir/test/Target/DXSA/dcl_hs_max_tessfactor_invalid.mlir new file mode 100644 index 000000000000..31a81a86b4d7 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_hs_max_tessfactor_invalid.mlir @@ -0,0 +1,29 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{'dxsa.dcl_hs_max_tessfactor' op max tessellation factor must be in [1.0, 64.0], got 5.000000e-01}} +dxsa.dcl_hs_max_tessfactor 0.5 + +// ----- + +// expected-error@+1 {{'dxsa.dcl_hs_max_tessfactor' op max tessellation factor must be in [1.0, 64.0], got -1.000000e+00}} +dxsa.dcl_hs_max_tessfactor -1.000000e+00 + +// ----- + +// expected-error@+1 {{'dxsa.dcl_hs_max_tessfactor' op max tessellation factor must be in [1.0, 64.0], got 6.500000e+01}} +dxsa.dcl_hs_max_tessfactor 6.500000e+01 + +// ----- + +// expected-error@+1 {{'dxsa.dcl_hs_max_tessfactor' op max tessellation factor must be in [1.0, 64.0], got nan}} +dxsa.dcl_hs_max_tessfactor 0x7FC00000 + +// ----- + +// expected-error@+1 {{'dxsa.dcl_hs_max_tessfactor' op max tessellation factor must be in [1.0, 64.0], got INF}} +dxsa.dcl_hs_max_tessfactor 0x7F800000 + +// ----- + +// expected-error@+1 {{'dxsa.dcl_hs_max_tessfactor' op max tessellation factor must be in [1.0, 64.0], got -INF}} +dxsa.dcl_hs_max_tessfactor 0xFF800000 diff --git a/mlir/test/Target/DXSA/dcl_index_range.mlir b/mlir/test/Target/DXSA/dcl_index_range.mlir new file mode 100644 index 000000000000..1135468dba9b --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_index_range.mlir @@ -0,0 +1,7 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_index_range.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_index_range , index = [1]>, 3 +// CHECK-NEXT: dxsa.dcl_index_range , index = [4]>, 6 +// CHECK-NEXT: dxsa.dcl_index_range , index = [0]>, 4 +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_input_ps_sgv.mlir b/mlir/test/Target/DXSA/dcl_input_ps_sgv.mlir index 7b3b4abcf427..2ca519c8fa0b 100644 --- a/mlir/test/Target/DXSA/dcl_input_ps_sgv.mlir +++ b/mlir/test/Target/DXSA/dcl_input_ps_sgv.mlir @@ -5,15 +5,15 @@ module { // dcl_input_ps_sgv v0.x, primitiveID // CHECK: %0 = dxsa.index.imm {imm = 0 : i32} // CHECK-NEXT: %1 = dxsa.operand %0 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_sgv %1, primitiveID + // CHECK-NEXT: dxsa.dcl_input_ps_sgv %1, // dcl_input_ps_sgv v1.x, isFrontFace // CHECK-NEXT: %2 = dxsa.index.imm {imm = 1 : i32} // CHECK-NEXT: %3 = dxsa.operand %2 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_sgv %3, isFrontFace + // CHECK-NEXT: dxsa.dcl_input_ps_sgv %3, // dcl_input_ps_sgv v2.x, sampleIndex // CHECK-NEXT: %4 = dxsa.index.imm {imm = 2 : i32} // CHECK-NEXT: %5 = dxsa.operand %4 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_sgv %5, sampleIndex + // CHECK-NEXT: dxsa.dcl_input_ps_sgv %5, } diff --git a/mlir/test/Target/DXSA/dcl_input_ps_siv.mlir b/mlir/test/Target/DXSA/dcl_input_ps_siv.mlir index 24c542847833..84f13f64a640 100644 --- a/mlir/test/Target/DXSA/dcl_input_ps_siv.mlir +++ b/mlir/test/Target/DXSA/dcl_input_ps_siv.mlir @@ -5,25 +5,25 @@ module { // dcl_input_ps_siv linear v0.x, position // CHECK: %0 = dxsa.index.imm {imm = 0 : i32} // CHECK-NEXT: %1 = dxsa.operand %0 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %1, position + // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %1, // dcl_input_ps_siv linear v1.x, clipDistance // CHECK-NEXT: %2 = dxsa.index.imm {imm = 1 : i32} // CHECK-NEXT: %3 = dxsa.operand %2 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %3, clipDistance + // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %3, // dcl_input_ps_siv linear v2.x, cullDistance // CHECK-NEXT: %4 = dxsa.index.imm {imm = 2 : i32} // CHECK-NEXT: %5 = dxsa.operand %4 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %5, cullDistance + // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %5, // dcl_input_ps_siv linear v3.x, renderTargetArrayIndex // CHECK-NEXT: %6 = dxsa.index.imm {imm = 3 : i32} // CHECK-NEXT: %7 = dxsa.operand %6 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %7, renderTargetArrayIndex + // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %7, // dcl_input_ps_siv linear v4.x, viewportArrayIndex // CHECK-NEXT: %8 = dxsa.index.imm {imm = 4 : i32} // CHECK-NEXT: %9 = dxsa.operand %8 {mask = 16 : i32, num_components = 4 : i32, type = 1 : i32} - // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %9, viewportArrayIndex + // CHECK-NEXT: dxsa.dcl_input_ps_siv linear %9, } diff --git a/mlir/test/Target/DXSA/dcl_output_sgv.mlir b/mlir/test/Target/DXSA/dcl_output_sgv.mlir new file mode 100644 index 000000000000..e7a39bb8fa58 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_output_sgv.mlir @@ -0,0 +1,7 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_output_sgv.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_output_sgv , index = [0]>, +// CHECK-NEXT: dxsa.dcl_output_sgv , index = [1]>, +// CHECK-NEXT: dxsa.dcl_output_sgv , index = [2]>, +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_output_siv.mlir b/mlir/test/Target/DXSA/dcl_output_siv.mlir new file mode 100644 index 000000000000..857856a3c765 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_output_siv.mlir @@ -0,0 +1,11 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_output_siv.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_output_siv , index = [0]>, +// CHECK-NEXT: dxsa.dcl_output_siv , index = [1]>, +// CHECK-NEXT: dxsa.dcl_output_siv , index = [2]>, +// CHECK-NEXT: dxsa.dcl_output_siv , index = [3]>, +// CHECK-NEXT: dxsa.dcl_output_siv , index = [4]>, +// CHECK-NEXT: dxsa.dcl_output_siv , index = [5]>, +// CHECK-NEXT: dxsa.dcl_output_siv , index = [6]>, +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_tgsm_raw.mlir b/mlir/test/Target/DXSA/dcl_tgsm_raw.mlir new file mode 100644 index 000000000000..cf0a881d7627 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_tgsm_raw.mlir @@ -0,0 +1,7 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_tgsm_raw.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_tgsm_raw , 4 +// CHECK-NEXT: dxsa.dcl_tgsm_raw , 1024 +// CHECK-NEXT: dxsa.dcl_tgsm_raw , 32768 +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_tgsm_raw_invalid.mlir b/mlir/test/Target/DXSA/dcl_tgsm_raw_invalid.mlir new file mode 100644 index 000000000000..1911c5763d2d --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_tgsm_raw_invalid.mlir @@ -0,0 +1,14 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{'dxsa.dcl_tgsm_raw' op byte count must be a multiple of 4, got 7}} +dxsa.dcl_tgsm_raw , 7 + +// ----- + +// expected-error@+1 {{attribute 'byte_count' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive whose maximum value is 32768}} +dxsa.dcl_tgsm_raw , 0 + +// ----- + +// expected-error@+1 {{attribute 'byte_count' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive whose maximum value is 32768}} +dxsa.dcl_tgsm_raw , 65536 diff --git a/mlir/test/Target/DXSA/inline_operand_invalid.mlir b/mlir/test/Target/DXSA/inline_operand_invalid.mlir new file mode 100644 index 000000000000..891af29af2e6 --- /dev/null +++ b/mlir/test/Target/DXSA/inline_operand_invalid.mlir @@ -0,0 +1,19 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{at most one of 'mask', 'swizzle', 'select' may be set on an operand}} +dxsa.dcl_constant_buffer , swizzle = , index = [0, 1]>, + +// ----- + +// expected-error@+1 {{at most one of 'mask', 'swizzle', 'select' may be set on an operand}} +dxsa.dcl_input , select = , index = [0]> + +// ----- + +// expected-error@+1 {{component selection mode is only valid on a 4-component operand, got 1 components}} +dxsa.dcl_output > + +// ----- + +// expected-error@+1 {{component selection mode is only valid on a 4-component operand, got 0 components}} +dxsa.dcl_tgsm_raw , index = [0]>, 16 diff --git a/mlir/test/Target/DXSA/inline_operand_roundtrip.mlir b/mlir/test/Target/DXSA/inline_operand_roundtrip.mlir new file mode 100644 index 000000000000..21f9fbf64e82 --- /dev/null +++ b/mlir/test/Target/DXSA/inline_operand_roundtrip.mlir @@ -0,0 +1,13 @@ +// RUN: mlir-opt %s | mlir-opt | FileCheck %s + +// Non-identity swizzle (read from a constant buffer reversed). +// CHECK: dxsa.dcl_constant_buffer , index = [0, 1]>, +dxsa.dcl_constant_buffer , index = [0, 1]>, + +// Broadcast swizzle. +// CHECK: dxsa.dcl_constant_buffer , index = [1, 4]>, +dxsa.dcl_constant_buffer , index = [1, 4]>, + +// Single-channel select (e.g. `r0.z`-style read). +// CHECK: dxsa.dcl_input , index = [0]> +dxsa.dcl_input , index = [0]> diff --git a/mlir/test/Target/DXSA/inputs/dcl_constant_buffer.bin b/mlir/test/Target/DXSA/inputs/dcl_constant_buffer.bin new file mode 100644 index 0000000000000000000000000000000000000000..3860e05d172f7f5a802f9e561b2d40648ad909b3 GIT binary patch literal 32 ccma!KU|@0UQ(yoAMj(#lfbf}t>;@nP063rnF8}}l literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_hs_fork_phase_instance_count.bin b/mlir/test/Target/DXSA/inputs/dcl_hs_fork_phase_instance_count.bin new file mode 100644 index 0000000000000000000000000000000000000000..e0ad90ea079775c5e4909ae87de627ba7bd6c95c GIT binary patch literal 8 PcmbQqz`(@9z`y_i1nK~w literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_hs_join_phase_instance_count.bin b/mlir/test/Target/DXSA/inputs/dcl_hs_join_phase_instance_count.bin new file mode 100644 index 0000000000000000000000000000000000000000..ef136f92001d91fb01a4054d8cd95f1097086ea3 GIT binary patch literal 8 PcmbQmz`(@Bz`y_i1nK~v literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_hs_max_tessfactor.bin b/mlir/test/Target/DXSA/inputs/dcl_hs_max_tessfactor.bin new file mode 100644 index 0000000000000000000000000000000000000000..67b473ee48ba2450690b6faa351d8a065b1d7793 GIT binary patch literal 8 PcmbQiz`(@7P~ivw1_J?9 literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_index_range.bin b/mlir/test/Target/DXSA/inputs/dcl_index_range.bin new file mode 100644 index 0000000000000000000000000000000000000000..c780403f7299a372d00dc5076a48f628e72818ed GIT binary patch literal 48 ocma!MU|6skj)Cj06shd7ytkO literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_output_siv.bin b/mlir/test/Target/DXSA/inputs/dcl_output_siv.bin new file mode 100644 index 0000000000000000000000000000000000000000..5d5eab4741f51b9c662bdd821b7a96568b27a648 GIT binary patch literal 112 zcmYdiU|{*AAiw|uj6j?Y1$AT|>cAH-%x;)B>MNPG~R6^RdGb0hKDfNXvs1^|n{ B1=;`r literal 0 HcmV?d00001 diff --git a/mlir/test/Target/DXSA/inputs/dcl_tgsm_raw.bin b/mlir/test/Target/DXSA/inputs/dcl_tgsm_raw.bin new file mode 100644 index 0000000000000000000000000000000000000000..09475e168faf942c0fc71cd6b14e058ca3a31eee GIT binary patch literal 48 gcmbQwz`(-rL689iSb%swl+Oqifbp3?{00UF0FcfFcmMzZ literal 0 HcmV?d00001