text_to_binary.image_test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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 "Image Instructions" section of
  15. // the SPIR-V spec.
  16. #include <string>
  17. #include <vector>
  18. #include "gmock/gmock.h"
  19. #include "test/test_fixture.h"
  20. #include "test/unit_spirv.h"
  21. namespace spvtools {
  22. namespace {
  23. using spvtest::MakeInstruction;
  24. using spvtest::TextToBinaryTest;
  25. using ::testing::Eq;
  26. // An example case for a mask value with operands.
  27. struct ImageOperandsCase {
  28. std::string image_operands;
  29. // The expected mask, followed by its operands.
  30. std::vector<uint32_t> expected_mask_and_operands;
  31. };
  32. // Test all kinds of image operands.
  33. using ImageOperandsTest =
  34. spvtest::TextToBinaryTestBase<::testing::TestWithParam<ImageOperandsCase>>;
  35. TEST_P(ImageOperandsTest, Sample) {
  36. const std::string input =
  37. "%2 = OpImageFetch %1 %3 %4" + GetParam().image_operands + "\n";
  38. EXPECT_THAT(CompiledInstructions(input),
  39. Eq(MakeInstruction(SpvOpImageFetch, {1, 2, 3, 4},
  40. GetParam().expected_mask_and_operands)));
  41. }
  42. #define MASK(NAME) SpvImageOperands##NAME##Mask
  43. INSTANTIATE_TEST_SUITE_P(
  44. TextToBinaryImageOperandsAny, ImageOperandsTest,
  45. ::testing::ValuesIn(std::vector<ImageOperandsCase>{
  46. // TODO(dneto): Rev32 adds many more values, and rearranges their
  47. // values.
  48. // Image operands are optional.
  49. {"", {}},
  50. // Test each kind, alone.
  51. {" Bias %5", {MASK(Bias), 5}},
  52. {" Lod %5", {MASK(Lod), 5}},
  53. {" Grad %5 %6", {MASK(Grad), 5, 6}},
  54. {" ConstOffset %5", {MASK(ConstOffset), 5}},
  55. {" Offset %5", {MASK(Offset), 5}},
  56. {" ConstOffsets %5", {MASK(ConstOffsets), 5}},
  57. {" Sample %5", {MASK(Sample), 5}},
  58. {" MinLod %5", {MASK(MinLod), 5}},
  59. }));
  60. #undef MASK
  61. #define MASK(NAME) static_cast<uint32_t>(SpvImageOperands##NAME##Mask)
  62. INSTANTIATE_TEST_SUITE_P(
  63. TextToBinaryImageOperandsCombination, ImageOperandsTest,
  64. ::testing::ValuesIn(std::vector<ImageOperandsCase>{
  65. // TODO(dneto): Rev32 adds many more values, and rearranges their
  66. // values.
  67. // Test adjacent pairs, so we can easily debug the values when it fails.
  68. {" Bias|Lod %5 %6", {MASK(Bias) | MASK(Lod), 5, 6}},
  69. {" Lod|Grad %5 %6 %7", {MASK(Lod) | MASK(Grad), 5, 6, 7}},
  70. {" Grad|ConstOffset %5 %6 %7",
  71. {MASK(Grad) | MASK(ConstOffset), 5, 6, 7}},
  72. {" ConstOffset|Offset %5 %6", {MASK(ConstOffset) | MASK(Offset), 5, 6}},
  73. {" Offset|ConstOffsets %5 %6",
  74. {MASK(Offset) | MASK(ConstOffsets), 5, 6}},
  75. {" ConstOffsets|Sample %5 %6",
  76. {MASK(ConstOffsets) | MASK(Sample), 5, 6}},
  77. // Test all masks together.
  78. {" Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample"
  79. " %5 %6 %7 %8 %9 %10 %11 %12",
  80. {MASK(Bias) | MASK(Lod) | MASK(Grad) | MASK(ConstOffset) |
  81. MASK(Offset) | MASK(ConstOffsets) | MASK(Sample),
  82. 5, 6, 7, 8, 9, 10, 11, 12}},
  83. // The same, but with mask value names reversed.
  84. {" Sample|ConstOffsets|Offset|ConstOffset|Grad|Lod|Bias"
  85. " %5 %6 %7 %8 %9 %10 %11 %12",
  86. {MASK(Bias) | MASK(Lod) | MASK(Grad) | MASK(ConstOffset) |
  87. MASK(Offset) | MASK(ConstOffsets) | MASK(Sample),
  88. 5, 6, 7, 8, 9, 10, 11, 12}}}));
  89. #undef MASK
  90. TEST_F(ImageOperandsTest, WrongOperand) {
  91. EXPECT_THAT(CompileFailure("%r = OpImageFetch %t %i %c xxyyzz"),
  92. Eq("Invalid image operand 'xxyyzz'."));
  93. }
  94. // Test OpImage
  95. using OpImageTest = TextToBinaryTest;
  96. TEST_F(OpImageTest, Valid) {
  97. const std::string input = "%2 = OpImage %1 %3\n";
  98. EXPECT_THAT(CompiledInstructions(input),
  99. Eq(MakeInstruction(SpvOpImage, {1, 2, 3})));
  100. // Test the disassembler.
  101. EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
  102. }
  103. TEST_F(OpImageTest, InvalidTypeOperand) {
  104. EXPECT_THAT(CompileFailure("%2 = OpImage 42"),
  105. Eq("Expected id to start with %."));
  106. }
  107. TEST_F(OpImageTest, MissingSampledImageOperand) {
  108. EXPECT_THAT(CompileFailure("%2 = OpImage %1"),
  109. Eq("Expected operand, found end of stream."));
  110. }
  111. TEST_F(OpImageTest, InvalidSampledImageOperand) {
  112. EXPECT_THAT(CompileFailure("%2 = OpImage %1 1000"),
  113. Eq("Expected id to start with %."));
  114. }
  115. TEST_F(OpImageTest, TooManyOperands) {
  116. // We should improve this message, to say what instruction we're trying to
  117. // parse.
  118. EXPECT_THAT(CompileFailure("%2 = OpImage %1 %3 %4"), // an Id
  119. Eq("Expected '=', found end of stream."));
  120. EXPECT_THAT(CompileFailure("%2 = OpImage %1 %3 99"), // a number
  121. Eq("Expected <opcode> or <result-id> at the beginning of an "
  122. "instruction, found '99'."));
  123. EXPECT_THAT(CompileFailure("%2 = OpImage %1 %3 \"abc\""), // a string
  124. Eq("Expected <opcode> or <result-id> at the beginning of an "
  125. "instruction, found '\"abc\"'."));
  126. }
  127. // Test OpImageSparseRead
  128. using OpImageSparseReadTest = TextToBinaryTest;
  129. TEST_F(OpImageSparseReadTest, OnlyRequiredOperands) {
  130. const std::string input = "%2 = OpImageSparseRead %1 %3 %4\n";
  131. EXPECT_THAT(CompiledInstructions(input),
  132. Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4})));
  133. // Test the disassembler.
  134. EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
  135. }
  136. // Test all kinds of image operands on OpImageSparseRead
  137. using ImageSparseReadImageOperandsTest =
  138. spvtest::TextToBinaryTestBase<::testing::TestWithParam<ImageOperandsCase>>;
  139. TEST_P(ImageSparseReadImageOperandsTest, Sample) {
  140. const std::string input =
  141. "%2 = OpImageSparseRead %1 %3 %4" + GetParam().image_operands + "\n";
  142. EXPECT_THAT(CompiledInstructions(input),
  143. Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4},
  144. GetParam().expected_mask_and_operands)));
  145. // Test the disassembler.
  146. EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
  147. }
  148. #define MASK(NAME) SpvImageOperands##NAME##Mask
  149. INSTANTIATE_TEST_SUITE_P(ImageSparseReadImageOperandsAny,
  150. ImageSparseReadImageOperandsTest,
  151. ::testing::ValuesIn(std::vector<ImageOperandsCase>{
  152. // Image operands are optional.
  153. {"", {}},
  154. // Test each kind, alone.
  155. {" Bias %5", {MASK(Bias), 5}},
  156. {" Lod %5", {MASK(Lod), 5}},
  157. {" Grad %5 %6", {MASK(Grad), 5, 6}},
  158. {" ConstOffset %5", {MASK(ConstOffset), 5}},
  159. {" Offset %5", {MASK(Offset), 5}},
  160. {" ConstOffsets %5", {MASK(ConstOffsets), 5}},
  161. {" Sample %5", {MASK(Sample), 5}},
  162. {" MinLod %5", {MASK(MinLod), 5}},
  163. }));
  164. #undef MASK
  165. #define MASK(NAME) static_cast<uint32_t>(SpvImageOperands##NAME##Mask)
  166. INSTANTIATE_TEST_SUITE_P(
  167. ImageSparseReadImageOperandsCombination, ImageSparseReadImageOperandsTest,
  168. ::testing::ValuesIn(std::vector<ImageOperandsCase>{
  169. // values.
  170. // Test adjacent pairs, so we can easily debug the values when it fails.
  171. {" Bias|Lod %5 %6", {MASK(Bias) | MASK(Lod), 5, 6}},
  172. {" Lod|Grad %5 %6 %7", {MASK(Lod) | MASK(Grad), 5, 6, 7}},
  173. {" Grad|ConstOffset %5 %6 %7",
  174. {MASK(Grad) | MASK(ConstOffset), 5, 6, 7}},
  175. {" ConstOffset|Offset %5 %6", {MASK(ConstOffset) | MASK(Offset), 5, 6}},
  176. {" Offset|ConstOffsets %5 %6",
  177. {MASK(Offset) | MASK(ConstOffsets), 5, 6}},
  178. {" ConstOffsets|Sample %5 %6",
  179. {MASK(ConstOffsets) | MASK(Sample), 5, 6}},
  180. // Test all masks together.
  181. {" Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample"
  182. " %5 %6 %7 %8 %9 %10 %11 %12",
  183. {MASK(Bias) | MASK(Lod) | MASK(Grad) | MASK(ConstOffset) |
  184. MASK(Offset) | MASK(ConstOffsets) | MASK(Sample),
  185. 5, 6, 7, 8, 9, 10, 11, 12}},
  186. // Don't try the masks reversed, since this is a round trip test,
  187. // and the disassembler will sort them.
  188. }));
  189. #undef MASK
  190. TEST_F(OpImageSparseReadTest, InvalidTypeOperand) {
  191. EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead 42"),
  192. Eq("Expected id to start with %."));
  193. }
  194. TEST_F(OpImageSparseReadTest, MissingImageOperand) {
  195. EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1"),
  196. Eq("Expected operand, found end of stream."));
  197. }
  198. TEST_F(OpImageSparseReadTest, InvalidImageOperand) {
  199. EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1 1000"),
  200. Eq("Expected id to start with %."));
  201. }
  202. TEST_F(OpImageSparseReadTest, MissingCoordinateOperand) {
  203. EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1 %2"),
  204. Eq("Expected operand, found end of stream."));
  205. }
  206. TEST_F(OpImageSparseReadTest, InvalidCoordinateOperand) {
  207. EXPECT_THAT(CompileFailure("%2 = OpImageSparseRead %1 %2 1000"),
  208. Eq("Expected id to start with %."));
  209. }
  210. // TODO(dneto): OpSampledImage
  211. // TODO(dneto): OpImageSampleImplicitLod
  212. // TODO(dneto): OpImageSampleExplicitLod
  213. // TODO(dneto): OpImageSampleDrefImplicitLod
  214. // TODO(dneto): OpImageSampleDrefExplicitLod
  215. // TODO(dneto): OpImageSampleProjImplicitLod
  216. // TODO(dneto): OpImageSampleProjExplicitLod
  217. // TODO(dneto): OpImageSampleProjDrefImplicitLod
  218. // TODO(dneto): OpImageSampleProjDrefExplicitLod
  219. // TODO(dneto): OpImageGather
  220. // TODO(dneto): OpImageDrefGather
  221. // TODO(dneto): OpImageRead
  222. // TODO(dneto): OpImageWrite
  223. // TODO(dneto): OpImageQueryFormat
  224. // TODO(dneto): OpImageQueryOrder
  225. // TODO(dneto): OpImageQuerySizeLod
  226. // TODO(dneto): OpImageQuerySize
  227. // TODO(dneto): OpImageQueryLod
  228. // TODO(dneto): OpImageQueryLevels
  229. // TODO(dneto): OpImageQuerySamples
  230. // TODO(dneto): OpImageSparseSampleImplicitLod
  231. // TODO(dneto): OpImageSparseSampleExplicitLod
  232. // TODO(dneto): OpImageSparseSampleDrefImplicitLod
  233. // TODO(dneto): OpImageSparseSampleDrefExplicitLod
  234. // TODO(dneto): OpImageSparseSampleProjImplicitLod
  235. // TODO(dneto): OpImageSparseSampleProjExplicitLod
  236. // TODO(dneto): OpImageSparseSampleProjDrefImplicitLod
  237. // TODO(dneto): OpImageSparseSampleProjDrefExplicitLod
  238. // TODO(dneto): OpImageSparseFetch
  239. // TODO(dneto): OpImageSparseDrefGather
  240. // TODO(dneto): OpImageSparseTexelsResident
  241. } // namespace
  242. } // namespace spvtools