ext_inst.opencl_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. #include <string>
  15. #include <vector>
  16. #include "gmock/gmock.h"
  17. #include "source/latest_version_opencl_std_header.h"
  18. #include "test/test_fixture.h"
  19. #include "test/unit_spirv.h"
  20. namespace spvtools {
  21. namespace {
  22. using spvtest::Concatenate;
  23. using spvtest::MakeInstruction;
  24. using spvtest::MakeVector;
  25. using spvtest::TextToBinaryTest;
  26. using testing::Eq;
  27. struct InstructionCase {
  28. uint32_t opcode;
  29. std::string name;
  30. std::string operands;
  31. std::vector<uint32_t> expected_operands;
  32. };
  33. using ExtInstOpenCLStdRoundTripTest =
  34. spvtest::TextToBinaryTestBase<::testing::TestWithParam<InstructionCase>>;
  35. TEST_P(ExtInstOpenCLStdRoundTripTest, ParameterizedExtInst) {
  36. // This example should not validate.
  37. const std::string input =
  38. "%1 = OpExtInstImport \"OpenCL.std\"\n"
  39. "%3 = OpExtInst %2 %1 " +
  40. GetParam().name + " " + GetParam().operands + "\n";
  41. // First make sure it assembles correctly.
  42. EXPECT_THAT(
  43. CompiledInstructions(input),
  44. Eq(Concatenate(
  45. {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
  46. MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
  47. GetParam().expected_operands)})))
  48. << input;
  49. // Now check the round trip through the disassembler.
  50. EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
  51. }
  52. #define CASE1(Enum, Name) \
  53. { \
  54. uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4", { 4 } \
  55. }
  56. #define CASE2(Enum, Name) \
  57. { \
  58. uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5", { 4, 5 } \
  59. }
  60. #define CASE3(Enum, Name) \
  61. { \
  62. uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6", { 4, 5, 6 } \
  63. }
  64. #define CASE4(Enum, Name) \
  65. { \
  66. uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 %7", { \
  67. 4, 5, 6, 7 \
  68. } \
  69. }
  70. #define CASE2Lit(Enum, Name, LiteralNumber) \
  71. { \
  72. uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 " #LiteralNumber, { \
  73. 4, 5, LiteralNumber \
  74. } \
  75. }
  76. #define CASE3Round(Enum, Name, Mode) \
  77. { \
  78. uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 " #Mode, { \
  79. 4, 5, 6, uint32_t(SpvFPRoundingMode##Mode) \
  80. } \
  81. }
  82. // clang-format off
  83. // OpenCL.std: 2.1 Math extended instructions
  84. INSTANTIATE_TEST_SUITE_P(
  85. OpenCLMath, ExtInstOpenCLStdRoundTripTest,
  86. ::testing::ValuesIn(std::vector<InstructionCase>({
  87. // We are only testing the correctness of encoding and decoding here.
  88. // Semantic correctness should be the responsibility of validator.
  89. CASE1(Acos, acos), // enum value 0
  90. CASE1(Acosh, acosh),
  91. CASE1(Acospi, acospi),
  92. CASE1(Asin, asin),
  93. CASE1(Asinh, asinh),
  94. CASE1(Asinh, asinh),
  95. CASE1(Asinpi, asinpi),
  96. CASE1(Atan, atan),
  97. CASE2(Atan2, atan2),
  98. CASE1(Atanh, atanh),
  99. CASE1(Atanpi, atanpi),
  100. CASE2(Atan2pi, atan2pi),
  101. CASE1(Cbrt, cbrt),
  102. CASE1(Ceil, ceil),
  103. CASE1(Ceil, ceil),
  104. CASE2(Copysign, copysign),
  105. CASE1(Cos, cos),
  106. CASE1(Cosh, cosh),
  107. CASE1(Cospi, cospi),
  108. CASE1(Erfc, erfc),
  109. CASE1(Erf, erf),
  110. CASE1(Exp, exp),
  111. CASE1(Exp2, exp2),
  112. CASE1(Exp10, exp10),
  113. CASE1(Expm1, expm1),
  114. CASE1(Fabs, fabs),
  115. CASE2(Fdim, fdim),
  116. CASE1(Floor, floor),
  117. CASE3(Fma, fma),
  118. CASE2(Fmax, fmax),
  119. CASE2(Fmin, fmin),
  120. CASE2(Fmod, fmod),
  121. CASE2(Fract, fract),
  122. CASE2(Frexp, frexp),
  123. CASE2(Hypot, hypot),
  124. CASE1(Ilogb, ilogb),
  125. CASE2(Ldexp, ldexp),
  126. CASE1(Lgamma, lgamma),
  127. CASE2(Lgamma_r, lgamma_r),
  128. CASE1(Log, log),
  129. CASE1(Log2, log2),
  130. CASE1(Log10, log10),
  131. CASE1(Log1p, log1p),
  132. CASE3(Mad, mad),
  133. CASE2(Maxmag, maxmag),
  134. CASE2(Minmag, minmag),
  135. CASE2(Modf, modf),
  136. CASE1(Nan, nan),
  137. CASE2(Nextafter, nextafter),
  138. CASE2(Pow, pow),
  139. CASE2(Pown, pown),
  140. CASE2(Powr, powr),
  141. CASE2(Remainder, remainder),
  142. CASE3(Remquo, remquo),
  143. CASE1(Rint, rint),
  144. CASE2(Rootn, rootn),
  145. CASE1(Round, round),
  146. CASE1(Rsqrt, rsqrt),
  147. CASE1(Sin, sin),
  148. CASE2(Sincos, sincos),
  149. CASE1(Sinh, sinh),
  150. CASE1(Sinpi, sinpi),
  151. CASE1(Sqrt, sqrt),
  152. CASE1(Tan, tan),
  153. CASE1(Tanh, tanh),
  154. CASE1(Tanpi, tanpi),
  155. CASE1(Tgamma, tgamma),
  156. CASE1(Trunc, trunc),
  157. CASE1(Half_cos, half_cos),
  158. CASE2(Half_divide, half_divide),
  159. CASE1(Half_exp, half_exp),
  160. CASE1(Half_exp2, half_exp2),
  161. CASE1(Half_exp10, half_exp10),
  162. CASE1(Half_log, half_log),
  163. CASE1(Half_log2, half_log2),
  164. CASE1(Half_log10, half_log10),
  165. CASE2(Half_powr, half_powr),
  166. CASE1(Half_recip, half_recip),
  167. CASE1(Half_rsqrt, half_rsqrt),
  168. CASE1(Half_sin, half_sin),
  169. CASE1(Half_sqrt, half_sqrt),
  170. CASE1(Half_tan, half_tan),
  171. CASE1(Native_cos, native_cos),
  172. CASE2(Native_divide, native_divide),
  173. CASE1(Native_exp, native_exp),
  174. CASE1(Native_exp2, native_exp2),
  175. CASE1(Native_exp10, native_exp10),
  176. CASE1(Native_log, native_log),
  177. CASE1(Native_log10, native_log10),
  178. CASE2(Native_powr, native_powr),
  179. CASE1(Native_recip, native_recip),
  180. CASE1(Native_rsqrt, native_rsqrt),
  181. CASE1(Native_sin, native_sin),
  182. CASE1(Native_sqrt, native_sqrt),
  183. CASE1(Native_tan, native_tan), // enum value 94
  184. })));
  185. // OpenCL.std: 2.1 Integer instructions
  186. INSTANTIATE_TEST_SUITE_P(
  187. OpenCLInteger, ExtInstOpenCLStdRoundTripTest,
  188. ::testing::ValuesIn(std::vector<InstructionCase>({
  189. CASE1(SAbs, s_abs), // enum value 141
  190. CASE2(SAbs_diff, s_abs_diff),
  191. CASE2(SAdd_sat, s_add_sat),
  192. CASE2(UAdd_sat, u_add_sat),
  193. CASE2(SHadd, s_hadd),
  194. CASE2(UHadd, u_hadd),
  195. CASE2(SRhadd, s_rhadd),
  196. CASE2(SRhadd, s_rhadd),
  197. CASE3(SClamp, s_clamp),
  198. CASE3(UClamp, u_clamp),
  199. CASE1(Clz, clz),
  200. CASE1(Ctz, ctz),
  201. CASE3(SMad_hi, s_mad_hi),
  202. CASE3(UMad_sat, u_mad_sat),
  203. CASE3(SMad_sat, s_mad_sat),
  204. CASE2(SMax, s_max),
  205. CASE2(UMax, u_max),
  206. CASE2(SMin, s_min),
  207. CASE2(UMin, u_min),
  208. CASE2(SMul_hi, s_mul_hi),
  209. CASE2(Rotate, rotate),
  210. CASE2(SSub_sat, s_sub_sat),
  211. CASE2(USub_sat, u_sub_sat),
  212. CASE2(U_Upsample, u_upsample),
  213. CASE2(S_Upsample, s_upsample),
  214. CASE1(Popcount, popcount),
  215. CASE3(SMad24, s_mad24),
  216. CASE3(UMad24, u_mad24),
  217. CASE2(SMul24, s_mul24),
  218. CASE2(UMul24, u_mul24), // enum value 170
  219. CASE1(UAbs, u_abs), // enum value 201
  220. CASE2(UAbs_diff, u_abs_diff),
  221. CASE2(UMul_hi, u_mul_hi),
  222. CASE3(UMad_hi, u_mad_hi), // enum value 204
  223. })));
  224. // OpenCL.std: 2.3 Common instrucitons
  225. INSTANTIATE_TEST_SUITE_P(
  226. OpenCLCommon, ExtInstOpenCLStdRoundTripTest,
  227. ::testing::ValuesIn(std::vector<InstructionCase>({
  228. CASE3(FClamp, fclamp), // enum value 95
  229. CASE1(Degrees, degrees),
  230. CASE2(FMax_common, fmax_common),
  231. CASE2(FMin_common, fmin_common),
  232. CASE3(Mix, mix),
  233. CASE1(Radians, radians),
  234. CASE2(Step, step),
  235. CASE3(Smoothstep, smoothstep),
  236. CASE1(Sign, sign), // enum value 103
  237. })));
  238. // OpenCL.std: 2.4 Geometric instructions
  239. INSTANTIATE_TEST_SUITE_P(
  240. OpenCLGeometric, ExtInstOpenCLStdRoundTripTest,
  241. ::testing::ValuesIn(std::vector<InstructionCase>({
  242. CASE2(Cross, cross), // enum value 104
  243. CASE2(Distance, distance),
  244. CASE1(Length, length),
  245. CASE1(Normalize, normalize),
  246. CASE2(Fast_distance, fast_distance),
  247. CASE1(Fast_length, fast_length),
  248. CASE1(Fast_normalize, fast_normalize), // enum value 110
  249. })));
  250. // OpenCL.std: 2.5 Relational instructions
  251. INSTANTIATE_TEST_SUITE_P(
  252. OpenCLRelational, ExtInstOpenCLStdRoundTripTest,
  253. ::testing::ValuesIn(std::vector<InstructionCase>({
  254. CASE3(Bitselect, bitselect), // enum value 186
  255. CASE3(Select, select), // enum value 187
  256. })));
  257. // OpenCL.std: 2.6 Vector data load and store instructions
  258. INSTANTIATE_TEST_SUITE_P(
  259. OpenCLVectorLoadStore, ExtInstOpenCLStdRoundTripTest,
  260. ::testing::ValuesIn(std::vector<InstructionCase>({
  261. // The last argument to Vloadn must be one of 2, 3, 4, 8, 16.
  262. CASE2Lit(Vloadn, vloadn, 2),
  263. CASE2Lit(Vloadn, vloadn, 3),
  264. CASE2Lit(Vloadn, vloadn, 4),
  265. CASE2Lit(Vloadn, vloadn, 8),
  266. CASE2Lit(Vloadn, vloadn, 16),
  267. CASE3(Vstoren, vstoren),
  268. CASE2(Vload_half, vload_half),
  269. CASE2Lit(Vload_halfn, vload_halfn, 2),
  270. CASE2Lit(Vload_halfn, vload_halfn, 3),
  271. CASE2Lit(Vload_halfn, vload_halfn, 4),
  272. CASE2Lit(Vload_halfn, vload_halfn, 8),
  273. CASE2Lit(Vload_halfn, vload_halfn, 16),
  274. CASE3(Vstore_half, vstore_half),
  275. // Try all the rounding modes.
  276. CASE3Round(Vstore_half_r, vstore_half_r, RTE),
  277. CASE3Round(Vstore_half_r, vstore_half_r, RTZ),
  278. CASE3Round(Vstore_half_r, vstore_half_r, RTP),
  279. CASE3Round(Vstore_half_r, vstore_half_r, RTN),
  280. CASE3(Vstore_halfn, vstore_halfn),
  281. CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTE),
  282. CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTZ),
  283. CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTP),
  284. CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTN),
  285. CASE2Lit(Vloada_halfn, vloada_halfn, 2),
  286. CASE2Lit(Vloada_halfn, vloada_halfn, 3),
  287. CASE2Lit(Vloada_halfn, vloada_halfn, 4),
  288. CASE2Lit(Vloada_halfn, vloada_halfn, 8),
  289. CASE2Lit(Vloada_halfn, vloada_halfn, 16),
  290. CASE3(Vstorea_halfn, vstorea_halfn),
  291. CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTE),
  292. CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTZ),
  293. CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTP),
  294. CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTN),
  295. })));
  296. // OpenCL.std: 2.7 Miscellaneous vector instructions
  297. INSTANTIATE_TEST_SUITE_P(
  298. OpenCLMiscellaneousVector, ExtInstOpenCLStdRoundTripTest,
  299. ::testing::ValuesIn(std::vector<InstructionCase>({
  300. CASE2(Shuffle, shuffle),
  301. CASE3(Shuffle2, shuffle2),
  302. })));
  303. // OpenCL.std: 2.8 Miscellaneous instructions
  304. #define PREFIX uint32_t(OpenCLLIB::Entrypoints::Printf), "printf"
  305. INSTANTIATE_TEST_SUITE_P(
  306. OpenCLMiscPrintf, ExtInstOpenCLStdRoundTripTest,
  307. ::testing::ValuesIn(std::vector<InstructionCase>({
  308. // Printf is interesting because it takes a variable number of arguments.
  309. // Start with zero optional arguments.
  310. {PREFIX, "%4", {4}},
  311. {PREFIX, "%4 %5", {4, 5}},
  312. {PREFIX, "%4 %5 %6", {4, 5, 6}},
  313. {PREFIX, "%4 %5 %6 %7", {4, 5, 6, 7}},
  314. {PREFIX, "%4 %5 %6 %7 %8", {4, 5, 6, 7, 8}},
  315. {PREFIX, "%4 %5 %6 %7 %8 %9", {4, 5, 6, 7, 8, 9}},
  316. {PREFIX, "%4 %5 %6 %7 %8 %9 %10", {4, 5, 6, 7, 8, 9, 10}},
  317. {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11", {4, 5, 6, 7, 8, 9, 10, 11}},
  318. {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12",
  319. {4, 5, 6, 7, 8, 9, 10, 11, 12}},
  320. {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13",
  321. {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
  322. {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14",
  323. {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}},
  324. })));
  325. #undef PREFIX
  326. INSTANTIATE_TEST_SUITE_P(
  327. OpenCLMiscPrefetch, ExtInstOpenCLStdRoundTripTest,
  328. ::testing::ValuesIn(std::vector<InstructionCase>({
  329. CASE2(Prefetch, prefetch),
  330. })));
  331. // OpenCL.std: 2.9.1 Image encoding
  332. // No new instructions defined in this section.
  333. // OpenCL.std: 2.9.2 Sampler encoding
  334. // No new instructions defined in this section.
  335. // OpenCL.std: 2.9.3 Image read
  336. // No new instructions defined in this section.
  337. // Use core instruction OpImageSampleExplicitLod instead.
  338. // OpenCL.std: 2.9.4 Image write
  339. // No new instructions defined in this section.
  340. // clang-format on
  341. #undef CASE1
  342. #undef CASE2
  343. #undef CASE3
  344. #undef CASE4
  345. #undef CASE2Lit
  346. #undef CASE3Round
  347. } // namespace
  348. } // namespace spvtools