Skip to content

Commit ac82abe

Browse files
committed
[mlir][spirv] Add definition for ImageWriteOp
1 parent 3bd11b5 commit ac82abe

File tree

5 files changed

+163
-6
lines changed

5 files changed

+163
-6
lines changed

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,6 +4362,7 @@ def SPIRV_OC_OpCompositeExtract : I32EnumAttrCase<"OpCompositeExtrac
43624362
def SPIRV_OC_OpCompositeInsert : I32EnumAttrCase<"OpCompositeInsert", 82>;
43634363
def SPIRV_OC_OpTranspose : I32EnumAttrCase<"OpTranspose", 84>;
43644364
def SPIRV_OC_OpImageDrefGather : I32EnumAttrCase<"OpImageDrefGather", 97>;
4365+
def SPIRV_OC_OpImageWrite : I32EnumAttrCase<"OpImageWrite", 99>;
43654366
def SPIRV_OC_OpImage : I32EnumAttrCase<"OpImage", 100>;
43664367
def SPIRV_OC_OpImageQuerySize : I32EnumAttrCase<"OpImageQuerySize", 104>;
43674368
def SPIRV_OC_OpConvertFToU : I32EnumAttrCase<"OpConvertFToU", 109>;
@@ -4558,10 +4559,10 @@ def SPIRV_OpcodeAttr :
45584559
SPIRV_OC_OpVectorInsertDynamic, SPIRV_OC_OpVectorShuffle,
45594560
SPIRV_OC_OpCompositeConstruct, SPIRV_OC_OpCompositeExtract,
45604561
SPIRV_OC_OpCompositeInsert, SPIRV_OC_OpTranspose, SPIRV_OC_OpImageDrefGather,
4561-
SPIRV_OC_OpImage, SPIRV_OC_OpImageQuerySize, SPIRV_OC_OpConvertFToU,
4562-
SPIRV_OC_OpConvertFToS, SPIRV_OC_OpConvertSToF, SPIRV_OC_OpConvertUToF,
4563-
SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert, SPIRV_OC_OpFConvert,
4564-
SPIRV_OC_OpConvertPtrToU, SPIRV_OC_OpConvertUToPtr,
4562+
SPIRV_OC_OpImageWrite, SPIRV_OC_OpImage, SPIRV_OC_OpImageQuerySize,
4563+
SPIRV_OC_OpConvertFToU, SPIRV_OC_OpConvertFToS, SPIRV_OC_OpConvertSToF,
4564+
SPIRV_OC_OpConvertUToF, SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert,
4565+
SPIRV_OC_OpFConvert, SPIRV_OC_OpConvertPtrToU, SPIRV_OC_OpConvertUToPtr,
45654566
SPIRV_OC_OpPtrCastToGeneric, SPIRV_OC_OpGenericCastToPtr,
45664567
SPIRV_OC_OpGenericCastToPtrExplicit, SPIRV_OC_OpBitcast, SPIRV_OC_OpSNegate,
45674568
SPIRV_OC_OpFNegate, SPIRV_OC_OpIAdd, SPIRV_OC_OpFAdd, SPIRV_OC_OpISub,

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVImageOps.td

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,58 @@ def SPIRV_ImageQuerySizeOp : SPIRV_Op<"ImageQuerySize", [Pure]> {
135135

136136
// -----
137137

138+
def SPIRV_ImageWriteOp : SPIRV_Op<"ImageWrite", []> {
139+
let summary = "Write a texel to an image without a sampler.";
140+
141+
let description = [{
142+
Image must be an object whose type is OpTypeImage with a Sampled operand
143+
of 0 or 2. If the Arrayed operand is 1, then additional capabilities may
144+
be required; e.g., ImageCubeArray, or ImageMSArray. Its Dim operand
145+
must not be SubpassData.
146+
147+
Coordinate must be a scalar or vector of floating-point type or integer
148+
type. It contains non-normalized texel coordinates (u[, v] ... [, array
149+
layer]) as needed by the definition of Image. See the client API
150+
specification for handling of coordinates outside the image.
151+
152+
Texel is the data to write. It must be a scalar or vector with component
153+
type the same as Sampled Type of the OpTypeImage (unless that Sampled
154+
Type is OpTypeVoid).
155+
156+
The Image Format must not be Unknown, unless the
157+
StorageImageWriteWithoutFormat Capability was declared.
158+
159+
Image Operands encodes what operands follow, as per Image Operands.
160+
161+
<!-- End of AutoGen section -->
162+
163+
#### Example:
164+
165+
```mlir
166+
spirv.ImageWrite %0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %1 : vector<2xsi32>, %2 : vector<4xf32>
167+
```
168+
}];
169+
170+
let arguments = (ins
171+
SPIRV_AnyImage:$image,
172+
AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>:$coordinate,
173+
AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>:$texel,
174+
OptionalAttr<SPIRV_ImageOperandsAttr>:$image_operands,
175+
Variadic<SPIRV_Type>:$operand_arguments
176+
);
177+
178+
let results = (outs);
179+
180+
let assemblyFormat = [{$image `:` type($image) `,`
181+
$coordinate `:` type($coordinate) `,`
182+
$texel `:` type($texel)
183+
custom<ImageOperands>($image_operands)
184+
( `(` $operand_arguments^ `:` type($operand_arguments) `)`)?
185+
attr-dict}];
186+
}
187+
188+
// -----
189+
138190
def SPIRV_ImageOp : SPIRV_Op<"Image",
139191
[Pure,
140192
TypesMatchWith<"type of 'result' matches image type of 'sampledimage'",

mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,45 @@ LogicalResult spirv::ImageDrefGatherOp::verify() {
20422042
return verifyImageOperands(*this, attr, operandArguments);
20432043
}
20442044

2045+
//===----------------------------------------------------------------------===//
2046+
// spirv.ImageWriteOp
2047+
//===----------------------------------------------------------------------===//
2048+
2049+
LogicalResult spirv::ImageWriteOp::verify() {
2050+
ImageType imageType = cast<ImageType>(getImage().getType());
2051+
Type sampledType = imageType.getElementType();
2052+
ImageSamplerUseInfo samplerInfo = imageType.getSamplerUseInfo();
2053+
2054+
if (!llvm::is_contained({spirv::ImageSamplerUseInfo::SamplerUnknown,
2055+
spirv::ImageSamplerUseInfo::NoSampler},
2056+
samplerInfo)) {
2057+
return emitOpError(
2058+
"the sampled operand of the underlying image must be 0 or 2");
2059+
}
2060+
2061+
// TODO: Do we need check for: "If the Arrayed operand is 1, then additional
2062+
// capabilities may be required; e.g., ImageCubeArray, or ImageMSArray."?
2063+
2064+
if (imageType.getDim() == spirv::Dim::SubpassData) {
2065+
return emitOpError(
2066+
"the Dim operand of the underlying image must not be SubpassData");
2067+
}
2068+
2069+
Type texelType = getElementTypeOrSelf(getTexel());
2070+
if (!isa<NoneType>(sampledType) && texelType != sampledType) {
2071+
return emitOpError(
2072+
"the texel component type must match the image sampled type");
2073+
}
2074+
2075+
// TODO: Ideally it should be somewhere verified that "The Image Format must
2076+
// not be Unknown, unless the StorageImageWriteWithoutFormat Capability was
2077+
// declared." This function however may not be the suitable place for such
2078+
// verification.
2079+
2080+
return verifyImageOperands(*this, getImageOperandsAttr(),
2081+
getOperandArguments());
2082+
}
2083+
20452084
//===----------------------------------------------------------------------===//
20462085
// spirv.ShiftLeftLogicalOp
20472086
//===----------------------------------------------------------------------===//

mlir/test/Dialect/SPIRV/IR/image-ops.mlir

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,45 @@ func.func @image_query_size_error_result2(%arg0 : !spirv.image<f32, Buffer, NoDe
115115
}
116116

117117
// -----
118+
119+
//===----------------------------------------------------------------------===//
120+
// spirv.ImageWrite
121+
//===----------------------------------------------------------------------===//
122+
123+
func.func @image_write(%arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>) -> () {
124+
// CHECK: spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
125+
spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
126+
spirv.Return
127+
}
128+
129+
// -----
130+
131+
func.func @image_write_scalar_texel(%arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : f32) -> () {
132+
// CHECK: spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : f32
133+
spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : f32
134+
spirv.Return
135+
}
136+
137+
// -----
138+
139+
func.func @image_write_need_sampler(%arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>) -> () {
140+
// expected-error @+1 {{the sampled operand of the underlying image must be 0 or 2}}
141+
spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
142+
spirv.Return
143+
}
144+
145+
// -----
146+
147+
func.func @image_write_subpass_data(%arg0 : !spirv.image<f32, SubpassData, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>) -> () {
148+
// expected-error @+1 {{the Dim operand of the underlying image must not be SubpassData}}
149+
spirv.ImageWrite %arg0 : !spirv.image<f32, SubpassData, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
150+
spirv.Return
151+
}
152+
153+
// -----
154+
155+
func.func @image_write_texel_type_mismatch(%arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xi32>) -> () {
156+
// expected-error @+1 {{the texel component type must match the image sampled type}}
157+
spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, %arg1 : vector<2xsi32>, %arg2 : vector<4xi32>
158+
spirv.Return
159+
}

mlir/test/Target/SPIRV/image-ops.mlir

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: mlir-translate -no-implicit-module -test-spirv-roundtrip %s | FileCheck %s
1+
// RUN: mlir-translate --no-implicit-module --split-input-file --test-spirv-roundtrip %s | FileCheck %s
22

3-
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
3+
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, ImageQuery], []> {
44
spirv.func @image(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>, %arg1 : vector<4xf32>, %arg2 : f32) "None" {
55
// CHECK: {{%.*}} = spirv.Image {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>
66
%0 = spirv.Image %arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>
@@ -13,4 +13,27 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
1313
%0 = spirv.ImageQuerySize %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown> -> vector<2xi32>
1414
spirv.Return
1515
}
16+
spirv.func @image_write(%arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba8>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>) "None" {
17+
// CHECK: spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba8>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
18+
spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba8>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
19+
spirv.Return
20+
}
21+
spirv.func @main() "None" {
22+
spirv.Return
23+
}
24+
spirv.EntryPoint "GLCompute" @main
25+
}
26+
27+
// -----
28+
29+
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, StorageImageWriteWithoutFormat], []> {
30+
spirv.func @image_write(%arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>) "None" {
31+
// CHECK: spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
32+
spirv.ImageWrite %arg0 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>, %arg1 : vector<2xsi32>, %arg2 : vector<4xf32>
33+
spirv.Return
34+
}
35+
spirv.func @main() "None" {
36+
spirv.Return
37+
}
38+
spirv.EntryPoint "GLCompute" @main
1639
}

0 commit comments

Comments
 (0)