• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Mode-Setting" section of the
16 // SPIR-V spec.
17 
18 #include <string>
19 #include <tuple>
20 #include <vector>
21 
22 #include "gmock/gmock.h"
23 #include "test/test_fixture.h"
24 #include "test/unit_spirv.h"
25 
26 namespace spvtools {
27 namespace {
28 
29 using spvtest::EnumCase;
30 using spvtest::MakeInstruction;
31 using spvtest::MakeVector;
32 using ::testing::Combine;
33 using ::testing::Eq;
34 using ::testing::TestWithParam;
35 using ::testing::Values;
36 using ::testing::ValuesIn;
37 
38 // Test OpMemoryModel
39 
40 // An example case for OpMemoryModel
41 struct MemoryModelCase {
get_addressing_valuespvtools::__anoned4781870111::MemoryModelCase42   uint32_t get_addressing_value() const {
43     return static_cast<uint32_t>(addressing_value);
44   }
get_memory_valuespvtools::__anoned4781870111::MemoryModelCase45   uint32_t get_memory_value() const {
46     return static_cast<uint32_t>(memory_value);
47   }
48   SpvAddressingModel addressing_value;
49   std::string addressing_name;
50   SpvMemoryModel memory_value;
51   std::string memory_name;
52 };
53 
54 using OpMemoryModelTest =
55     spvtest::TextToBinaryTestBase<TestWithParam<MemoryModelCase>>;
56 
TEST_P(OpMemoryModelTest,AnyMemoryModelCase)57 TEST_P(OpMemoryModelTest, AnyMemoryModelCase) {
58   const std::string input = "OpMemoryModel " + GetParam().addressing_name +
59                             " " + GetParam().memory_name;
60   EXPECT_THAT(
61       CompiledInstructions(input),
62       Eq(MakeInstruction(SpvOpMemoryModel, {GetParam().get_addressing_value(),
63                                             GetParam().get_memory_value()})));
64 }
65 
66 #define CASE(ADDRESSING, MEMORY)                                         \
67   {                                                                      \
68     SpvAddressingModel##ADDRESSING, #ADDRESSING, SpvMemoryModel##MEMORY, \
69         #MEMORY                                                          \
70   }
71 // clang-format off
72 INSTANTIATE_TEST_CASE_P(TextToBinaryMemoryModel, OpMemoryModelTest,
73                         ValuesIn(std::vector<MemoryModelCase>{
74                           // These cases exercise each addressing model, and
75                           // each memory model, but not necessarily in
76                           // combination.
77                             CASE(Logical,Simple),
78                             CASE(Logical,GLSL450),
79                             CASE(Physical32,OpenCL),
80                             CASE(Physical64,OpenCL),
81                         }),);
82 #undef CASE
83 // clang-format on
84 
TEST_F(OpMemoryModelTest,WrongModel)85 TEST_F(OpMemoryModelTest, WrongModel) {
86   EXPECT_THAT(CompileFailure("OpMemoryModel xxyyzz Simple"),
87               Eq("Invalid addressing model 'xxyyzz'."));
88   EXPECT_THAT(CompileFailure("OpMemoryModel Logical xxyyzz"),
89               Eq("Invalid memory model 'xxyyzz'."));
90 }
91 
92 // Test OpEntryPoint
93 
94 // An example case for OpEntryPoint
95 struct EntryPointCase {
get_execution_valuespvtools::__anoned4781870111::EntryPointCase96   uint32_t get_execution_value() const {
97     return static_cast<uint32_t>(execution_value);
98   }
99   SpvExecutionModel execution_value;
100   std::string execution_name;
101   std::string entry_point_name;
102 };
103 
104 using OpEntryPointTest =
105     spvtest::TextToBinaryTestBase<TestWithParam<EntryPointCase>>;
106 
TEST_P(OpEntryPointTest,AnyEntryPointCase)107 TEST_P(OpEntryPointTest, AnyEntryPointCase) {
108   // TODO(dneto): utf-8, escaping, quoting cases for entry point name.
109   const std::string input = "OpEntryPoint " + GetParam().execution_name +
110                             " %1 \"" + GetParam().entry_point_name + "\"";
111   EXPECT_THAT(
112       CompiledInstructions(input),
113       Eq(MakeInstruction(SpvOpEntryPoint, {GetParam().get_execution_value(), 1},
114                          MakeVector(GetParam().entry_point_name))));
115 }
116 
117 // clang-format off
118 #define CASE(NAME) SpvExecutionModel##NAME, #NAME
119 INSTANTIATE_TEST_CASE_P(TextToBinaryEntryPoint, OpEntryPointTest,
120                         ValuesIn(std::vector<EntryPointCase>{
121                           { CASE(Vertex), "" },
122                           { CASE(TessellationControl), "my tess" },
123                           { CASE(TessellationEvaluation), "really fancy" },
124                           { CASE(Geometry), "Euclid" },
125                           { CASE(Fragment), "FAT32" },
126                           { CASE(GLCompute), "cubic" },
127                           { CASE(Kernel), "Sanders" },
128                         }),);
129 #undef CASE
130 // clang-format on
131 
TEST_F(OpEntryPointTest,WrongModel)132 TEST_F(OpEntryPointTest, WrongModel) {
133   EXPECT_THAT(CompileFailure("OpEntryPoint xxyyzz %1 \"fun\""),
134               Eq("Invalid execution model 'xxyyzz'."));
135 }
136 
137 // Test OpExecutionMode
138 using OpExecutionModeTest = spvtest::TextToBinaryTestBase<
139     TestWithParam<std::tuple<spv_target_env, EnumCase<SpvExecutionMode>>>>;
140 
TEST_P(OpExecutionModeTest,AnyExecutionMode)141 TEST_P(OpExecutionModeTest, AnyExecutionMode) {
142   // This string should assemble, but should not validate.
143   std::stringstream input;
144   input << "OpExecutionMode %1 " << std::get<1>(GetParam()).name();
145   for (auto operand : std::get<1>(GetParam()).operands())
146     input << " " << operand;
147   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
148               Eq(MakeInstruction(SpvOpExecutionMode,
149                                  {1, std::get<1>(GetParam()).value()},
150                                  std::get<1>(GetParam()).operands())));
151 }
152 
153 #define CASE(NAME) SpvExecutionMode##NAME, #NAME
154 INSTANTIATE_TEST_CASE_P(
155     TextToBinaryExecutionMode, OpExecutionModeTest,
156     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
157             ValuesIn(std::vector<EnumCase<SpvExecutionMode>>{
158                 // The operand literal values are arbitrarily chosen,
159                 // but there are the right number of them.
160                 {CASE(Invocations), {101}},
161                 {CASE(SpacingEqual), {}},
162                 {CASE(SpacingFractionalEven), {}},
163                 {CASE(SpacingFractionalOdd), {}},
164                 {CASE(VertexOrderCw), {}},
165                 {CASE(VertexOrderCcw), {}},
166                 {CASE(PixelCenterInteger), {}},
167                 {CASE(OriginUpperLeft), {}},
168                 {CASE(OriginLowerLeft), {}},
169                 {CASE(EarlyFragmentTests), {}},
170                 {CASE(PointMode), {}},
171                 {CASE(Xfb), {}},
172                 {CASE(DepthReplacing), {}},
173                 {CASE(DepthGreater), {}},
174                 {CASE(DepthLess), {}},
175                 {CASE(DepthUnchanged), {}},
176                 {CASE(LocalSize), {64, 1, 2}},
177                 {CASE(LocalSizeHint), {8, 2, 4}},
178                 {CASE(InputPoints), {}},
179                 {CASE(InputLines), {}},
180                 {CASE(InputLinesAdjacency), {}},
181                 {CASE(Triangles), {}},
182                 {CASE(InputTrianglesAdjacency), {}},
183                 {CASE(Quads), {}},
184                 {CASE(Isolines), {}},
185                 {CASE(OutputVertices), {21}},
186                 {CASE(OutputPoints), {}},
187                 {CASE(OutputLineStrip), {}},
188                 {CASE(OutputTriangleStrip), {}},
189                 {CASE(VecTypeHint), {96}},
190                 {CASE(ContractionOff), {}},
191             })), );
192 
193 INSTANTIATE_TEST_CASE_P(
194     TextToBinaryExecutionModeV11, OpExecutionModeTest,
195     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
196             ValuesIn(std::vector<EnumCase<SpvExecutionMode>>{
197                 {CASE(Initializer)},
198                 {CASE(Finalizer)},
199                 {CASE(SubgroupSize), {12}},
200                 {CASE(SubgroupsPerWorkgroup), {64}}})), );
201 #undef CASE
202 
TEST_F(OpExecutionModeTest,WrongMode)203 TEST_F(OpExecutionModeTest, WrongMode) {
204   EXPECT_THAT(CompileFailure("OpExecutionMode %1 xxyyzz"),
205               Eq("Invalid execution mode 'xxyyzz'."));
206 }
207 
TEST_F(OpExecutionModeTest,TooManyModes)208 TEST_F(OpExecutionModeTest, TooManyModes) {
209   EXPECT_THAT(CompileFailure("OpExecutionMode %1 Xfb PointMode"),
210               Eq("Expected <opcode> or <result-id> at the beginning of an "
211                  "instruction, found 'PointMode'."));
212 }
213 
214 // Test OpCapability
215 
216 using OpCapabilityTest =
217     spvtest::TextToBinaryTestBase<TestWithParam<EnumCase<SpvCapability>>>;
218 
TEST_P(OpCapabilityTest,AnyCapability)219 TEST_P(OpCapabilityTest, AnyCapability) {
220   const std::string input = "OpCapability " + GetParam().name();
221   EXPECT_THAT(CompiledInstructions(input),
222               Eq(MakeInstruction(SpvOpCapability, {GetParam().value()})));
223 }
224 
225 // clang-format off
226 #define CASE(NAME) { SpvCapability##NAME, #NAME }
227 INSTANTIATE_TEST_CASE_P(TextToBinaryCapability, OpCapabilityTest,
228                         ValuesIn(std::vector<EnumCase<SpvCapability>>{
229                             CASE(Matrix),
230                             CASE(Shader),
231                             CASE(Geometry),
232                             CASE(Tessellation),
233                             CASE(Addresses),
234                             CASE(Linkage),
235                             CASE(Kernel),
236                             CASE(Vector16),
237                             CASE(Float16Buffer),
238                             CASE(Float16),
239                             CASE(Float64),
240                             CASE(Int64),
241                             CASE(Int64Atomics),
242                             CASE(ImageBasic),
243                             CASE(ImageReadWrite),
244                             CASE(ImageMipmap),
245                             // Value 16 intentionally missing
246                             CASE(Pipes),
247                             CASE(Groups),
248                             CASE(DeviceEnqueue),
249                             CASE(LiteralSampler),
250                             CASE(AtomicStorage),
251                             CASE(Int16),
252                             CASE(TessellationPointSize),
253                             CASE(GeometryPointSize),
254                             CASE(ImageGatherExtended),
255                             // Value 26 intentionally missing
256                             CASE(StorageImageMultisample),
257                             CASE(UniformBufferArrayDynamicIndexing),
258                             CASE(SampledImageArrayDynamicIndexing),
259                             CASE(StorageBufferArrayDynamicIndexing),
260                             CASE(StorageImageArrayDynamicIndexing),
261                             CASE(ClipDistance),
262                             CASE(CullDistance),
263                             CASE(ImageCubeArray),
264                             CASE(SampleRateShading),
265                             CASE(ImageRect),
266                             CASE(SampledRect),
267                             CASE(GenericPointer),
268                             CASE(Int8),
269                             CASE(InputAttachment),
270                             CASE(SparseResidency),
271                             CASE(MinLod),
272                             CASE(Sampled1D),
273                             CASE(Image1D),
274                             CASE(SampledCubeArray),
275                             CASE(SampledBuffer),
276                             CASE(ImageBuffer),
277                             CASE(ImageMSArray),
278                             CASE(StorageImageExtendedFormats),
279                             CASE(ImageQuery),
280                             CASE(DerivativeControl),
281                             CASE(InterpolationFunction),
282                             CASE(TransformFeedback),
283                         }),);
284 #undef CASE
285 // clang-format on
286 
287 using TextToBinaryCapability = spvtest::TextToBinaryTest;
288 
TEST_F(TextToBinaryCapability,BadMissingCapability)289 TEST_F(TextToBinaryCapability, BadMissingCapability) {
290   EXPECT_THAT(CompileFailure("OpCapability"),
291               Eq("Expected operand, found end of stream."));
292 }
293 
TEST_F(TextToBinaryCapability,BadInvalidCapability)294 TEST_F(TextToBinaryCapability, BadInvalidCapability) {
295   EXPECT_THAT(CompileFailure("OpCapability 123"),
296               Eq("Invalid capability '123'."));
297 }
298 
299 // TODO(dneto): OpExecutionMode
300 
301 }  // namespace
302 }  // namespace spvtools
303