text_to_binary.mode_setting_test.cpp 12 KB

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