diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 9d26894db8c5..9ad764c56b17 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -255,6 +255,64 @@ def DXSA_SystemValueNameAttr : let assemblyFormat = "`<` $value `>`"; } +def DXSA_ResourceDimension_Buffer : I32EnumAttrCase<"buffer", 1>; +def DXSA_ResourceDimension_Texture1D : I32EnumAttrCase<"texture1d", 2>; +def DXSA_ResourceDimension_Texture2D : I32EnumAttrCase<"texture2d", 3>; +def DXSA_ResourceDimension_Texture2DMS : I32EnumAttrCase<"texture2dms", 4>; +def DXSA_ResourceDimension_Texture3D : I32EnumAttrCase<"texture3d", 5>; +def DXSA_ResourceDimension_TextureCube : I32EnumAttrCase<"texturecube", 6>; +def DXSA_ResourceDimension_Texture1DArray : I32EnumAttrCase<"texture1darray", 7>; +def DXSA_ResourceDimension_Texture2DArray : I32EnumAttrCase<"texture2darray", 8>; +def DXSA_ResourceDimension_Texture2DMSArray : I32EnumAttrCase<"texture2dmsarray", 9>; +def DXSA_ResourceDimension_TextureCubeArray : I32EnumAttrCase<"texturecubearray", 10>; + +def DXSA_ResourceDimension : I32EnumAttr< + "ResourceDimension", "input resource dimension", [ + DXSA_ResourceDimension_Buffer, + DXSA_ResourceDimension_Texture1D, + DXSA_ResourceDimension_Texture2D, + DXSA_ResourceDimension_Texture2DMS, + DXSA_ResourceDimension_Texture3D, + DXSA_ResourceDimension_TextureCube, + DXSA_ResourceDimension_Texture1DArray, + DXSA_ResourceDimension_Texture2DArray, + DXSA_ResourceDimension_Texture2DMSArray, + DXSA_ResourceDimension_TextureCubeArray + ]> { + let cppNamespace = "::mlir::dxsa"; + let genSpecializedAttr = 0; +} + +def DXSA_ResourceDimensionAttr : + EnumAttr { + let assemblyFormat = "$value"; +} + +// `float` is a reserved C++ keyword, so the symbolic (C++ enum case) names use +// PascalCase while the printable asm form stays lowercase. +def DXSA_ResourceReturnType_Unorm : I32EnumAttrCase<"Unorm", 1, "unorm">; +def DXSA_ResourceReturnType_Snorm : I32EnumAttrCase<"Snorm", 2, "snorm">; +def DXSA_ResourceReturnType_Sint : I32EnumAttrCase<"Sint", 3, "sint">; +def DXSA_ResourceReturnType_Uint : I32EnumAttrCase<"Uint", 4, "uint">; +def DXSA_ResourceReturnType_Float : I32EnumAttrCase<"Float", 5, "float">; + +def DXSA_ResourceReturnType : I32EnumAttr< + "ResourceReturnType", "input resource per-component return type", [ + DXSA_ResourceReturnType_Unorm, + DXSA_ResourceReturnType_Snorm, + DXSA_ResourceReturnType_Sint, + DXSA_ResourceReturnType_Uint, + DXSA_ResourceReturnType_Float + ]> { + let cppNamespace = "::mlir::dxsa"; + let genSpecializedAttr = 0; +} + +def DXSA_ResourceReturnTypeAttr : + EnumAttr { + let assemblyFormat = "$value"; +} + //===----------------------------------------------------------------------===// // DXSA ComponentMask bit-enum (mask field of operand, normalized to bits 0..3) //===----------------------------------------------------------------------===// @@ -922,4 +980,46 @@ def DXSA_DclTgsmStructured : DXSA_Op<"dcl_tgsm_structured"> { let hasVerifier = 1; } +def DXSA_DclResource : DXSA_Op<"dcl_resource"> { + let summary = "declares a shader input resource bound to a register"; + let description = [{ + The `dxsa.dcl_resource` operation declares a shader input resource + bound to a register. + + Example: + + ```mlir + dxsa.dcl_resource , , + + dxsa.dcl_resource , , + + dxsa.dcl_resource , + , + ``` + }]; + + let arguments = (ins + I32Attr:$id, + DXSA_ResourceDimensionAttr:$dim, + DXSA_ResourceReturnTypeAttr:$x, + DXSA_ResourceReturnTypeAttr:$y, + DXSA_ResourceReturnTypeAttr:$z, + DXSA_ResourceReturnTypeAttr:$w, + OptionalAttr]>>:$sample_count, + OptionalAttr:$lbound, + OptionalAttr:$ubound, + OptionalAttr:$space); + let assemblyFormat = [{ + ` ` `<` `id` `=` $id + (`,` `lbound` `=` $lbound^ `,` `ubound` `=` $ubound + `,` `space` `=` $space)? `>` `,` + `<` `dim` `=` $dim + (`,` `sample_count` `=` $sample_count^)? `>` `,` + `<` `x` `=` $x `,` `y` `=` $y `,` `z` `=` $z `,` `w` `=` $w `>` + attr-dict + }]; + let hasVerifier = 1; +} + #endif // DXSA_OPS diff --git a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp index f703a32e48ea..5315ad55acaf 100644 --- a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp +++ b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp @@ -84,6 +84,25 @@ LogicalResult DclTgsmStructured::verify() { return success(); } +LogicalResult DclResource::verify() { + auto dim = getDim(); + bool isMultisampled = dim == ResourceDimension::texture2dms || + dim == ResourceDimension::texture2dmsarray; + if (isMultisampled && !getSampleCount()) + return emitOpError("missing sample_count for multisampled dimension ") + << stringifyResourceDimension(dim); + if (!isMultisampled && getSampleCount()) + return emitOpError("sample_count is only valid for texture2dms and " + "texture2dmsarray, got ") + << stringifyResourceDimension(dim); + auto lbound = getLbound(); + auto ubound = getUbound(); + if (lbound && ubound && *lbound > *ubound) + return emitOpError("expected lbound <= ubound, got lbound=") + << *lbound << ", ubound=" << *ubound; + return success(); +} + //===----------------------------------------------------------------------===// // TableGen'd attribute method definitions //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 1ac5161fbb96..5125f55f15a9 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -692,6 +692,20 @@ class DXBuilder { builder.getI32IntegerAttr(structCount)); } + Instruction buildDclResource( + uint32_t id, dxsa::ResourceDimension dim, dxsa::ResourceReturnType x, + dxsa::ResourceReturnType y, dxsa::ResourceReturnType z, + dxsa::ResourceReturnType w, std::optional sampleCount, + std::optional lbound, std::optional ubound, + std::optional space, Location loc) { + auto toAttr = [&](std::optional v) -> IntegerAttr { + return v ? builder.getI32IntegerAttr(*v) : IntegerAttr(); + }; + return dxsa::DclResource::create(builder, loc, id, dim, x, y, z, w, + toAttr(sampleCount), toAttr(lbound), + toAttr(ubound), toAttr(space)); + } + private: MLIRContext *context; ModuleOp module; @@ -1317,6 +1331,73 @@ class Parser { *structCount, loc); } + FailureOr + parseResourceReturnType(uint32_t returnTypeToken, uint32_t component, + Location loc) { + auto rawReturnType = + DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(returnTypeToken, component); + auto returnType = dxsa::symbolizeResourceReturnType(rawReturnType); + if (!returnType) + return emitError(loc, "unknown resource return type: ") << rawReturnType; + return *returnType; + } + + FailureOr parseDclResource(uint32_t opcodeToken, Location loc) { + auto rawDim = DECODE_D3D10_SB_RESOURCE_DIMENSION(opcodeToken); + auto dim = dxsa::symbolizeResourceDimension(rawDim); + if (!dim) + return emitError(loc, "unknown resource dimension: ") << rawDim; + + std::optional sampleCount; + if (*dim == dxsa::ResourceDimension::texture2dms || + *dim == dxsa::ResourceDimension::texture2dmsarray) { + auto rawSampleCount = DECODE_D3D10_SB_RESOURCE_SAMPLE_COUNT(opcodeToken); + if (rawSampleCount == 0) + return emitError(loc, "sample count must be non-zero for multisampled " + "dimension ") + << dxsa::stringifyResourceDimension(*dim); + sampleCount = rawSampleCount; + } + + auto operand = parseInlineOperand(); + FAILURE_IF_FAILED(operand); + if (operand->getType() != dxsa::InlineOperandType::resource) + return emitError(loc, "operand must be a resource register, got ") + << dxsa::stringifyInlineOperandType(operand->getType()); + auto indexArray = operand->getIndex(); + auto indexDim = indexArray ? indexArray.size() : 0; + if (indexDim != 1 && indexDim != 3) + return emitError(loc, "operand must have a 1D or 3D index, got ") + << indexDim; + auto id = indexArray[0]; + std::optional lbound, ubound; + if (indexDim == 3) { + lbound = indexArray[1]; + ubound = indexArray[2]; + } + + auto returnTypeToken = parseToken(); + FAILURE_IF_FAILED(returnTypeToken); + auto x = parseResourceReturnType(*returnTypeToken, 0, loc); + FAILURE_IF_FAILED(x); + auto y = parseResourceReturnType(*returnTypeToken, 1, loc); + FAILURE_IF_FAILED(y); + auto z = parseResourceReturnType(*returnTypeToken, 2, loc); + FAILURE_IF_FAILED(z); + auto w = parseResourceReturnType(*returnTypeToken, 3, loc); + FAILURE_IF_FAILED(w); + + std::optional space; + if (indexDim == 3) { + auto spaceToken = parseToken(); + FAILURE_IF_FAILED(spaceToken); + space = *spaceToken; + } + + return builder.buildDclResource(id, *dim, *x, *y, *z, *w, sampleCount, + lbound, ubound, space, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -1393,6 +1474,9 @@ class Parser { case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: result = parseDclTgsmStructured(loc); break; + case D3D10_SB_OPCODE_DCL_RESOURCE: + result = parseDclResource(opcodeToken, loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_resource.mlir b/mlir/test/Target/DXSA/dcl_resource.mlir new file mode 100644 index 000000000000..d94cba20cb48 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_resource.mlir @@ -0,0 +1,15 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_resource.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: dxsa.dcl_resource , , +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_resource_invalid.mlir b/mlir/test/Target/DXSA/dcl_resource_invalid.mlir new file mode 100644 index 000000000000..c15f271f88bf --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_resource_invalid.mlir @@ -0,0 +1,64 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{'dxsa.dcl_resource' op missing sample_count for multisampled dimension texture2dms}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op missing sample_count for multisampled dimension texture2dmsarray}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got buffer}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texture1d}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texture1darray}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texture2d}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texture2darray}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texture3d}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texturecube}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op sample_count is only valid for texture2dms and texture2dmsarray, got texturecubearray}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{attribute 'sample_count' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive whose maximum value is 127}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{attribute 'sample_count' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive whose maximum value is 127}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op expected lbound <= ubound, got lbound=5, ubound=3}} +dxsa.dcl_resource , , diff --git a/mlir/test/Target/DXSA/inputs/dcl_resource.bin b/mlir/test/Target/DXSA/inputs/dcl_resource.bin new file mode 100644 index 000000000000..358af69116a2 Binary files /dev/null and b/mlir/test/Target/DXSA/inputs/dcl_resource.bin differ