spirv_target_env.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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 "source/spirv_target_env.h"
  15. #include <array>
  16. #include <cassert>
  17. #include <cctype>
  18. #include <cstring>
  19. #include <string>
  20. #include "source/latest_version_spirv_header.h"
  21. #include "source/spirv_constant.h"
  22. #include "spirv-tools/libspirv.h"
  23. const char* spvTargetEnvDescription(spv_target_env env) {
  24. switch (env) {
  25. case SPV_ENV_UNIVERSAL_1_0:
  26. return "SPIR-V 1.0";
  27. case SPV_ENV_VULKAN_1_0:
  28. return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
  29. case SPV_ENV_UNIVERSAL_1_1:
  30. return "SPIR-V 1.1";
  31. case SPV_ENV_OPENCL_1_2:
  32. return "SPIR-V 1.0 (under OpenCL 1.2 Full Profile semantics)";
  33. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  34. return "SPIR-V 1.0 (under OpenCL 1.2 Embedded Profile semantics)";
  35. case SPV_ENV_OPENCL_2_0:
  36. return "SPIR-V 1.0 (under OpenCL 2.0 Full Profile semantics)";
  37. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  38. return "SPIR-V 1.0 (under OpenCL 2.0 Embedded Profile semantics)";
  39. case SPV_ENV_OPENCL_2_1:
  40. return "SPIR-V 1.0 (under OpenCL 2.1 Full Profile semantics)";
  41. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  42. return "SPIR-V 1.0 (under OpenCL 2.1 Embedded Profile semantics)";
  43. case SPV_ENV_OPENCL_2_2:
  44. return "SPIR-V 1.2 (under OpenCL 2.2 Full Profile semantics)";
  45. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  46. return "SPIR-V 1.2 (under OpenCL 2.2 Embedded Profile semantics)";
  47. case SPV_ENV_OPENGL_4_0:
  48. return "SPIR-V 1.0 (under OpenGL 4.0 semantics)";
  49. case SPV_ENV_OPENGL_4_1:
  50. return "SPIR-V 1.0 (under OpenGL 4.1 semantics)";
  51. case SPV_ENV_OPENGL_4_2:
  52. return "SPIR-V 1.0 (under OpenGL 4.2 semantics)";
  53. case SPV_ENV_OPENGL_4_3:
  54. return "SPIR-V 1.0 (under OpenGL 4.3 semantics)";
  55. case SPV_ENV_OPENGL_4_5:
  56. return "SPIR-V 1.0 (under OpenGL 4.5 semantics)";
  57. case SPV_ENV_UNIVERSAL_1_2:
  58. return "SPIR-V 1.2";
  59. case SPV_ENV_UNIVERSAL_1_3:
  60. return "SPIR-V 1.3";
  61. case SPV_ENV_VULKAN_1_1:
  62. return "SPIR-V 1.3 (under Vulkan 1.1 semantics)";
  63. case SPV_ENV_WEBGPU_0:
  64. assert(false && "Deprecated target environment value.");
  65. break;
  66. case SPV_ENV_UNIVERSAL_1_4:
  67. return "SPIR-V 1.4";
  68. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  69. return "SPIR-V 1.4 (under Vulkan 1.1 semantics)";
  70. case SPV_ENV_UNIVERSAL_1_5:
  71. return "SPIR-V 1.5";
  72. case SPV_ENV_VULKAN_1_2:
  73. return "SPIR-V 1.5 (under Vulkan 1.2 semantics)";
  74. case SPV_ENV_UNIVERSAL_1_6:
  75. return "SPIR-V 1.6";
  76. case SPV_ENV_VULKAN_1_3:
  77. return "SPIR-V 1.6 (under Vulkan 1.3 semantics)";
  78. case SPV_ENV_VULKAN_1_4:
  79. return "SPIR-V 1.6 (under Vulkan 1.4 semantics)";
  80. case SPV_ENV_MAX:
  81. assert(false && "Invalid target environment value.");
  82. break;
  83. }
  84. return "";
  85. }
  86. uint32_t spvVersionForTargetEnv(spv_target_env env) {
  87. switch (env) {
  88. case SPV_ENV_UNIVERSAL_1_0:
  89. case SPV_ENV_VULKAN_1_0:
  90. case SPV_ENV_OPENCL_1_2:
  91. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  92. case SPV_ENV_OPENCL_2_0:
  93. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  94. case SPV_ENV_OPENCL_2_1:
  95. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  96. case SPV_ENV_OPENGL_4_0:
  97. case SPV_ENV_OPENGL_4_1:
  98. case SPV_ENV_OPENGL_4_2:
  99. case SPV_ENV_OPENGL_4_3:
  100. case SPV_ENV_OPENGL_4_5:
  101. return SPV_SPIRV_VERSION_WORD(1, 0);
  102. case SPV_ENV_UNIVERSAL_1_1:
  103. return SPV_SPIRV_VERSION_WORD(1, 1);
  104. case SPV_ENV_UNIVERSAL_1_2:
  105. case SPV_ENV_OPENCL_2_2:
  106. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  107. return SPV_SPIRV_VERSION_WORD(1, 2);
  108. case SPV_ENV_UNIVERSAL_1_3:
  109. case SPV_ENV_VULKAN_1_1:
  110. return SPV_SPIRV_VERSION_WORD(1, 3);
  111. case SPV_ENV_WEBGPU_0:
  112. assert(false && "Deprecated target environment value.");
  113. break;
  114. case SPV_ENV_UNIVERSAL_1_4:
  115. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  116. return SPV_SPIRV_VERSION_WORD(1, 4);
  117. case SPV_ENV_UNIVERSAL_1_5:
  118. case SPV_ENV_VULKAN_1_2:
  119. return SPV_SPIRV_VERSION_WORD(1, 5);
  120. case SPV_ENV_UNIVERSAL_1_6:
  121. case SPV_ENV_VULKAN_1_3:
  122. case SPV_ENV_VULKAN_1_4:
  123. return SPV_SPIRV_VERSION_WORD(1, 6);
  124. case SPV_ENV_MAX:
  125. assert(false && "Invalid target environment value.");
  126. break;
  127. }
  128. return SPV_SPIRV_VERSION_WORD(0, 0);
  129. }
  130. // When a new SPIR-V version is released, update this table.
  131. static_assert(spv::Version == 0x10600);
  132. constexpr auto ordered_universal_envs = std::array<spv_target_env, 7>{
  133. SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
  134. SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
  135. SPV_ENV_UNIVERSAL_1_6,
  136. };
  137. // When a new SPIR-V version is released, update this table.
  138. // Users see this ordered list when running 'spirv-val --help'. Order
  139. // matters for readability.
  140. static_assert(spv::Version == 0x10600);
  141. inline constexpr std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] =
  142. {
  143. // Do not reorder blindly. The algorithm to find the target looks for
  144. // the first entry where the key is a prefix of the string provided by
  145. // the user. For example, if the user provides `vulkan1.2spv1.5`, it
  146. // will match `vulkan1.2`. If this feature is to work correctly, the
  147. // keys must be ordered so that a string is before its prefix. For
  148. // example, `vulkan1.1spv1.4` must be before `vulkan1.1`. Otherwise,
  149. // `vulkan1.1` will be returned when looking for `vulkan1.1spv1.4`.
  150. {"vulkan1.0", SPV_ENV_VULKAN_1_0},
  151. {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
  152. {"vulkan1.1", SPV_ENV_VULKAN_1_1},
  153. {"vulkan1.2", SPV_ENV_VULKAN_1_2},
  154. {"vulkan1.3", SPV_ENV_VULKAN_1_3},
  155. {"vulkan1.4", SPV_ENV_VULKAN_1_4},
  156. {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
  157. {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
  158. {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
  159. {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
  160. {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
  161. {"spv1.5", SPV_ENV_UNIVERSAL_1_5},
  162. {"spv1.6", SPV_ENV_UNIVERSAL_1_6},
  163. {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
  164. {"opencl1.2", SPV_ENV_OPENCL_1_2},
  165. {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
  166. {"opencl2.0", SPV_ENV_OPENCL_2_0},
  167. {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
  168. {"opencl2.1", SPV_ENV_OPENCL_2_1},
  169. {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
  170. {"opencl2.2", SPV_ENV_OPENCL_2_2},
  171. {"opengl4.0", SPV_ENV_OPENGL_4_0},
  172. {"opengl4.1", SPV_ENV_OPENGL_4_1},
  173. {"opengl4.2", SPV_ENV_OPENGL_4_2},
  174. {"opengl4.3", SPV_ENV_OPENGL_4_3},
  175. {"opengl4.5", SPV_ENV_OPENGL_4_5},
  176. };
  177. bool spvParseTargetEnv(const char* s, spv_target_env* env) {
  178. auto match = [s](const char* b) {
  179. return s && (0 == strncmp(s, b, strlen(b)));
  180. };
  181. for (auto& name_env : spvTargetEnvNameMap) {
  182. if (match(name_env.first)) {
  183. if (env) {
  184. *env = name_env.second;
  185. }
  186. return true;
  187. }
  188. }
  189. if (env) *env = SPV_ENV_UNIVERSAL_1_0;
  190. return false;
  191. }
  192. bool spvReadEnvironmentFromText(const std::vector<char>& text,
  193. spv_target_env* env) {
  194. // Version is expected to match "; Version: 1.X"
  195. // Version string must occur in header, that is, initial lines of comments
  196. // Once a non-comment line occurs, the header has ended
  197. for (std::size_t i = 0; i < text.size(); ++i) {
  198. char c = text[i];
  199. if (c == ';') {
  200. // Try to match against the expected version string
  201. constexpr const char* kVersionPrefix = "; Version: 1.";
  202. constexpr const auto kPrefixLength = 13;
  203. // 'minor_digit_pos' is the expected position of the version digit.
  204. const auto minor_digit_pos = i + kPrefixLength;
  205. if (minor_digit_pos >= text.size()) return false;
  206. // Match the prefix.
  207. auto j = 1;
  208. for (; j < kPrefixLength; ++j) {
  209. if (kVersionPrefix[j] != text[i + j]) break;
  210. }
  211. // j will match the prefix length if all characters before matched
  212. if (j == kPrefixLength) {
  213. // This expects only one digit in the minor number.
  214. static_assert(((spv::Version >> 8) & 0xff) < 10);
  215. char minor = text[minor_digit_pos];
  216. char next_char =
  217. minor_digit_pos + 1 < text.size() ? text[minor_digit_pos + 1] : 0;
  218. if (std::isdigit(minor) && !std::isdigit(next_char)) {
  219. const auto index = minor - '0';
  220. assert(index >= 0);
  221. if (static_cast<size_t>(index) < ordered_universal_envs.size()) {
  222. *env = ordered_universal_envs[index];
  223. return true;
  224. }
  225. }
  226. }
  227. // If no match, determine whether the header has ended (in which case,
  228. // assumption has failed.)
  229. // Skip until the next line.
  230. i += j;
  231. for (; i < text.size(); ++i) {
  232. if (text[i] == '\n') break;
  233. }
  234. } else if (!std::isspace(c)) {
  235. // Allow blanks, but end the search if we find something else.
  236. break;
  237. }
  238. }
  239. return false;
  240. }
  241. #define VULKAN_VER(MAJOR, MINOR) ((MAJOR << 22) | (MINOR << 12))
  242. #define SPIRV_VER(MAJOR, MINOR) ((MAJOR << 16) | (MINOR << 8))
  243. struct VulkanEnv {
  244. spv_target_env vulkan_env;
  245. uint32_t vulkan_ver;
  246. uint32_t spirv_ver;
  247. };
  248. // Maps each Vulkan target environment enum to the Vulkan version, and the
  249. // maximum supported SPIR-V version for that Vulkan environment.
  250. // Keep this ordered from least capable to most capable.
  251. static const VulkanEnv ordered_vulkan_envs[] = {
  252. {SPV_ENV_VULKAN_1_0, VULKAN_VER(1, 0), SPIRV_VER(1, 0)},
  253. {SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)},
  254. {SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)},
  255. {SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)},
  256. {SPV_ENV_VULKAN_1_3, VULKAN_VER(1, 3), SPIRV_VER(1, 6)},
  257. {SPV_ENV_VULKAN_1_4, VULKAN_VER(1, 4), SPIRV_VER(1, 6)}};
  258. bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver,
  259. spv_target_env* env) {
  260. for (auto triple : ordered_vulkan_envs) {
  261. if (triple.vulkan_ver >= vulkan_ver && triple.spirv_ver >= spirv_ver) {
  262. *env = triple.vulkan_env;
  263. return true;
  264. }
  265. }
  266. return false;
  267. }
  268. bool spvIsVulkanEnv(spv_target_env env) {
  269. switch (env) {
  270. case SPV_ENV_UNIVERSAL_1_0:
  271. case SPV_ENV_OPENCL_1_2:
  272. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  273. case SPV_ENV_OPENCL_2_0:
  274. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  275. case SPV_ENV_OPENCL_2_1:
  276. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  277. case SPV_ENV_OPENGL_4_0:
  278. case SPV_ENV_OPENGL_4_1:
  279. case SPV_ENV_OPENGL_4_2:
  280. case SPV_ENV_OPENGL_4_3:
  281. case SPV_ENV_OPENGL_4_5:
  282. case SPV_ENV_UNIVERSAL_1_1:
  283. case SPV_ENV_UNIVERSAL_1_2:
  284. case SPV_ENV_OPENCL_2_2:
  285. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  286. case SPV_ENV_UNIVERSAL_1_3:
  287. case SPV_ENV_UNIVERSAL_1_4:
  288. case SPV_ENV_UNIVERSAL_1_5:
  289. case SPV_ENV_UNIVERSAL_1_6:
  290. return false;
  291. case SPV_ENV_VULKAN_1_0:
  292. case SPV_ENV_VULKAN_1_1:
  293. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  294. case SPV_ENV_VULKAN_1_2:
  295. case SPV_ENV_VULKAN_1_3:
  296. case SPV_ENV_VULKAN_1_4:
  297. return true;
  298. case SPV_ENV_WEBGPU_0:
  299. assert(false && "Deprecated target environment value.");
  300. break;
  301. case SPV_ENV_MAX:
  302. assert(false && "Invalid target environment value.");
  303. break;
  304. }
  305. return false;
  306. }
  307. bool spvIsOpenCLEnv(spv_target_env env) {
  308. switch (env) {
  309. case SPV_ENV_UNIVERSAL_1_0:
  310. case SPV_ENV_VULKAN_1_0:
  311. case SPV_ENV_UNIVERSAL_1_1:
  312. case SPV_ENV_OPENGL_4_0:
  313. case SPV_ENV_OPENGL_4_1:
  314. case SPV_ENV_OPENGL_4_2:
  315. case SPV_ENV_OPENGL_4_3:
  316. case SPV_ENV_OPENGL_4_5:
  317. case SPV_ENV_UNIVERSAL_1_2:
  318. case SPV_ENV_UNIVERSAL_1_3:
  319. case SPV_ENV_VULKAN_1_1:
  320. case SPV_ENV_UNIVERSAL_1_4:
  321. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  322. case SPV_ENV_UNIVERSAL_1_5:
  323. case SPV_ENV_VULKAN_1_2:
  324. case SPV_ENV_UNIVERSAL_1_6:
  325. case SPV_ENV_VULKAN_1_3:
  326. case SPV_ENV_VULKAN_1_4:
  327. return false;
  328. case SPV_ENV_OPENCL_1_2:
  329. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  330. case SPV_ENV_OPENCL_2_0:
  331. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  332. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  333. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  334. case SPV_ENV_OPENCL_2_1:
  335. case SPV_ENV_OPENCL_2_2:
  336. return true;
  337. case SPV_ENV_WEBGPU_0:
  338. assert(false && "Deprecated target environment value.");
  339. break;
  340. case SPV_ENV_MAX:
  341. assert(false && "Invalid target environment value.");
  342. break;
  343. }
  344. return false;
  345. }
  346. bool spvIsOpenGLEnv(spv_target_env env) {
  347. switch (env) {
  348. case SPV_ENV_UNIVERSAL_1_0:
  349. case SPV_ENV_VULKAN_1_0:
  350. case SPV_ENV_UNIVERSAL_1_1:
  351. case SPV_ENV_UNIVERSAL_1_2:
  352. case SPV_ENV_UNIVERSAL_1_3:
  353. case SPV_ENV_VULKAN_1_1:
  354. case SPV_ENV_OPENCL_1_2:
  355. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  356. case SPV_ENV_OPENCL_2_0:
  357. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  358. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  359. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  360. case SPV_ENV_OPENCL_2_1:
  361. case SPV_ENV_OPENCL_2_2:
  362. case SPV_ENV_UNIVERSAL_1_4:
  363. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  364. case SPV_ENV_UNIVERSAL_1_5:
  365. case SPV_ENV_VULKAN_1_2:
  366. case SPV_ENV_UNIVERSAL_1_6:
  367. case SPV_ENV_VULKAN_1_3:
  368. case SPV_ENV_VULKAN_1_4:
  369. return false;
  370. case SPV_ENV_OPENGL_4_0:
  371. case SPV_ENV_OPENGL_4_1:
  372. case SPV_ENV_OPENGL_4_2:
  373. case SPV_ENV_OPENGL_4_3:
  374. case SPV_ENV_OPENGL_4_5:
  375. return true;
  376. case SPV_ENV_WEBGPU_0:
  377. assert(false && "Deprecated target environment value.");
  378. break;
  379. case SPV_ENV_MAX:
  380. assert(false && "Invalid target environment value.");
  381. break;
  382. }
  383. return false;
  384. }
  385. bool spvIsValidEnv(spv_target_env env) {
  386. switch (env) {
  387. case SPV_ENV_UNIVERSAL_1_0:
  388. case SPV_ENV_VULKAN_1_0:
  389. case SPV_ENV_UNIVERSAL_1_1:
  390. case SPV_ENV_UNIVERSAL_1_2:
  391. case SPV_ENV_UNIVERSAL_1_3:
  392. case SPV_ENV_VULKAN_1_1:
  393. case SPV_ENV_OPENCL_1_2:
  394. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  395. case SPV_ENV_OPENCL_2_0:
  396. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  397. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  398. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  399. case SPV_ENV_OPENCL_2_1:
  400. case SPV_ENV_OPENCL_2_2:
  401. case SPV_ENV_UNIVERSAL_1_4:
  402. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  403. case SPV_ENV_UNIVERSAL_1_5:
  404. case SPV_ENV_VULKAN_1_2:
  405. case SPV_ENV_UNIVERSAL_1_6:
  406. case SPV_ENV_VULKAN_1_3:
  407. case SPV_ENV_VULKAN_1_4:
  408. case SPV_ENV_OPENGL_4_0:
  409. case SPV_ENV_OPENGL_4_1:
  410. case SPV_ENV_OPENGL_4_2:
  411. case SPV_ENV_OPENGL_4_3:
  412. case SPV_ENV_OPENGL_4_5:
  413. return true;
  414. case SPV_ENV_WEBGPU_0:
  415. case SPV_ENV_MAX:
  416. break;
  417. }
  418. return false;
  419. }
  420. std::string spvLogStringForEnv(spv_target_env env) {
  421. switch (env) {
  422. case SPV_ENV_OPENCL_1_2:
  423. case SPV_ENV_OPENCL_2_0:
  424. case SPV_ENV_OPENCL_2_1:
  425. case SPV_ENV_OPENCL_2_2:
  426. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  427. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  428. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  429. case SPV_ENV_OPENCL_EMBEDDED_2_2: {
  430. return "OpenCL";
  431. }
  432. case SPV_ENV_OPENGL_4_0:
  433. case SPV_ENV_OPENGL_4_1:
  434. case SPV_ENV_OPENGL_4_2:
  435. case SPV_ENV_OPENGL_4_3:
  436. case SPV_ENV_OPENGL_4_5: {
  437. return "OpenGL";
  438. }
  439. case SPV_ENV_VULKAN_1_0:
  440. case SPV_ENV_VULKAN_1_1:
  441. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  442. case SPV_ENV_VULKAN_1_2:
  443. case SPV_ENV_VULKAN_1_3:
  444. case SPV_ENV_VULKAN_1_4: {
  445. return "Vulkan";
  446. }
  447. case SPV_ENV_UNIVERSAL_1_0:
  448. case SPV_ENV_UNIVERSAL_1_1:
  449. case SPV_ENV_UNIVERSAL_1_2:
  450. case SPV_ENV_UNIVERSAL_1_3:
  451. case SPV_ENV_UNIVERSAL_1_4:
  452. case SPV_ENV_UNIVERSAL_1_5:
  453. case SPV_ENV_UNIVERSAL_1_6: {
  454. return "Universal";
  455. }
  456. case SPV_ENV_WEBGPU_0:
  457. assert(false && "Deprecated target environment value.");
  458. break;
  459. case SPV_ENV_MAX:
  460. assert(false && "Invalid target environment value.");
  461. break;
  462. }
  463. return "Unknown";
  464. }
  465. std::string spvTargetEnvList(const int pad, const int wrap) {
  466. std::string ret;
  467. size_t max_line_len = wrap - pad; // The first line isn't padded
  468. std::string line;
  469. std::string sep = "";
  470. for (auto& name_env : spvTargetEnvNameMap) {
  471. std::string word = sep + name_env.first;
  472. if (line.length() + word.length() > max_line_len) {
  473. // Adding one word wouldn't fit, commit the line in progress and
  474. // start a new one.
  475. ret += line + "\n";
  476. line.assign(pad, ' ');
  477. // The first line is done. The max length now comprises the
  478. // padding.
  479. max_line_len = wrap;
  480. }
  481. line += word;
  482. sep = "|";
  483. }
  484. ret += line;
  485. return ret;
  486. }