Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions mlir/include/mlir/Dialect/DXSA/IR/DXSAResourceOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,201 @@

include "mlir/Dialect/DXSA/IR/DXSAOpBase.td"

//===----------------------------------------------------------------------===//
// dxsa.bufinfo
//===----------------------------------------------------------------------===//

def DXSA_BufInfo : DXSA_UnaryOp<"bufinfo"> {
let summary = "query the element count on a Buffer (but not Constant Buffer)";
let description = [{
srcResource (`$src`) can be a Buffer (not a Constant Buffer) in an
SRV (`t#`) or UAV (`u#`).

All components in `$dst` receive the integer number of elements in the
Buffer’s Shader Resource View. The number of elements depends on the
view parameters such as memory format.

For a Typed Buffer SRV or UAV, the return value is the number of elements
in the View (where an element is one unit of the typed format).

For a Raw Buffer SRV or UAV, the return value is the number of bytes in
the view.

For a Structured Buffer SRV or UAV, the return value is the number of
structures in the view.

Example:

```mlir
dxsa.bufinfo r<0, <x>>, t<0, vector>
dxsa.bufinfo r<0, <y>>, u<1, vector, <y, x, z, w>>
```
}];
}

//===----------------------------------------------------------------------===//
// dxsa.resinfo
//===----------------------------------------------------------------------===//

def DXSA_ResInfo : DXSA_BinaryOp<"resinfo"> {
let summary = "query the dimensions of a given input resource.";
let description = [{
The `dxsa.resinfo` queries the dimensions of a given input resource.

srcMipLevel (`$lhs`) is read as an unsigned integer scalar
(so a single component selector is required for the
source register, if it is not a scalar immediate value).
srcResource (`$rhs`) is a `t#` or `u#` input texture for which the
dimensions are being queried.
`$dst` receives [width, height, depth or array size, total-mip-count],
selected by the write mask.

Returned values are all floating point, unless the `_uint` modifier is used,
in which case the returned values are all integers. If the `_rcpFloat`
modifier is used, all returned values are floating point, and the width,
height and depth are returned as reciprocals (1.0f/width, 1.0f/height,
1.0f/depth), including INF if width/height/depth are 0 (from out-of-range
srcMipLevel behavior above). Note that the `_rcpFloat` modifier only applies
to width, height, and depth returned values (and does not apply to values
that are set to 0 and thus not returned, and also does not apply to array
size returns).

For more information, see Direct3D 11.3 Functional Specification, 22.4.14.

Example:

```mlir
dxsa.resinfo r<0>, r<1, <x>>, r<2>
dxsa.resinfo r<0, <x>>, r<1, <x>>, r<2, <x, x, x, x>>
```
}];
}

def DXSA_ResInfoUInt : DXSA_BinaryOp<"resinfo_uint"> {
let summary = "query the dimensions of a given input resource.";
let description = [{
The `dxsa.resinfo_uint` queries the dimensions of a given input resource.
Returned values are all integer.

See `dxsa.resinfo` for more info.

Example:

```mlir
dxsa.resinfo_uint r<0>, r<1, <x>>, r<2>
dxsa.resinfo_uint r<0, <x>>, r<1, <x>>, r<2, <x, x, x, x>>
```
}];
}

def DXSA_ResInfoRcpFloat : DXSA_BinaryOp<"resinfo_rcpFloat"> {
let summary = "query the dimensions of a given input resource.";
let description = [{
The `dxsa.resinfo_rcpFloat` queries the dimensions of a given input resource.
All returned values are floating point, and the width, height and depth are
returned as reciprocals (1.0f/width, 1.0f/height, 1.0f/depth),
including INF if width/height/depth are 0 (from out-of-range srcMipLevel
behavior above).
Note that the `_rcpFloat` modifier only applies to width, height, and depth
returned values (and does not apply to values that are set to 0 and thus
not returned, and also does not apply to array size returns).

See `dxsa.resinfo` for more info.

Example:

```mlir
dxsa.resinfo_rcpFloat r<0>, r<1, <x>>, r<2>
dxsa.resinfo_rcpFloat r<0, <x>>, r<1, <x>>, r<2, <x, x, x, x>>
```
}];
}

//===----------------------------------------------------------------------===//
// dxsa.sampleinfo
//===----------------------------------------------------------------------===//

def DXSA_SampleInfo : DXSA_UnaryOp<"sampleinfo"> {
let summary = "query the number of samples in a given shader resource view "
"or in the rasterizer";
let description = [{
The `dxsa.sampleinfo` returns the number of samples for the given resource
or the rasterizer. Only valid for resources that can be loaded using `ld2dms`
unless the "rasterizer" is specified as `$src`.
`$src` could be `t#` register (a shader resource view) or "rasterizer" register.

The instruction computes the following vector (SampleCount,0,0,0).
The swizzle on srcResource allows the returned values to be swizzled
arbitrarily before they are written to the destination.
If there is no resource bound to the specified slot, 0 is returned.
Returned value is floating point.

Example:

```mlir
dxsa.sampleinfo r<0>, r<1>
dxsa.sampleinfo o<0, <x, y>>, rasterizer<vector, <x>>
```
}];
}

def DXSA_SampleInfoUInt : DXSA_UnaryOp<"sampleinfo_uint"> {
let summary = "query the number of samples in a given shader resource view "
"or in the rasterizer";
let description = [{
The `dxsa.sampleinfo_uint` returns the number of samples for the given resource
or the rasterizer. Only valid for resources that can be loaded using `ld2dms`
unless the "rasterizer" is specified as `$src`.
`$src` could be `t#` register (a shader resource view) or "rasterizer" register.

The instruction computes the following vector (SampleCount,0,0,0).
The swizzle on srcResource allows the returned values to be swizzled
arbitrarily before they are written to the destination.
If there is no resource bound to the specified slot, 0 is returned.
Returned value is integer.

Example:

```mlir
dxsa.sampleinfo_uint r<0>, r<1>
dxsa.sampleinfo_uint o<0, <x, y>>, rasterizer<vector, <x>>
```
}];
}

//===----------------------------------------------------------------------===//
// dxsa.samplepos
//===----------------------------------------------------------------------===//

def DXSA_SamplePos : DXSA_BinaryOp<"samplepos"> {
let summary = "query the position of a sample in a given shader resource "
"view or in the rasterizer.";
let description = [{
The `dxsa.samplepos` returns the 2D sample position of sample
sampleIndex (`$rhs`) for the given resource. Only valid for resources that
can be loaded using `ld2dms` unless the "rasterizer" is specified as
srcResource (`$lhs`).

srcResource could be t# register (a shader resource view) or "rasterizer" register.

The instruction computes the following floating point vector (Xposition, Yposition, 0, 0).

The swizzle on srcResource allows the returned values to be swizzled arbitrarily
before they are written to the destination.
The sample position is relative to the pixel's center, based on the Pixel Coordinate System (3.3.1).

If sampleIndex is out of bounds a zero vector is returned.
If there is no resource bound to the specified slot, 0 is returned.

Example:

```mlir
dxsa.samplepos r<0>, r<1>, l(0x2)
dxsa.samplepos r<0>, r<1>, r<2, <x, x, x, x>>
```
}];
}

//===----------------------------------------------------------------------===//
// dxsa.eval_centroid
//===----------------------------------------------------------------------===//
Expand Down
41 changes: 39 additions & 2 deletions mlir/lib/Target/DXSA/BinaryParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3410,6 +3410,34 @@ class Parser {
case D3D11_SB_OPCODE_EMITTHENCUT_STREAM:
return STREAM_INDEX_OP(EmitThenCutStream);
// Resource instructions
case D3D11_SB_OPCODE_BUFINFO:
return PLAIN_OP(BufInfo, 1, 1, HasPreciseAttr::Yes);
case D3D10_SB_OPCODE_RESINFO: {
D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE resinfo_type =
DECODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(*opcodeToken0);
switch (resinfo_type) {
case D3D10_SB_RESINFO_INSTRUCTION_RETURN_FLOAT:
return PLAIN_OP(ResInfo, 1, 2, HasPreciseAttr::Yes);
case D3D10_SB_RESINFO_INSTRUCTION_RETURN_RCPFLOAT:
return PLAIN_OP(ResInfoRcpFloat, 1, 2, HasPreciseAttr::Yes);
case D3D10_SB_RESINFO_INSTRUCTION_RETURN_UINT:
return PLAIN_OP(ResInfoUInt, 1, 2, HasPreciseAttr::Yes);
}
llvm_unreachable("unhandled resinfo");
}
case D3D10_1_SB_OPCODE_SAMPLE_INFO: {
D3D10_SB_INSTRUCTION_RETURN_TYPE sampleinfo_type =
DECODE_D3D10_SB_INSTRUCTION_RETURN_TYPE(*opcodeToken0);
switch (sampleinfo_type) {
case D3D10_SB_INSTRUCTION_RETURN_FLOAT:
return PLAIN_OP(SampleInfo, 1, 1, HasPreciseAttr::Yes);
case D3D10_SB_INSTRUCTION_RETURN_UINT:
return PLAIN_OP(SampleInfoUInt, 1, 1, HasPreciseAttr::Yes);
}
llvm_unreachable("unhandled sampleinfo");
}
case D3D10_1_SB_OPCODE_SAMPLE_POS:
return PLAIN_OP(SamplePos, 1, 2, HasPreciseAttr::Yes);
case D3D11_SB_OPCODE_EVAL_CENTROID:
return PLAIN_OP(EvalCentroid, 1, 1, HasPreciseAttr::Yes);
case D3D11_SB_OPCODE_EVAL_SAMPLE_INDEX:
Expand Down Expand Up @@ -3668,10 +3696,19 @@ class Parser {
}

LogicalResult verifyInstructionLength(size_t beginOffset, uint32_t length) {
if (((currentTokenOffset - beginOffset) / tokenSize) != length) {
emitError(getLocation(), "instruction length mismatch");
// WORKAROUND: some instructions such as samplepos have trailing
// tokens that do not correspond to any operands. Therefore we
// allow actual instruction length to be less then length read
// from the opcode token.
if (((currentTokenOffset - beginOffset) / tokenSize) > length) {
emitError(getLocation(), "operands did not fit into instruction length");
return failure();
}
// WORKAROUND: skip unparsed tokens in the end. See above.
while (((currentTokenOffset - beginOffset) / tokenSize) < length) {
auto token = parseToken();
FAILURE_IF_FAILED(token);
}
return success();
}

Expand Down
36 changes: 6 additions & 30 deletions mlir/test/Target/DXSA/hlsl/bufinfo.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,18 @@
// CHECK: dxsa.dcl_uav_typed <id = 3, dim = buffer>, <x = sint, y = sint, z = sint, w = sint>
// CHECK: dxsa.dcl_output o<0, <x>>
// CHECK: dxsa.dcl_temps 1
// CHECK: %[[INDEX_0:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_0:.*]] = dxsa.operand %[[INDEX_0]] {mask = 16 : i32, num_components = 4 : i32, type = 0 : i32}
// CHECK: %[[INDEX_1:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_1:.*]] = dxsa.operand %[[INDEX_1]] {num_components = 4 : i32, swizzle = dense<[0, 1, 2, 3]> : vector<4xi32>, type = 7 : i32}
// CHECK: dxsa.instruction "bufinfo" %[[OPERAND_0]], %[[OPERAND_1]]
// CHECK: dxsa.bufinfo r<0, <x>>, t<0, vector>
// CHECK: dxsa.iadd r<0, <x>>, r<0, <x>>, l(0x34)
// CHECK: %[[INDEX_2:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_2:.*]] = dxsa.operand %[[INDEX_2]] {mask = 32 : i32, num_components = 4 : i32, type = 0 : i32}
// CHECK: %[[INDEX_3:.*]] = dxsa.index.imm {imm = 1 : i32}
// CHECK: %[[OPERAND_3:.*]] = dxsa.operand %[[INDEX_3]] {num_components = 4 : i32, swizzle = dense<[1, 0, 2, 3]> : vector<4xi32>, type = 30 : i32}
// CHECK: dxsa.instruction "bufinfo" %[[OPERAND_2]], %[[OPERAND_3]]
// CHECK: dxsa.bufinfo r<0, <y>>, u<1, vector, <y, x, z, w>>
// CHECK: dxsa.iadd r<0, <x>>, r<0, <x>>, r<0, <y>>
// CHECK: dxsa.iadd r<0, <x>>, r<0, <x>>, l(0x34)
// CHECK: %[[INDEX_4:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_4:.*]] = dxsa.operand %[[INDEX_4]] {mask = 32 : i32, num_components = 4 : i32, type = 0 : i32}
// CHECK: %[[INDEX_5:.*]] = dxsa.index.imm {imm = 1 : i32}
// CHECK: %[[OPERAND_5:.*]] = dxsa.operand %[[INDEX_5]] {num_components = 4 : i32, swizzle = dense<[1, 0, 2, 3]> : vector<4xi32>, type = 7 : i32}
// CHECK: dxsa.instruction "bufinfo" %[[OPERAND_4]], %[[OPERAND_5]]
// CHECK: dxsa.bufinfo r<0, <y>>, t<1, vector, <y, x, z, w>>
// CHECK: dxsa.iadd r<0, <x>>, r<0, <y>>, r<0, <x>>
// CHECK: %[[INDEX_6:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_6:.*]] = dxsa.operand %[[INDEX_6]] {mask = 32 : i32, num_components = 4 : i32, type = 0 : i32}
// CHECK: %[[INDEX_7:.*]] = dxsa.index.imm {imm = 2 : i32}
// CHECK: %[[OPERAND_7:.*]] = dxsa.operand %[[INDEX_7]] {num_components = 4 : i32, swizzle = dense<[1, 0, 2, 3]> : vector<4xi32>, type = 30 : i32}
// CHECK: dxsa.instruction "bufinfo" %[[OPERAND_6]], %[[OPERAND_7]]
// CHECK: dxsa.bufinfo r<0, <y>>, u<2, vector, <y, x, z, w>>
// CHECK: dxsa.iadd r<0, <x>>, r<0, <y>>, r<0, <x>>
// CHECK: %[[INDEX_8:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_8:.*]] = dxsa.operand %[[INDEX_8]] {mask = 32 : i32, num_components = 4 : i32, type = 0 : i32}
// CHECK: %[[INDEX_9:.*]] = dxsa.index.imm {imm = 2 : i32}
// CHECK: %[[OPERAND_9:.*]] = dxsa.operand %[[INDEX_9]] {num_components = 4 : i32, swizzle = dense<[1, 0, 2, 3]> : vector<4xi32>, type = 7 : i32}
// CHECK: dxsa.instruction "bufinfo" %[[OPERAND_8]], %[[OPERAND_9]]
// CHECK: dxsa.bufinfo r<0, <y>>, t<2, vector, <y, x, z, w>>
// CHECK: dxsa.iadd r<0, <x>>, r<0, <y>>, r<0, <x>>
// CHECK: %[[INDEX_10:.*]] = dxsa.index.imm {imm = 0 : i32}
// CHECK: %[[OPERAND_10:.*]] = dxsa.operand %[[INDEX_10]] {mask = 32 : i32, num_components = 4 : i32, type = 0 : i32}
// CHECK: %[[INDEX_11:.*]] = dxsa.index.imm {imm = 3 : i32}
// CHECK: %[[OPERAND_11:.*]] = dxsa.operand %[[INDEX_11]] {num_components = 4 : i32, swizzle = dense<[1, 0, 2, 3]> : vector<4xi32>, type = 30 : i32}
// CHECK: dxsa.instruction "bufinfo" %[[OPERAND_10]], %[[OPERAND_11]]
// CHECK: dxsa.bufinfo r<0, <y>>, u<3, vector, <y, x, z, w>>
// CHECK: dxsa.iadd o<0, <x>>, r<0, <y>>, r<0, <x>>
// CHECK: dxsa.ret

Loading