text_to_binary.mode_setting_test.cpp 12 KB

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