1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Assembler tests for instructions in the "Type-Declaration" section of the
16 // SPIR-V spec.
17
18 #include <string>
19 #include <vector>
20
21 #include "gmock/gmock.h"
22 #include "test/test_fixture.h"
23 #include "test/unit_spirv.h"
24
25 namespace spvtools {
26 namespace {
27
28 using spvtest::EnumCase;
29 using spvtest::MakeInstruction;
30 using ::testing::Eq;
31
32 // Test Dim enums via OpTypeImage
33
34 using DimTest =
35 spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvDim>>>;
36
TEST_P(DimTest,AnyDim)37 TEST_P(DimTest, AnyDim) {
38 const std::string input =
39 "%1 = OpTypeImage %2 " + GetParam().name() + " 2 3 0 4 Rgba8\n";
40 EXPECT_THAT(
41 CompiledInstructions(input),
42 Eq(MakeInstruction(SpvOpTypeImage, {1, 2, GetParam().value(), 2, 3, 0, 4,
43 SpvImageFormatRgba8})));
44
45 // Check the disassembler as well.
46 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
47 }
48
49 // clang-format off
50 #define CASE(NAME) {SpvDim##NAME, #NAME}
51 INSTANTIATE_TEST_SUITE_P(
52 TextToBinaryDim, DimTest,
53 ::testing::ValuesIn(std::vector<EnumCase<SpvDim>>{
54 CASE(1D),
55 CASE(2D),
56 CASE(3D),
57 CASE(Cube),
58 CASE(Rect),
59 CASE(Buffer),
60 CASE(SubpassData),
61 }));
62 #undef CASE
63 // clang-format on
64
TEST_F(DimTest,WrongDim)65 TEST_F(DimTest, WrongDim) {
66 EXPECT_THAT(CompileFailure("%i = OpTypeImage %t xxyyzz 1 2 3 4 R8"),
67 Eq("Invalid dimensionality 'xxyyzz'."));
68 }
69
70 // Test ImageFormat enums via OpTypeImage
71
72 using ImageFormatTest = spvtest::TextToBinaryTestBase<
73 ::testing::TestWithParam<EnumCase<SpvImageFormat>>>;
74
TEST_P(ImageFormatTest,AnyImageFormatAndNoAccessQualifier)75 TEST_P(ImageFormatTest, AnyImageFormatAndNoAccessQualifier) {
76 const std::string input =
77 "%1 = OpTypeImage %2 1D 2 3 0 4 " + GetParam().name() + "\n";
78 EXPECT_THAT(CompiledInstructions(input),
79 Eq(MakeInstruction(SpvOpTypeImage, {1, 2, SpvDim1D, 2, 3, 0, 4,
80 GetParam().value()})));
81 // Check the disassembler as well.
82 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
83 }
84
85 // clang-format off
86 #define CASE(NAME) {SpvImageFormat##NAME, #NAME}
87 INSTANTIATE_TEST_SUITE_P(
88 TextToBinaryImageFormat, ImageFormatTest,
89 ::testing::ValuesIn(std::vector<EnumCase<SpvImageFormat>>{
90 CASE(Unknown),
91 CASE(Rgba32f),
92 CASE(Rgba16f),
93 CASE(R32f),
94 CASE(Rgba8),
95 CASE(Rgba8Snorm),
96 CASE(Rg32f),
97 CASE(Rg16f),
98 CASE(R11fG11fB10f),
99 CASE(R16f),
100 CASE(Rgba16),
101 CASE(Rgb10A2),
102 CASE(Rg16),
103 CASE(Rg8),
104 CASE(R16),
105 CASE(R8),
106 CASE(Rgba16Snorm),
107 CASE(Rg16Snorm),
108 CASE(Rg8Snorm),
109 CASE(R16Snorm),
110 CASE(R8Snorm),
111 CASE(Rgba32i),
112 CASE(Rgba16i),
113 CASE(Rgba8i),
114 CASE(R32i),
115 CASE(Rg32i),
116 CASE(Rg16i),
117 CASE(Rg8i),
118 CASE(R16i),
119 CASE(R8i),
120 CASE(Rgba32ui),
121 CASE(Rgba16ui),
122 CASE(Rgba8ui),
123 CASE(R32ui),
124 CASE(Rgb10a2ui),
125 CASE(Rg32ui),
126 CASE(Rg16ui),
127 CASE(Rg8ui),
128 CASE(R16ui),
129 CASE(R8ui),
130 }));
131 #undef CASE
132 // clang-format on
133
TEST_F(ImageFormatTest,WrongFormat)134 TEST_F(ImageFormatTest, WrongFormat) {
135 EXPECT_THAT(CompileFailure("%r = OpTypeImage %t 1D 2 3 0 4 xxyyzz"),
136 Eq("Invalid image format 'xxyyzz'."));
137 }
138
139 // Test AccessQualifier enums via OpTypeImage.
140 using ImageAccessQualifierTest = spvtest::TextToBinaryTestBase<
141 ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>;
142
TEST_P(ImageAccessQualifierTest,AnyAccessQualifier)143 TEST_P(ImageAccessQualifierTest, AnyAccessQualifier) {
144 const std::string input =
145 "%1 = OpTypeImage %2 1D 2 3 0 4 Rgba8 " + GetParam().name() + "\n";
146 EXPECT_THAT(CompiledInstructions(input),
147 Eq(MakeInstruction(SpvOpTypeImage,
148 {1, 2, SpvDim1D, 2, 3, 0, 4,
149 SpvImageFormatRgba8, GetParam().value()})));
150 // Check the disassembler as well.
151 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
152 }
153
154 // clang-format off
155 #define CASE(NAME) {SpvAccessQualifier##NAME, #NAME}
156 INSTANTIATE_TEST_SUITE_P(
157 AccessQualifier, ImageAccessQualifierTest,
158 ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{
159 CASE(ReadOnly),
160 CASE(WriteOnly),
161 CASE(ReadWrite),
162 }));
163 // clang-format on
164 #undef CASE
165
166 // Test AccessQualifier enums via OpTypePipe.
167
168 using OpTypePipeTest = spvtest::TextToBinaryTestBase<
169 ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>;
170
TEST_P(OpTypePipeTest,AnyAccessQualifier)171 TEST_P(OpTypePipeTest, AnyAccessQualifier) {
172 const std::string input = "%1 = OpTypePipe " + GetParam().name() + "\n";
173 EXPECT_THAT(CompiledInstructions(input),
174 Eq(MakeInstruction(SpvOpTypePipe, {1, GetParam().value()})));
175 // Check the disassembler as well.
176 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
177 }
178
179 // clang-format off
180 #define CASE(NAME) {SpvAccessQualifier##NAME, #NAME}
181 INSTANTIATE_TEST_SUITE_P(
182 TextToBinaryTypePipe, OpTypePipeTest,
183 ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{
184 CASE(ReadOnly),
185 CASE(WriteOnly),
186 CASE(ReadWrite),
187 }));
188 #undef CASE
189 // clang-format on
190
TEST_F(OpTypePipeTest,WrongAccessQualifier)191 TEST_F(OpTypePipeTest, WrongAccessQualifier) {
192 EXPECT_THAT(CompileFailure("%1 = OpTypePipe xxyyzz"),
193 Eq("Invalid access qualifier 'xxyyzz'."));
194 }
195
196 using OpTypeForwardPointerTest = spvtest::TextToBinaryTest;
197
198 #define CASE(storage_class) \
199 do { \
200 EXPECT_THAT( \
201 CompiledInstructions("OpTypeForwardPointer %pt " #storage_class), \
202 Eq(MakeInstruction(SpvOpTypeForwardPointer, \
203 {1, SpvStorageClass##storage_class}))); \
204 } while (0)
205
TEST_F(OpTypeForwardPointerTest,ValidStorageClass)206 TEST_F(OpTypeForwardPointerTest, ValidStorageClass) {
207 CASE(UniformConstant);
208 CASE(Input);
209 CASE(Uniform);
210 CASE(Output);
211 CASE(Workgroup);
212 CASE(CrossWorkgroup);
213 CASE(Private);
214 CASE(Function);
215 CASE(Generic);
216 CASE(PushConstant);
217 CASE(AtomicCounter);
218 CASE(Image);
219 CASE(StorageBuffer);
220 }
221
222 #undef CASE
223
TEST_F(OpTypeForwardPointerTest,MissingType)224 TEST_F(OpTypeForwardPointerTest, MissingType) {
225 EXPECT_THAT(CompileFailure("OpTypeForwardPointer"),
226 Eq("Expected operand, found end of stream."));
227 }
228
TEST_F(OpTypeForwardPointerTest,MissingClass)229 TEST_F(OpTypeForwardPointerTest, MissingClass) {
230 EXPECT_THAT(CompileFailure("OpTypeForwardPointer %pt"),
231 Eq("Expected operand, found end of stream."));
232 }
233
TEST_F(OpTypeForwardPointerTest,WrongClass)234 TEST_F(OpTypeForwardPointerTest, WrongClass) {
235 EXPECT_THAT(CompileFailure("OpTypeForwardPointer %pt xxyyzz"),
236 Eq("Invalid storage class 'xxyyzz'."));
237 }
238
239 using OpSizeOfTest = spvtest::TextToBinaryTest;
240
241 // We should be able to assemble it. Validation checks are in another test
242 // file.
TEST_F(OpSizeOfTest,OpcodeAssemblesInV10)243 TEST_F(OpSizeOfTest, OpcodeAssemblesInV10) {
244 EXPECT_THAT(
245 CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_0),
246 Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3})));
247 }
248
TEST_F(OpSizeOfTest,ArgumentCount)249 TEST_F(OpSizeOfTest, ArgumentCount) {
250 EXPECT_THAT(
251 CompileFailure("OpSizeOf", SPV_ENV_UNIVERSAL_1_1),
252 Eq("Expected <result-id> at the beginning of an instruction, found "
253 "'OpSizeOf'."));
254 EXPECT_THAT(CompileFailure("%res = OpSizeOf OpNop", SPV_ENV_UNIVERSAL_1_1),
255 Eq("Expected operand, found next instruction instead."));
256 EXPECT_THAT(
257 CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_1),
258 Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3})));
259 EXPECT_THAT(
260 CompileFailure("%1 = OpSizeOf %2 %3 44 55 ", SPV_ENV_UNIVERSAL_1_1),
261 Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
262 "found '44'."));
263 }
264
TEST_F(OpSizeOfTest,ArgumentTypes)265 TEST_F(OpSizeOfTest, ArgumentTypes) {
266 EXPECT_THAT(CompileFailure("%1 = OpSizeOf 2 %3", SPV_ENV_UNIVERSAL_1_1),
267 Eq("Expected id to start with %."));
268 EXPECT_THAT(CompileFailure("%1 = OpSizeOf %2 \"abc\"", SPV_ENV_UNIVERSAL_1_1),
269 Eq("Expected id to start with %."));
270 }
271
272 // TODO(dneto): OpTypeVoid
273 // TODO(dneto): OpTypeBool
274 // TODO(dneto): OpTypeInt
275 // TODO(dneto): OpTypeFloat
276 // TODO(dneto): OpTypeVector
277 // TODO(dneto): OpTypeMatrix
278 // TODO(dneto): OpTypeImage
279 // TODO(dneto): OpTypeSampler
280 // TODO(dneto): OpTypeSampledImage
281 // TODO(dneto): OpTypeArray
282 // TODO(dneto): OpTypeRuntimeArray
283 // TODO(dneto): OpTypeStruct
284 // TODO(dneto): OpTypeOpaque
285 // TODO(dneto): OpTypePointer
286 // TODO(dneto): OpTypeFunction
287 // TODO(dneto): OpTypeEvent
288 // TODO(dneto): OpTypeDeviceEvent
289 // TODO(dneto): OpTypeReserveId
290 // TODO(dneto): OpTypeQueue
291
292 } // namespace
293 } // namespace spvtools
294