From 161d8b2c2b9442ab660711759363e252e78d2805 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Thu, 2 Jul 2026 17:06:09 +0900 Subject: [PATCH] [mlir][dxsa] Add sample instruction Sample instruction takes an address, a resource (texture), a sampler, and writes texture data to the destination register. There are several optional that can be present: - Offset is encoded as an extended opcode. - LOD clamp and feeback for sample_cl_s. The spec mentions clamp and feedback as optional, but DXC decodes them both. It is possible that they are always present as operands, but can be null. Other extended instruction are added for other resource instructions, and not enabled for sample instruction. Feedback (ClampFeedback) and Offset are both supposed to be optional attributes. MLIR parser is not able to handle cases where feedback is present, but offset is absent, so and fails roundtrip verifier tests. Therefore such instructions are separate, and feedback operand is not optional. --- .../mlir/Dialect/DXSA/IR/DXSAResourceOps.td | 428 ++++++++++++++++++ mlir/lib/Dialect/DXSA/IR/DXSAOperand.cpp | 15 + mlir/lib/Target/DXSA/BinaryParser.cpp | 397 ++++++++++++++++ mlir/test/Target/DXSA/sample.test | 21 + mlir/test/Target/DXSA/sample_b.test | 17 + mlir/test/Target/DXSA/sample_c.test | 17 + mlir/test/Target/DXSA/sample_c_lz.test | 17 + mlir/test/Target/DXSA/sample_d.test | 17 + mlir/test/Target/DXSA/sample_l.test | 30 ++ .../Target/DXSA/sample_offset_invalid.mlir | 29 ++ 10 files changed, 988 insertions(+) create mode 100644 mlir/test/Target/DXSA/sample.test create mode 100644 mlir/test/Target/DXSA/sample_b.test create mode 100644 mlir/test/Target/DXSA/sample_c.test create mode 100644 mlir/test/Target/DXSA/sample_c_lz.test create mode 100644 mlir/test/Target/DXSA/sample_d.test create mode 100644 mlir/test/Target/DXSA/sample_l.test create mode 100644 mlir/test/Target/DXSA/sample_offset_invalid.mlir diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAResourceOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAResourceOps.td index f1a401e107e8..e73ef4c04357 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAResourceOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAResourceOps.td @@ -76,4 +76,432 @@ def DXSA_EvalSnapped : DXSA_BinaryOp<"eval_snapped"> { }]; } +//===----------------------------------------------------------------------===// +// dxsa.sample +//===----------------------------------------------------------------------===// + +def DXSA_SampleOffsetAttr : AttrDef { + let mnemonic = "sample_offset"; + let summary = "immediate offset for the texture coordinates for the sample"; + let description = [{ + The dxsa.sample_offset attribute indicates that the texture coordinates for + the sample are to be offset by a set of provided immediate texel space + integer constant values. The literal values are a set of 4 bit 2's + complement numbers, having integer range [-8,7]. + }]; + let parameters = (ins "int32_t":$u, "int32_t":$v, "int32_t":$w); + let assemblyFormat = "`<` struct(params) `>`"; + let genVerifyDecl = 1; +} + +def DXSA_SampleClampFeedbackAttr : AttrDef { + let mnemonic = "sample_clamp_feedback"; + let summary = "optional LOD clamp and Tiled Resources shader feedback status output value"; + let description = [{ + The dxsa.sample_clamp_feed attribute is an optional pair of operands for + dxsa.sample instruction. + + `lod_clamp` is an additional 32 bit scalar LOD clamp operand. + + `feedback` is a shader feedback status output value. The contents + of the return value are opaque - direct reading by the shader + program is disallowed. + }]; + + let parameters = (ins + AttrParameter<"SrcOperandAttr", "lod_clamp">:$lod_clamp, + AttrParameter<"DstOperandAttr", "feedback">:$feedback); + + let assemblyFormat = "`<` $lod_clamp `,` $feedback `>`"; +} + +def DXSA_Sample : DXSA_Op<"sample"> { + let summary = "sample data from the specified texture using the filtering mode identified by the given sampler"; + let description = [{ + The dxsa.sample operation uses provided address, sample data from the + specified Element/texture using the filtering mode identified by the given + sampler. The source data may come from any Resource Type (5), other than + Buffers. + + `src_address` provides the set of texture coordinates needed to perform the + sample, as floating point values referencing normalized space in the texture. + + `src_resource` is a texture register (t). This is simply a + placeholder for a texture, including the return data type of the + resource being sampled. + + `src_sampler` is a sampler register (s). This is simply a + placeholder for a collection of filtering controls (such as point + vs. linear, mipmapping and address wrapping controls). + + The optional `offset` operand suffix (address offset by immediate + integer) indicates that the texture coordinates for the sample are + to be offset by a set of provided immediate texel space integer + constant values. The literal values are a set of 4 bit 2's + complement numbers, having integer range [-8,7]. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler + (`,` $offset^)? + attr-dict + }]; +} + +def DXSA_SampleClampFeedback : DXSA_Op<"sample_cl_s"> { + let summary = "same as `dxsa.sample`, but with an additional LOD clamp and status output"; + let description = [{ + `src_address`, `src_resource`, `src_sampler`, `offset` operands + are the same as in `dxsa.sample` instruction. + + The `clamp_feedback` operand appends an additional 32 bit scalar + LOD clamp operand and an additional 32 bit scalar Tiled Resources + shader feedback status output value. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SampleClampFeedbackAttr:$clamp_feedback, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $clamp_feedback + (`,` $offset^)? + attr-dict + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.sample_b +//===----------------------------------------------------------------------===// + +def DXSA_SampleB : DXSA_Op<"sample_b"> { + let summary = "sample data from the specified texture with an additional bias applied to the LOD"; + let description = [{ + The `dxsa.sample_b` operation uses provided address, sample data from the + specified Element/texture using the filtering mode identified by the given + sampler. The source data may come from any Resource Type(5), other than + Buffers. An additional bias is applied to the level of detail computed as + part of the instruction execution. + + `src_address`, `src_resource`, `src_sampler` and `offset` operands + are the same as in `dxsa.sample` instruction. + + The `src_lod_bias` value is added to the computed LOD on a per-pixel basis, + along with the sampler MipLODBias value, prior to the clamp to MinLOD and + MaxLOD. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_lod_bias, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_lod_bias + (`,` $offset^)? + attr-dict + }]; +} + +def DXSA_SampleBClampFeedback : DXSA_Op<"sample_b_cl_s"> { + let summary = "same as `dxsa.sample_b`, but with an additional LOD clamp and status output"; + let description = [{ + `src_address`, `src_resource`, `src_sampler`, `src_lod_bias` and + `offset` operands are the same as in `dxsa.sample_b` instruction. + + The `clamp_feedback` operand appends an additional 32 bit scalar + LOD clamp operand and an additional 32 bit scalar Tiled Resources + shader feedback status output value. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_lod_bias, + DXSA_SampleClampFeedbackAttr:$clamp_feedback, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_lod_bias `,` $clamp_feedback + (`,` $offset^)? + attr-dict + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.sample_d +//===----------------------------------------------------------------------===// + +def DXSA_SampleD : DXSA_Op<"sample_d"> { + let summary = "sample data from the specified texture with derivatives for X and Y"; + let description = [{ + The `dxsa.sample_d` operation uses provided address, sample data from the + specified Element/texture using the filtering mode identified by the given + sampler. The source data may come from any Resource Type(5), other than + Buffers. + + `src_address`, `src_resource`, `src_sampler` and `offset` operands + are the same as in `dxsa.sample` instruction. + + Derivatives for the source address in the x direction and the y direction are + provided by extra parameters, `src_x_derivatives` and `src_y_derivatives`, + respectively. These derivatives are in normalized texture coordinate space. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_x_derivatives, + DXSA_SrcOperandAttr:$src_y_derivatives, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler + `,` $src_x_derivatives `,` $src_y_derivatives + (`,` $offset^)? + attr-dict + }]; +} + +def DXSA_SampleDClampFeedback : DXSA_Op<"sample_d_cl_s"> { + let summary = "same as `dxsa.sample_d`, but with an additional LOD clamp and status output"; + let description = [{ + `dst`, `src`_address, `src`_resource, `src`_sampler, + `src`_x_derivatives, `src`_y_derivatives and `offset` operands are + the same as in `dxsa.sample_d` instruction. + + The `clamp_feedback` operand appends an additional 32 bit scalar + LOD clamp operand and an additional 32 bit scalar Tiled Resources + shader feedback status output value. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_x_derivatives, + DXSA_SrcOperandAttr:$src_y_derivatives, + DXSA_SampleClampFeedbackAttr:$clamp_feedback, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler + `,` $src_x_derivatives `,` $src_y_derivatives `,` $clamp_feedback + (`,` $offset^)? + attr-dict + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.sample_l +//===----------------------------------------------------------------------===// + +def DXSA_SampleL : DXSA_Op<"sample_l"> { + let summary = "sample data from the specified texture with specific LOD"; + let description = [{ + `dxsa.sample_l` is identical to `dxsa.sample`, except that LOD is provided + directly by the application as a scalar value, representing no anisotropy. + + `src_address`, `src_resource`, `src_sampler` and `offset` operands + are the same as in `dxsa.sample` instruction. + + `src_lod` is the LOD value. If the LOD value is <= 0, the zero'th (biggest + map) is chosen, with the magnify filter applied (if applicable based on the + filter mode). Since `src_lod` is a floating point value, the fractional + value is used to interpolate (if the minify filter is LINEAR or with + anisotropic filtering) between two mip levels. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_lod, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_lod + (`,` $offset^)? + attr-dict + }]; +} + +def DXSA_SampleLFeedback : DXSA_Op<"sample_l_cl_s"> { + let summary = "same as `dxsa.sample_l`, but with an additional LOD clamp and status output"; + let description = [{ + `dst`, `src_address`, `src_resource`,`src_sampler`, `src_lod` and + `offset` operands are the same as in `dxsa.sample_l` instruction. + + The `clamp_feedback` operand appends an additional 32 bit scalar + LOD clamp operand and an additional 32 bit scalar Tiled Resources + shader feedback status output value. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_lod, + DXSA_DstOperandAttr:$feedback, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_lod `,` $feedback + (`,` $offset^)? + attr-dict + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.sample_c +//===----------------------------------------------------------------------===// + +def DXSA_SampleC : DXSA_Op<"sample_c"> { + let summary = "perform a comparison filter"; + let description = [{ + `dxsa.sample_c` is to provide a building-block for Percentage-Closer Depth + filtering. The 'c' in sample_c stands for Comparison. + + The operands to `dxsa.sample_c` are identical to `dxsa.sample`, except that + there is an additional float32 source operand, `src_reference_value`, which + must be a register with single-component selected, or a scalar literal. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_reference_value, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_reference_value + (`,` $offset^)? + attr-dict + }]; +} + +def DXSA_SampleCClampFeedback : DXSA_Op<"sample_c_cl_s"> { + let summary = "same as `dxsa.sample_c`, but with an additional LOD clamp and status output"; + let description = [{ + `dst`,`src_address`,`src_resource`,`src_sampler`,`src_reference_value` + and `offset operands are the same as in `dxsa.sample_c` + instruction. + + The `clamp_feedback` operand appends an additional 32 bit scalar + LOD clamp operand and an additional 32 bit scalar Tiled Resources + shader feedback status output value. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_reference_value, + DXSA_SampleClampFeedbackAttr:$clamp_feedback, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_reference_value `,` $clamp_feedback + (`,` $offset^)? + attr-dict + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.sample_c_lz +//===----------------------------------------------------------------------===// + +def DXSA_SampleCLZ : DXSA_Op<"sample_c_lz"> { + let summary = "perform a comparison filter with zero LOD"; + let description = [{ + Same as `dxsa.sample_c`, except LOD is 0, and derivatives are ignored (as if + they are 0). The 'lz' stands for level-zero. Because derivatives are + ignored, this instruction is available in shaders other than the Pixel + Shader. + + `dxsa.sample_c` is to provide a building-block for Percentage-Closer Depth + filtering. The 'c' in sample_c stands for Comparison. + + The operands to `dxsa.sample_c_lz` are identical to `dxsa.sample_c`. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_reference_value, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_reference_value + (`,` $offset^)? + attr-dict + }]; +} + +def DXSA_SampleCLZFeedback : DXSA_Op<"sample_c_lz_s"> { + let summary = "same as `dxsa.sample_c_lz`, but with an additional LOD clamp and status output"; + let description = [{ + `dst`, `src_address`, `src_resource`, `src_sampler`, + `src_reference_value`, `offset` operands are the same as in + `dxsa.sample` instruction. + + The `clamp_feedback` operand appends an additional 32 bit scalar + LOD clamp operand and an additional 32 bit scalar Tiled Resources + shader feedback status output value. + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_SrcOperandAttr:$src_address, + DXSA_SrcOperandAttr:$src_resource, + DXSA_SrcOperandAttr:$src_sampler, + DXSA_SrcOperandAttr:$src_reference_value, + DXSA_SampleClampFeedbackAttr:$feedback, + OptionalAttr:$offset); + let results = (outs); + + let assemblyFormat = [{ + $dst `,` $src_address `,` $src_resource `,` $src_sampler `,` $src_reference_value `,` $feedback + (`,` $offset^)? + attr-dict + }]; +} + #endif // MLIR_DIALECT_DXSA_IR_DXSARESOURCEOPS diff --git a/mlir/lib/Dialect/DXSA/IR/DXSAOperand.cpp b/mlir/lib/Dialect/DXSA/IR/DXSAOperand.cpp index 9208efaa6cf4..8027465af4c7 100644 --- a/mlir/lib/Dialect/DXSA/IR/DXSAOperand.cpp +++ b/mlir/lib/Dialect/DXSA/IR/DXSAOperand.cpp @@ -991,3 +991,18 @@ void SrcOperandAttr::print(AsmPrinter &printer) const { printNegAndAbsModifier(printer, getModifier(), [&] { printSrcOperandBody(printer, *this); }); } + +LogicalResult +SampleOffsetAttr::verify(function_ref emitError, + int32_t u, int32_t v, int32_t w) { + int32_t values[] = {u, v, w}; + for (int32_t value : values) { + if (value < -8 || value > 7) { + return emitError() + << "sample offsets must be 4 bit 2's complement numbers, " + "having integer range [-8,7], got " + << value; + } + } + return success(); +} diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 7910d7acc105..b641df41ccab 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -390,6 +390,30 @@ struct InstructionModifier { // Whether an op carries a precise modifier attribute. enum class HasPreciseAttr { No, Yes }; +struct ExtendedInstructionSampleOffset { + int32_t u; + int32_t v; + int32_t w; +}; + +struct ExtendedInstructionResourceDim { + uint32_t dim; + std::optional stride; +}; + +struct ExtendedInstructionResourceReturnType { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; +}; + +struct ExtendedInstruction { + std::optional sampleOffset; + std::optional resourceDim; + std::optional resourceReturnType; +}; + struct OperandModifier { uint32_t modifier{0}; uint32_t minPrecision{0}; @@ -1006,6 +1030,144 @@ class DXBuilder { builder.getI32IntegerAttr(y), builder.getI32IntegerAttr(z)); } + dxsa::SampleOffsetAttr + buildSampleOffsetAttr(const ExtendedInstructionSampleOffset &sampleOffset) { + return dxsa::SampleOffsetAttr::get(context, sampleOffset.u, sampleOffset.v, + sampleOffset.w); + } + + dxsa::SampleClampFeedbackAttr + buildSampleClampFeedbackAttr(dxsa::SrcOperandAttr clamp, + dxsa::DstOperandAttr feedback) { + return dxsa::SampleClampFeedbackAttr::get(context, clamp, feedback); + } + + Instruction buildSample(dxsa::DstOperandAttr dst, + dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, + dxsa::SrcOperandAttr srcSampler, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::Sample::create(builder, loc, dst, srcAddress, srcResource, + srcSampler, offset); + } + + Instruction buildSampleClampFeedback( + dxsa::DstOperandAttr dst, dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, dxsa::SrcOperandAttr srcSampler, + dxsa::SampleClampFeedbackAttr clampFeedback, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleClampFeedback::create(builder, loc, dst, srcAddress, + srcResource, srcSampler, + clampFeedback, offset); + } + + Instruction buildSampleB(dxsa::DstOperandAttr dst, + dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, + dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcLodBias, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleB::create(builder, loc, dst, srcAddress, srcResource, + srcSampler, srcLodBias, offset); + } + + Instruction buildSampleBClampFeedback( + dxsa::DstOperandAttr dst, dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcLodBias, + dxsa::SampleClampFeedbackAttr clampFeedback, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleBClampFeedback::create( + builder, loc, dst, srcAddress, srcResource, srcSampler, srcLodBias, + clampFeedback, offset); + } + + Instruction buildSampleD(dxsa::DstOperandAttr dst, + dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, + dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcXDerivatives, + dxsa::SrcOperandAttr srcYDerivatives, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleD::create(builder, loc, dst, srcAddress, srcResource, + srcSampler, srcXDerivatives, srcYDerivatives, + offset); + } + + Instruction buildSampleDClampFeedback( + dxsa::DstOperandAttr dst, dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcXDerivatives, + dxsa::SrcOperandAttr srcYDerivatives, + dxsa::SampleClampFeedbackAttr clampFeedback, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleDClampFeedback::create( + builder, loc, dst, srcAddress, srcResource, srcSampler, srcXDerivatives, + srcYDerivatives, clampFeedback, offset); + } + + Instruction buildSampleL(dxsa::DstOperandAttr dst, + dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, + dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcLod, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleL::create(builder, loc, dst, srcAddress, srcResource, + srcSampler, srcLod, offset); + } + + Instruction buildSampleLFeedback( + dxsa::DstOperandAttr dst, dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcLod, dxsa::DstOperandAttr feedback, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleLFeedback::create(builder, loc, dst, srcAddress, + srcResource, srcSampler, srcLod, + feedback, offset); + } + + Instruction buildSampleC(dxsa::DstOperandAttr dst, + dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, + dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcReferenceValue, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleC::create(builder, loc, dst, srcAddress, srcResource, + srcSampler, srcReferenceValue, offset); + } + + Instruction buildSampleCClampFeedback( + dxsa::DstOperandAttr dst, dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcReferenceValue, + dxsa::SampleClampFeedbackAttr clampFeedback, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleCClampFeedback::create( + builder, loc, dst, srcAddress, srcResource, srcSampler, + srcReferenceValue, clampFeedback, offset); + } + + Instruction buildSampleCLZ(dxsa::DstOperandAttr dst, + dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, + dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcReferenceValue, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleCLZ::create(builder, loc, dst, srcAddress, srcResource, + srcSampler, srcReferenceValue, offset); + } + + Instruction buildSampleCLZFeedback( + dxsa::DstOperandAttr dst, dxsa::SrcOperandAttr srcAddress, + dxsa::SrcOperandAttr srcResource, dxsa::SrcOperandAttr srcSampler, + dxsa::SrcOperandAttr srcReferenceValue, + dxsa::SampleClampFeedbackAttr clampFeedback, + dxsa::SampleOffsetAttr offset, Location loc) { + return dxsa::SampleCLZFeedback::create( + builder, loc, dst, srcAddress, srcResource, srcSampler, + srcReferenceValue, clampFeedback, offset); + } + private: MLIRContext *context; OpBuilder builder; @@ -1745,6 +1907,215 @@ class Parser { return builder.buildGsStreamIndexOp(*index, loc); } + void parseExtendedInstruction(uint32_t extendedToken, + ExtendedInstruction &ext) { + switch (DECODE_D3D10_SB_EXTENDED_OPCODE_TYPE(extendedToken)) { + case D3D10_SB_EXTENDED_OPCODE_EMPTY: + return; + case D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS: { + auto token = static_cast(extendedToken); + int32_t offsets[3] = { + DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET( + D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U, token), + DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET( + D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V, token), + DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET( + D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W, token), + }; + for (int32_t &offset : offsets) { + // Sign extend from 4 bits to 32. + if (offset & 0x8) { + offset |= 0xfffffff0; + } + } + ext.sampleOffset = {offsets[0], offsets[1], offsets[2]}; + return; + } + case D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM: { + auto dim = DECODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION(extendedToken); + auto stride = + (dim == D3D11_SB_RESOURCE_DIMENSION_STRUCTURED_BUFFER) + ? std::optional( + DECODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION_STRUCTURE_STRIDE( + extendedToken)) + : std::nullopt; + ext.resourceDim = {dim, stride}; + return; + } + case D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE: { + ext.resourceReturnType = { + DECODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(extendedToken, 0), + DECODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(extendedToken, 1), + DECODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(extendedToken, 2), + DECODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(extendedToken, 3), + }; + return; + } + } + } + + FailureOr parseSampleInstruction(uint32_t opcode, + ExtendedInstruction &ext, + size_t beginOffset, + uint32_t length, Location loc) { + dxsa::SampleOffsetAttr offset; + if (ext.sampleOffset) { + offset = builder.buildSampleOffsetAttr(*ext.sampleOffset); + } + + auto dst = parseDstOperand(); + FAILURE_IF_FAILED(dst); + + dxsa::DstOperandAttr feedback; + switch (opcode) { + case D3DWDDM1_3_SB_OPCODE_SAMPLE_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_D_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_B_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_L_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK: + auto op = parseDstOperand(); + FAILURE_IF_FAILED(op); + feedback = *op; + break; + } + + auto srcAddress = parseSrcOperand(); + FAILURE_IF_FAILED(srcAddress); + + auto srcResource = parseSrcOperand(); + FAILURE_IF_FAILED(srcResource); + + auto srcSampler = parseSrcOperand(); + FAILURE_IF_FAILED(srcSampler); + + FailureOr instr; + switch (opcode) { + case D3D10_SB_OPCODE_SAMPLE: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_CLAMP_FEEDBACK: { + if (feedback) { + auto clamp = parseSrcOperand(); + FAILURE_IF_FAILED(clamp); + + auto clampFeedback = + builder.buildSampleClampFeedbackAttr(*clamp, feedback); + instr = builder.buildSampleClampFeedback(*dst, *srcAddress, + *srcResource, *srcSampler, + clampFeedback, offset, loc); + } else { + instr = builder.buildSample(*dst, *srcAddress, *srcResource, + *srcSampler, offset, loc); + } + break; + } + case D3D10_SB_OPCODE_SAMPLE_D: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_D_CLAMP_FEEDBACK: { + auto srcXDerivatives = parseSrcOperand(); + FAILURE_IF_FAILED(srcXDerivatives); + + auto srcYDerivatives = parseSrcOperand(); + FAILURE_IF_FAILED(srcYDerivatives); + + if (feedback) { + auto clamp = parseSrcOperand(); + FAILURE_IF_FAILED(clamp); + + auto clampFeedback = + builder.buildSampleClampFeedbackAttr(*clamp, feedback); + instr = builder.buildSampleDClampFeedback( + *dst, *srcAddress, *srcResource, *srcSampler, *srcXDerivatives, + *srcYDerivatives, clampFeedback, offset, loc); + } else { + instr = builder.buildSampleD(*dst, *srcAddress, *srcResource, + *srcSampler, *srcXDerivatives, + *srcYDerivatives, offset, loc); + } + break; + } + case D3D10_SB_OPCODE_SAMPLE_B: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_B_CLAMP_FEEDBACK: { + auto srcLodBias = parseSrcOperand(); + FAILURE_IF_FAILED(srcLodBias); + + if (feedback) { + auto clamp = parseSrcOperand(); + FAILURE_IF_FAILED(clamp); + auto clampFeedback = + builder.buildSampleClampFeedbackAttr(*clamp, feedback); + instr = builder.buildSampleBClampFeedback( + *dst, *srcAddress, *srcResource, *srcSampler, *srcLodBias, + clampFeedback, offset, loc); + } else { + instr = builder.buildSampleB(*dst, *srcAddress, *srcResource, + *srcSampler, *srcLodBias, offset, loc); + } + break; + } + case D3D10_SB_OPCODE_SAMPLE_L: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_L_FEEDBACK: { + auto srcLod = parseSrcOperand(); + FAILURE_IF_FAILED(srcLod); + + if (feedback) { + instr = builder.buildSampleLFeedback(*dst, *srcAddress, *srcResource, + *srcSampler, *srcLod, feedback, + offset, loc); + } else { + instr = builder.buildSampleL(*dst, *srcAddress, *srcResource, + *srcSampler, *srcLod, offset, loc); + } + break; + } + case D3D10_SB_OPCODE_SAMPLE_C: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK: { + auto srcReferenceValue = parseSrcOperand(); + FAILURE_IF_FAILED(srcReferenceValue); + + if (feedback) { + auto clamp = parseSrcOperand(); + FAILURE_IF_FAILED(clamp); + auto clampFeedback = + builder.buildSampleClampFeedbackAttr(*clamp, feedback); + instr = builder.buildSampleCClampFeedback( + *dst, *srcAddress, *srcResource, *srcSampler, *srcReferenceValue, + clampFeedback, offset, loc); + } else { + instr = + builder.buildSampleC(*dst, *srcAddress, *srcResource, *srcSampler, + *srcReferenceValue, offset, loc); + } + break; + } + case D3D10_SB_OPCODE_SAMPLE_C_LZ: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK: { + auto srcReferenceValue = parseSrcOperand(); + FAILURE_IF_FAILED(srcReferenceValue); + + if (feedback) { + auto clamp = parseSrcOperand(); + FAILURE_IF_FAILED(clamp); + auto clampFeedback = + builder.buildSampleClampFeedbackAttr(*clamp, feedback); + + instr = builder.buildSampleCLZFeedback(*dst, *srcAddress, *srcResource, + *srcSampler, *srcReferenceValue, + clampFeedback, offset, loc); + } else { + instr = + builder.buildSampleCLZ(*dst, *srcAddress, *srcResource, *srcSampler, + *srcReferenceValue, offset, loc); + } + break; + } + default: + llvm_unreachable("unhandled instruction"); + } + + FAILURE_IF_FAILED(instr); + FAILURE_IF_FAILED(verifyInstructionLength(beginOffset, length)); + return instr; + } + FailureOr parseDclInput(Location loc) { auto operand = parseDstOperand(); FAILURE_IF_FAILED(operand); @@ -2350,6 +2721,18 @@ class Parser { modifier.saturate = DECODE_IS_D3D10_SB_INSTRUCTION_SATURATE_ENABLED(*opcodeToken0); + ExtendedInstruction extendedInst; + if (DECODE_IS_D3D10_SB_OPCODE_EXTENDED(*opcodeToken0)) { + // opcodeToken0 is followed by zero or more opcodeToken1 that describe + // sampler or resource parameters. + Token opcodeToken1; + do { + opcodeToken1 = parseToken(); + FAILURE_IF_FAILED(opcodeToken1); + parseExtendedInstruction(*opcodeToken1, extendedInst); + } while (DECODE_IS_D3D10_SB_OPCODE_EXTENDED(*opcodeToken1)); + } + // TODO: extended instructions: // BOOL b51PlusShader = // BOOL bExtended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(Token) @@ -2693,6 +3076,20 @@ class Parser { case D3D11_SB_OPCODE_SYNC: return parseSync(*opcodeToken0, beginOffset, instructionLengthInTokens, getLocation()); + case D3D10_SB_OPCODE_SAMPLE: + case D3D10_SB_OPCODE_SAMPLE_B: + case D3D10_SB_OPCODE_SAMPLE_C: + case D3D10_SB_OPCODE_SAMPLE_C_LZ: + case D3D10_SB_OPCODE_SAMPLE_D: + case D3D10_SB_OPCODE_SAMPLE_L: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_B_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_D_CLAMP_FEEDBACK: + case D3DWDDM1_3_SB_OPCODE_SAMPLE_L_FEEDBACK: + return parseSampleInstruction(opcode, extendedInst, beginOffset, + instructionLengthInTokens, getLocation()); } #undef SATURABLE_OP #undef PLAIN_OP diff --git a/mlir/test/Target/DXSA/sample.test b/mlir/test/Target/DXSA/sample.test new file mode 100644 index 000000000000..a2fcf748a480 --- /dev/null +++ b/mlir/test/Target/DXSA/sample.test @@ -0,0 +1,21 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.sample r<0>, v<0, >, t<3, vector>, s<5> + +0x8b000045, 0x800000c2, 0x00155543, 0x001000f2, +0x00000000, 0x00101046, 0x00000000, 0x00107e46, +0x00000003, 0x00106000, 0x00000005 + +// CHECK: dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>, + +0x8c000045, 0x8000f601, 0x800000c2, 0x00155543, +0x001000f2, 0x00000001, 0x00101046, 0x00000000, +0x00107e46, 0x00000003, 0x00106000, 0x00000005 + +// CHECK: dxsa.sample_cl_s r<1>, v<0, >, t<3, vector>, s<5>, , + +0x8f0000e6, 0x80003801, 0x800000c2, 0x00155543, +0x001000f2, 0x00000001, 0x0000d000, 0x00101046, +0x00000000, 0x00107e46, 0x00000003, 0x00106000, +0x00000005, 0x00004001, 0x3f000000 diff --git a/mlir/test/Target/DXSA/sample_b.test b/mlir/test/Target/DXSA/sample_b.test new file mode 100644 index 000000000000..e7841a1f3335 --- /dev/null +++ b/mlir/test/Target/DXSA/sample_b.test @@ -0,0 +1,17 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.sample_b r<0>, v<0, >, t<3, vector>, s<5>, v<0, > + +0x8d00004a, 0x800000c2, 0x00155543, 0x001000f2, +0x00000000, 0x00101046, 0x00000000, 0x00107e46, +0x00000003, 0x00106000, 0x00000005, 0x0010101a, +0x00000000 + +// CHECK: dxsa.sample_b_cl_s r<1>, v<0, >, t<3, vector>, s<5>, v<0, >, , + +0x910000e7, 0x80003801, 0x800000c2, 0x00155543, +0x001000f2, 0x00000001, 0x0000d000, 0x00101046, +0x00000000, 0x00107e46, 0x00000003, 0x00106000, +0x00000005, 0x0010101a, 0x00000000, 0x00004001, +0x3f000000 diff --git a/mlir/test/Target/DXSA/sample_c.test b/mlir/test/Target/DXSA/sample_c.test new file mode 100644 index 000000000000..245852033a93 --- /dev/null +++ b/mlir/test/Target/DXSA/sample_c.test @@ -0,0 +1,17 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.sample_c r<0, >, v<0, >, t<3, vector, >, s<5>, r<0, > + +0x8d000046, 0x800000c2, 0x00155543, 0x00100022, +0x00000000, 0x00101046, 0x00000000, 0x00107006, +0x00000003, 0x00106000, 0x00000005, 0x0010000a, +0x00000000 + +// CHECK: dxsa.sample_c_cl_s r<1, >, v<0, >, t<3, vector, >, s<5>, r<0, >, , + +0x910000e9, 0x80003801, 0x800000c2, 0x00155543, +0x00100012, 0x00000001, 0x0000d000, 0x00101046, +0x00000000, 0x00107006, 0x00000003, 0x00106000, +0x00000005, 0x0010000a, 0x00000000, 0x00004001, +0x3f000000 diff --git a/mlir/test/Target/DXSA/sample_c_lz.test b/mlir/test/Target/DXSA/sample_c_lz.test new file mode 100644 index 000000000000..0219c6b7962c --- /dev/null +++ b/mlir/test/Target/DXSA/sample_c_lz.test @@ -0,0 +1,17 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.sample_c_lz r<0, >, v<0, >, t<3, vector, >, s<5>, r<0, > + +0x8d000047, 0x800000c2, 0x00155543, 0x00100022, +0x00000000, 0x00101046, 0x00000000, 0x00107006, +0x00000003, 0x00106000, 0x00000005, 0x0010000a, +0x00000000 + +// CHECK: dxsa.sample_c_lz_s r<1, >, v<0, >, t<3, vector, >, s<5>, r<0, >, , + +0x910000e5, 0x80003801, 0x800000c2, 0x00155543, +0x00100012, 0x00000001, 0x0000d000, 0x00101046, +0x00000000, 0x00107006, 0x00000003, 0x00106000, +0x00000005, 0x0010000a, 0x00000000, 0x00004001, +0x3f000000 diff --git a/mlir/test/Target/DXSA/sample_d.test b/mlir/test/Target/DXSA/sample_d.test new file mode 100644 index 000000000000..2f2337c27a4a --- /dev/null +++ b/mlir/test/Target/DXSA/sample_d.test @@ -0,0 +1,17 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.sample_d r<0>, v<0, >, t<3, vector>, s<5>, v<0, >, v<0, > + +0x8f000049, 0x800000c2, 0x00155543, 0x001000f2, +0x00000000, 0x00101046, 0x00000000, 0x00107e46, +0x00000003, 0x00106000, 0x00000005, 0x00101556, +0x00000000, 0x00101516, 0x00000000 + +// CHECK: dxsa.sample_d_cl_s r<1>, v<0, >, t<3, vector>, s<5>, v<0, >, v<0, >, , + +0x930000e8, 0x80003801, 0x800000c2, 0x00155543, +0x001000f2, 0x00000001, 0x0000d000, 0x00101046, +0x00000000, 0x00107e46, 0x00000003, 0x00106000, +0x00000005, 0x00101556, 0x00000000, 0x00101516, +0x00000000, 0x00004001, 0x3f000000 \ No newline at end of file diff --git a/mlir/test/Target/DXSA/sample_l.test b/mlir/test/Target/DXSA/sample_l.test new file mode 100644 index 000000000000..58c677a80d6f --- /dev/null +++ b/mlir/test/Target/DXSA/sample_l.test @@ -0,0 +1,30 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.sample_l r<0>, v<0, >, t<3, vector>, s<5>, v<0, > + +0x8d000048, 0x800000c2, 0x00155543, 0x001000f2, +0x00000000, 0x00101046, 0x00000000, 0x00107e46, +0x00000003, 0x00106000, 0x00000005, 0x0010101a, +0x00000000 + +// CHECK: dxsa.sample_l r<1>, v<0, >, t<3, vector>, s<5>, v<0, >, + +0x8e000048, 0x8000f601, 0x800000c2, 0x00155543, +0x001000f2, 0x00000001, 0x00101046, 0x00000000, +0x00107e46, 0x00000003, 0x00106000, 0x00000005, +0x0010101a, 0x00000000 + +// CHECK: dxsa.sample_l_cl_s r<1>, v<0>, t<5, vector>, s<5>, v<0, >, r<2, > + +0x8f0000e4, 0x80000282, 0x00155543, 0x001000f2, +0x00000001, 0x00100012, 0x00000002, 0x00101e46, +0x00000000, 0x00107e46, 0x00000005, 0x00106000, +0x00000005, 0x0010101a, 0x00000000 + +// CHECK: dxsa.sample_l_cl_s r<1>, v<0, >, t<3, vector>, s<5>, v<0, >, r<2, >, + +0x900000e4, 0x80005a01, 0x800000c2, 0x00155543, +0x001000f2, 0x00000001, 0x00100012, 0x00000002, +0x00101046, 0x00000000, 0x00107e46, 0x00000003, +0x00106000, 0x00000005, 0x0010101a, 0x00000000 diff --git a/mlir/test/Target/DXSA/sample_offset_invalid.mlir b/mlir/test/Target/DXSA/sample_offset_invalid.mlir new file mode 100644 index 000000000000..e9a1cba1fb00 --- /dev/null +++ b/mlir/test/Target/DXSA/sample_offset_invalid.mlir @@ -0,0 +1,29 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{sample offsets must be 4 bit 2's complement numbers, having integer range [-8,7]}} +dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>, + +// ----- + +// expected-error@+1 {{sample offsets must be 4 bit 2's complement numbers, having integer range [-8,7]}} +dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>, + +// ----- + +// expected-error@+1 {{sample offsets must be 4 bit 2's complement numbers, having integer range [-8,7]}} +dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>, + +// ----- + +// expected-error@+1 {{sample offsets must be 4 bit 2's complement numbers, having integer range [-8,7]}} +dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>, + +// ----- + +// expected-error@+1 {{sample offsets must be 4 bit 2's complement numbers, having integer range [-8,7]}} +dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>, + +// ----- + +// expected-error@+1 {{sample offsets must be 4 bit 2's complement numbers, having integer range [-8,7]}} +dxsa.sample r<1>, v<0, >, t<3, vector>, s<5>,