diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 1d45d4d771d5..24ea0a037ba3 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -1172,4 +1172,34 @@ def DXSA_DclResource : DXSA_Op<"dcl_resource"> { let hasVerifier = 1; } +def DXSA_DclResourceStructured : DXSA_Op<"dcl_resource_structured"> { + let summary = "declares a structured buffer shader input resource bound to a register"; + let description = [{ + The `dxsa.dcl_resource_structured` operation declares a structured + buffer shader input resource bound to a register. + + Example: + + ```mlir + dxsa.dcl_resource_structured + dxsa.dcl_resource_structured + + ``` + }]; + + let arguments = (ins + I32Attr:$id, + ConfinedAttr:$struct_byte_stride, + OptionalAttr:$lbound, + OptionalAttr:$ubound, + OptionalAttr:$space); + let assemblyFormat = [{ + ` ` `<` `id` `=` $id `,` `struct_byte_stride` `=` $struct_byte_stride + (`,` `lbound` `=` $lbound^ `,` `ubound` `=` $ubound + `,` `space` `=` $space)? `>` + 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 8e8c73ea0f4e..d741607282b4 100644 --- a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp +++ b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp @@ -113,6 +113,33 @@ LogicalResult DclResource::verify() { return emitOpError("sample_count is only valid for texture2dms and " "texture2dmsarray, got ") << stringifyResourceDimension(dim); + auto lbound = getLbound(); + auto ubound = getUbound(); + auto space = getSpace(); + if ((lbound || ubound || space) && !(lbound && ubound && space)) + return emitOpError( + "lbound, ubound and space must be either all set or all absent"); + if (lbound && ubound && *lbound > *ubound) + return emitOpError("expected lbound <= ubound, got lbound=") + << *lbound << ", ubound=" << *ubound; + return success(); +} + +LogicalResult DclResourceStructured::verify() { + auto stride = getStructByteStride(); + if (stride % 4 != 0) + return emitOpError("struct byte stride must be a multiple of 4, got ") + << stride; + auto lbound = getLbound(); + auto ubound = getUbound(); + auto space = getSpace(); + if ((lbound || ubound || space) && !(lbound && ubound && space)) + return emitOpError( + "lbound, ubound and space must be either all set or all absent"); + if (lbound && ubound && *lbound > *ubound) + return emitOpError("expected lbound <= ubound, got lbound=") + << *lbound << ", ubound=" << *ubound; + return success(); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 22260aa53092..939406e4bb09 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -747,6 +747,19 @@ class DXBuilder { toAttr(ubound), toAttr(space)); } + Instruction buildDclResourceStructured(uint32_t id, uint32_t structByteStride, + 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::DclResourceStructured::create(builder, loc, id, + structByteStride, toAttr(lbound), + toAttr(ubound), toAttr(space)); + } + private: MLIRContext *context; ModuleOp module; @@ -1557,6 +1570,38 @@ class Parser { lbound, ubound, space, loc); } + FailureOr parseDclResourceStructured(Location loc) { + 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 strideToken = parseToken(); + FAILURE_IF_FAILED(strideToken); + + std::optional space; + if (indexDim == 3) { + auto spaceToken = parseToken(); + FAILURE_IF_FAILED(spaceToken); + space = *spaceToken; + } + + return builder.buildDclResourceStructured(id, *strideToken, lbound, ubound, + space, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -1651,6 +1696,9 @@ class Parser { case D3D10_SB_OPCODE_DCL_RESOURCE: result = parseDclResource(opcodeToken, loc); break; + case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED: + result = parseDclResourceStructured(loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_resource_invalid.mlir b/mlir/test/Target/DXSA/dcl_resource_invalid.mlir index c15f271f88bf..f1f50e95e52e 100644 --- a/mlir/test/Target/DXSA/dcl_resource_invalid.mlir +++ b/mlir/test/Target/DXSA/dcl_resource_invalid.mlir @@ -62,3 +62,56 @@ dxsa.dcl_resource , , , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op expected lbound <= ubound, got lbound=5, ubound=3}} +dxsa.dcl_resource , , + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource"() {id = 0 : i32, dim = #dxsa, + x = #dxsa, y = #dxsa, + z = #dxsa, w = #dxsa, + lbound = 0 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource"() {id = 0 : i32, dim = #dxsa, + x = #dxsa, y = #dxsa, + z = #dxsa, w = #dxsa, + ubound = 3 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource"() {id = 0 : i32, dim = #dxsa, + x = #dxsa, y = #dxsa, + z = #dxsa, w = #dxsa, + space = 1 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource"() {id = 0 : i32, dim = #dxsa, + x = #dxsa, y = #dxsa, + z = #dxsa, w = #dxsa, + lbound = 0 : i32, ubound = 3 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource"() {id = 0 : i32, dim = #dxsa, + x = #dxsa, y = #dxsa, + z = #dxsa, w = #dxsa, + lbound = 0 : i32, space = 1 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource"() {id = 0 : i32, dim = #dxsa, + x = #dxsa, y = #dxsa, + z = #dxsa, w = #dxsa, + ubound = 3 : i32, space = 1 : i32} : () -> () diff --git a/mlir/test/Target/DXSA/dcl_resource_structured.mlir b/mlir/test/Target/DXSA/dcl_resource_structured.mlir new file mode 100644 index 000000000000..de0258bc8f12 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_resource_structured.mlir @@ -0,0 +1,6 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_resource_structured.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_resource_structured +// CHECK-NEXT: dxsa.dcl_resource_structured +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_resource_structured_invalid.mlir b/mlir/test/Target/DXSA/dcl_resource_structured_invalid.mlir new file mode 100644 index 000000000000..6d453d644ea2 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_resource_structured_invalid.mlir @@ -0,0 +1,44 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op struct byte stride must be a multiple of 4, got 6}} +dxsa.dcl_resource_structured + +// ----- + +// expected-error@+1 {{attribute 'struct_byte_stride' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive}} +dxsa.dcl_resource_structured + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op expected lbound <= ubound, got lbound=5, ubound=3}} +dxsa.dcl_resource_structured + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource_structured"() {id = 0 : i32, struct_byte_stride = 16 : i32, lbound = 0 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource_structured"() {id = 0 : i32, struct_byte_stride = 16 : i32, ubound = 3 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource_structured"() {id = 0 : i32, struct_byte_stride = 16 : i32, space = 1 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource_structured"() {id = 0 : i32, struct_byte_stride = 16 : i32, lbound = 0 : i32, ubound = 3 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource_structured"() {id = 0 : i32, struct_byte_stride = 16 : i32, lbound = 0 : i32, space = 1 : i32} : () -> () + +// ----- + +// expected-error@+1 {{'dxsa.dcl_resource_structured' op lbound, ubound and space must be either all set or all absent}} +"dxsa.dcl_resource_structured"() {id = 0 : i32, struct_byte_stride = 16 : i32, ubound = 3 : i32, space = 1 : i32} : () -> () diff --git a/mlir/test/Target/DXSA/inputs/dcl_resource_structured.bin b/mlir/test/Target/DXSA/inputs/dcl_resource_structured.bin new file mode 100644 index 000000000000..c01d68c2b717 Binary files /dev/null and b/mlir/test/Target/DXSA/inputs/dcl_resource_structured.bin differ