spirv_target_env.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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 <cassert>
  16. #include <cstring>
  17. #include <string>
  18. #include "source/spirv_constant.h"
  19. #include "spirv-tools/libspirv.h"
  20. const char* spvTargetEnvDescription(spv_target_env env) {
  21. switch (env) {
  22. case SPV_ENV_UNIVERSAL_1_0:
  23. return "SPIR-V 1.0";
  24. case SPV_ENV_VULKAN_1_0:
  25. return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
  26. case SPV_ENV_UNIVERSAL_1_1:
  27. return "SPIR-V 1.1";
  28. case SPV_ENV_OPENCL_1_2:
  29. return "SPIR-V 1.0 (under OpenCL 1.2 Full Profile semantics)";
  30. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  31. return "SPIR-V 1.0 (under OpenCL 1.2 Embedded Profile semantics)";
  32. case SPV_ENV_OPENCL_2_0:
  33. return "SPIR-V 1.0 (under OpenCL 2.0 Full Profile semantics)";
  34. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  35. return "SPIR-V 1.0 (under OpenCL 2.0 Embedded Profile semantics)";
  36. case SPV_ENV_OPENCL_2_1:
  37. return "SPIR-V 1.0 (under OpenCL 2.1 Full Profile semantics)";
  38. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  39. return "SPIR-V 1.0 (under OpenCL 2.1 Embedded Profile semantics)";
  40. case SPV_ENV_OPENCL_2_2:
  41. return "SPIR-V 1.2 (under OpenCL 2.2 Full Profile semantics)";
  42. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  43. return "SPIR-V 1.2 (under OpenCL 2.2 Embedded Profile semantics)";
  44. case SPV_ENV_OPENGL_4_0:
  45. return "SPIR-V 1.0 (under OpenGL 4.0 semantics)";
  46. case SPV_ENV_OPENGL_4_1:
  47. return "SPIR-V 1.0 (under OpenGL 4.1 semantics)";
  48. case SPV_ENV_OPENGL_4_2:
  49. return "SPIR-V 1.0 (under OpenGL 4.2 semantics)";
  50. case SPV_ENV_OPENGL_4_3:
  51. return "SPIR-V 1.0 (under OpenGL 4.3 semantics)";
  52. case SPV_ENV_OPENGL_4_5:
  53. return "SPIR-V 1.0 (under OpenGL 4.5 semantics)";
  54. case SPV_ENV_UNIVERSAL_1_2:
  55. return "SPIR-V 1.2";
  56. case SPV_ENV_UNIVERSAL_1_3:
  57. return "SPIR-V 1.3";
  58. case SPV_ENV_VULKAN_1_1:
  59. return "SPIR-V 1.3 (under Vulkan 1.1 semantics)";
  60. case SPV_ENV_WEBGPU_0:
  61. assert(false && "Deprecated target environment value.");
  62. break;
  63. case SPV_ENV_UNIVERSAL_1_4:
  64. return "SPIR-V 1.4";
  65. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  66. return "SPIR-V 1.4 (under Vulkan 1.1 semantics)";
  67. case SPV_ENV_UNIVERSAL_1_5:
  68. return "SPIR-V 1.5";
  69. case SPV_ENV_VULKAN_1_2:
  70. return "SPIR-V 1.5 (under Vulkan 1.2 semantics)";
  71. case SPV_ENV_UNIVERSAL_1_6:
  72. return "SPIR-V 1.6";
  73. case SPV_ENV_VULKAN_1_3:
  74. return "SPIR-V 1.6 (under Vulkan 1.3 semantics)";
  75. case SPV_ENV_MAX:
  76. assert(false && "Invalid target environment value.");
  77. break;
  78. }
  79. return "";
  80. }
  81. uint32_t spvVersionForTargetEnv(spv_target_env env) {
  82. switch (env) {
  83. case SPV_ENV_UNIVERSAL_1_0:
  84. case SPV_ENV_VULKAN_1_0:
  85. case SPV_ENV_OPENCL_1_2:
  86. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  87. case SPV_ENV_OPENCL_2_0:
  88. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  89. case SPV_ENV_OPENCL_2_1:
  90. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  91. case SPV_ENV_OPENGL_4_0:
  92. case SPV_ENV_OPENGL_4_1:
  93. case SPV_ENV_OPENGL_4_2:
  94. case SPV_ENV_OPENGL_4_3:
  95. case SPV_ENV_OPENGL_4_5:
  96. return SPV_SPIRV_VERSION_WORD(1, 0);
  97. case SPV_ENV_UNIVERSAL_1_1:
  98. return SPV_SPIRV_VERSION_WORD(1, 1);
  99. case SPV_ENV_UNIVERSAL_1_2:
  100. case SPV_ENV_OPENCL_2_2:
  101. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  102. return SPV_SPIRV_VERSION_WORD(1, 2);
  103. case SPV_ENV_UNIVERSAL_1_3:
  104. case SPV_ENV_VULKAN_1_1:
  105. return SPV_SPIRV_VERSION_WORD(1, 3);
  106. case SPV_ENV_WEBGPU_0:
  107. assert(false && "Deprecated target environment value.");
  108. break;
  109. case SPV_ENV_UNIVERSAL_1_4:
  110. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  111. return SPV_SPIRV_VERSION_WORD(1, 4);
  112. case SPV_ENV_UNIVERSAL_1_5:
  113. case SPV_ENV_VULKAN_1_2:
  114. return SPV_SPIRV_VERSION_WORD(1, 5);
  115. case SPV_ENV_UNIVERSAL_1_6:
  116. case SPV_ENV_VULKAN_1_3:
  117. return SPV_SPIRV_VERSION_WORD(1, 6);
  118. case SPV_ENV_MAX:
  119. assert(false && "Invalid target environment value.");
  120. break;
  121. }
  122. return SPV_SPIRV_VERSION_WORD(0, 0);
  123. }
  124. static const std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] = {
  125. {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
  126. {"vulkan1.0", SPV_ENV_VULKAN_1_0},
  127. {"vulkan1.1", SPV_ENV_VULKAN_1_1},
  128. {"vulkan1.2", SPV_ENV_VULKAN_1_2},
  129. {"vulkan1.3", SPV_ENV_VULKAN_1_3},
  130. {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
  131. {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
  132. {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
  133. {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
  134. {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
  135. {"spv1.5", SPV_ENV_UNIVERSAL_1_5},
  136. {"spv1.6", SPV_ENV_UNIVERSAL_1_6},
  137. {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
  138. {"opencl1.2", SPV_ENV_OPENCL_1_2},
  139. {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
  140. {"opencl2.0", SPV_ENV_OPENCL_2_0},
  141. {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
  142. {"opencl2.1", SPV_ENV_OPENCL_2_1},
  143. {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
  144. {"opencl2.2", SPV_ENV_OPENCL_2_2},
  145. {"opengl4.0", SPV_ENV_OPENGL_4_0},
  146. {"opengl4.1", SPV_ENV_OPENGL_4_1},
  147. {"opengl4.2", SPV_ENV_OPENGL_4_2},
  148. {"opengl4.3", SPV_ENV_OPENGL_4_3},
  149. {"opengl4.5", SPV_ENV_OPENGL_4_5},
  150. };
  151. bool spvParseTargetEnv(const char* s, spv_target_env* env) {
  152. auto match = [s](const char* b) {
  153. return s && (0 == strncmp(s, b, strlen(b)));
  154. };
  155. for (auto& name_env : spvTargetEnvNameMap) {
  156. if (match(name_env.first)) {
  157. if (env) {
  158. *env = name_env.second;
  159. }
  160. return true;
  161. }
  162. }
  163. if (env) *env = SPV_ENV_UNIVERSAL_1_0;
  164. return false;
  165. }
  166. #define VULKAN_VER(MAJOR, MINOR) ((MAJOR << 22) | (MINOR << 12))
  167. #define SPIRV_VER(MAJOR, MINOR) ((MAJOR << 16) | (MINOR << 8))
  168. struct VulkanEnv {
  169. spv_target_env vulkan_env;
  170. uint32_t vulkan_ver;
  171. uint32_t spirv_ver;
  172. };
  173. // Maps each Vulkan target environment enum to the Vulkan version, and the
  174. // maximum supported SPIR-V version for that Vulkan environment.
  175. // Keep this ordered from least capable to most capable.
  176. static const VulkanEnv ordered_vulkan_envs[] = {
  177. {SPV_ENV_VULKAN_1_0, VULKAN_VER(1, 0), SPIRV_VER(1, 0)},
  178. {SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)},
  179. {SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)},
  180. {SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)},
  181. {SPV_ENV_VULKAN_1_3, VULKAN_VER(1, 3), SPIRV_VER(1, 6)}};
  182. bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver,
  183. spv_target_env* env) {
  184. for (auto triple : ordered_vulkan_envs) {
  185. if (triple.vulkan_ver >= vulkan_ver && triple.spirv_ver >= spirv_ver) {
  186. *env = triple.vulkan_env;
  187. return true;
  188. }
  189. }
  190. return false;
  191. }
  192. bool spvIsVulkanEnv(spv_target_env env) {
  193. switch (env) {
  194. case SPV_ENV_UNIVERSAL_1_0:
  195. case SPV_ENV_OPENCL_1_2:
  196. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  197. case SPV_ENV_OPENCL_2_0:
  198. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  199. case SPV_ENV_OPENCL_2_1:
  200. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  201. case SPV_ENV_OPENGL_4_0:
  202. case SPV_ENV_OPENGL_4_1:
  203. case SPV_ENV_OPENGL_4_2:
  204. case SPV_ENV_OPENGL_4_3:
  205. case SPV_ENV_OPENGL_4_5:
  206. case SPV_ENV_UNIVERSAL_1_1:
  207. case SPV_ENV_UNIVERSAL_1_2:
  208. case SPV_ENV_OPENCL_2_2:
  209. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  210. case SPV_ENV_UNIVERSAL_1_3:
  211. case SPV_ENV_UNIVERSAL_1_4:
  212. case SPV_ENV_UNIVERSAL_1_5:
  213. case SPV_ENV_UNIVERSAL_1_6:
  214. return false;
  215. case SPV_ENV_VULKAN_1_0:
  216. case SPV_ENV_VULKAN_1_1:
  217. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  218. case SPV_ENV_VULKAN_1_2:
  219. case SPV_ENV_VULKAN_1_3:
  220. return true;
  221. case SPV_ENV_WEBGPU_0:
  222. assert(false && "Deprecated target environment value.");
  223. break;
  224. case SPV_ENV_MAX:
  225. assert(false && "Invalid target environment value.");
  226. break;
  227. }
  228. return false;
  229. }
  230. bool spvIsOpenCLEnv(spv_target_env env) {
  231. switch (env) {
  232. case SPV_ENV_UNIVERSAL_1_0:
  233. case SPV_ENV_VULKAN_1_0:
  234. case SPV_ENV_UNIVERSAL_1_1:
  235. case SPV_ENV_OPENGL_4_0:
  236. case SPV_ENV_OPENGL_4_1:
  237. case SPV_ENV_OPENGL_4_2:
  238. case SPV_ENV_OPENGL_4_3:
  239. case SPV_ENV_OPENGL_4_5:
  240. case SPV_ENV_UNIVERSAL_1_2:
  241. case SPV_ENV_UNIVERSAL_1_3:
  242. case SPV_ENV_VULKAN_1_1:
  243. case SPV_ENV_UNIVERSAL_1_4:
  244. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  245. case SPV_ENV_UNIVERSAL_1_5:
  246. case SPV_ENV_VULKAN_1_2:
  247. case SPV_ENV_UNIVERSAL_1_6:
  248. case SPV_ENV_VULKAN_1_3:
  249. return false;
  250. case SPV_ENV_OPENCL_1_2:
  251. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  252. case SPV_ENV_OPENCL_2_0:
  253. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  254. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  255. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  256. case SPV_ENV_OPENCL_2_1:
  257. case SPV_ENV_OPENCL_2_2:
  258. return true;
  259. case SPV_ENV_WEBGPU_0:
  260. assert(false && "Deprecated target environment value.");
  261. break;
  262. case SPV_ENV_MAX:
  263. assert(false && "Invalid target environment value.");
  264. break;
  265. }
  266. return false;
  267. }
  268. bool spvIsOpenGLEnv(spv_target_env env) {
  269. switch (env) {
  270. case SPV_ENV_UNIVERSAL_1_0:
  271. case SPV_ENV_VULKAN_1_0:
  272. case SPV_ENV_UNIVERSAL_1_1:
  273. case SPV_ENV_UNIVERSAL_1_2:
  274. case SPV_ENV_UNIVERSAL_1_3:
  275. case SPV_ENV_VULKAN_1_1:
  276. case SPV_ENV_OPENCL_1_2:
  277. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  278. case SPV_ENV_OPENCL_2_0:
  279. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  280. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  281. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  282. case SPV_ENV_OPENCL_2_1:
  283. case SPV_ENV_OPENCL_2_2:
  284. case SPV_ENV_UNIVERSAL_1_4:
  285. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  286. case SPV_ENV_UNIVERSAL_1_5:
  287. case SPV_ENV_VULKAN_1_2:
  288. case SPV_ENV_UNIVERSAL_1_6:
  289. case SPV_ENV_VULKAN_1_3:
  290. return false;
  291. case SPV_ENV_OPENGL_4_0:
  292. case SPV_ENV_OPENGL_4_1:
  293. case SPV_ENV_OPENGL_4_2:
  294. case SPV_ENV_OPENGL_4_3:
  295. case SPV_ENV_OPENGL_4_5:
  296. return true;
  297. case SPV_ENV_WEBGPU_0:
  298. assert(false && "Deprecated target environment value.");
  299. break;
  300. case SPV_ENV_MAX:
  301. assert(false && "Invalid target environment value.");
  302. break;
  303. }
  304. return false;
  305. }
  306. bool spvIsValidEnv(spv_target_env env) {
  307. switch (env) {
  308. case SPV_ENV_UNIVERSAL_1_0:
  309. case SPV_ENV_VULKAN_1_0:
  310. case SPV_ENV_UNIVERSAL_1_1:
  311. case SPV_ENV_UNIVERSAL_1_2:
  312. case SPV_ENV_UNIVERSAL_1_3:
  313. case SPV_ENV_VULKAN_1_1:
  314. case SPV_ENV_OPENCL_1_2:
  315. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  316. case SPV_ENV_OPENCL_2_0:
  317. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  318. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  319. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  320. case SPV_ENV_OPENCL_2_1:
  321. case SPV_ENV_OPENCL_2_2:
  322. case SPV_ENV_UNIVERSAL_1_4:
  323. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  324. case SPV_ENV_UNIVERSAL_1_5:
  325. case SPV_ENV_VULKAN_1_2:
  326. case SPV_ENV_UNIVERSAL_1_6:
  327. case SPV_ENV_VULKAN_1_3:
  328. case SPV_ENV_OPENGL_4_0:
  329. case SPV_ENV_OPENGL_4_1:
  330. case SPV_ENV_OPENGL_4_2:
  331. case SPV_ENV_OPENGL_4_3:
  332. case SPV_ENV_OPENGL_4_5:
  333. return true;
  334. case SPV_ENV_WEBGPU_0:
  335. case SPV_ENV_MAX:
  336. break;
  337. }
  338. return false;
  339. }
  340. std::string spvLogStringForEnv(spv_target_env env) {
  341. switch (env) {
  342. case SPV_ENV_OPENCL_1_2:
  343. case SPV_ENV_OPENCL_2_0:
  344. case SPV_ENV_OPENCL_2_1:
  345. case SPV_ENV_OPENCL_2_2:
  346. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  347. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  348. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  349. case SPV_ENV_OPENCL_EMBEDDED_2_2: {
  350. return "OpenCL";
  351. }
  352. case SPV_ENV_OPENGL_4_0:
  353. case SPV_ENV_OPENGL_4_1:
  354. case SPV_ENV_OPENGL_4_2:
  355. case SPV_ENV_OPENGL_4_3:
  356. case SPV_ENV_OPENGL_4_5: {
  357. return "OpenGL";
  358. }
  359. case SPV_ENV_VULKAN_1_0:
  360. case SPV_ENV_VULKAN_1_1:
  361. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  362. case SPV_ENV_VULKAN_1_2:
  363. case SPV_ENV_VULKAN_1_3: {
  364. return "Vulkan";
  365. }
  366. case SPV_ENV_UNIVERSAL_1_0:
  367. case SPV_ENV_UNIVERSAL_1_1:
  368. case SPV_ENV_UNIVERSAL_1_2:
  369. case SPV_ENV_UNIVERSAL_1_3:
  370. case SPV_ENV_UNIVERSAL_1_4:
  371. case SPV_ENV_UNIVERSAL_1_5:
  372. case SPV_ENV_UNIVERSAL_1_6: {
  373. return "Universal";
  374. }
  375. case SPV_ENV_WEBGPU_0:
  376. assert(false && "Deprecated target environment value.");
  377. break;
  378. case SPV_ENV_MAX:
  379. assert(false && "Invalid target environment value.");
  380. break;
  381. }
  382. return "Unknown";
  383. }
  384. std::string spvTargetEnvList(const int pad, const int wrap) {
  385. std::string ret;
  386. size_t max_line_len = wrap - pad; // The first line isn't padded
  387. std::string line;
  388. std::string sep = "";
  389. for (auto& name_env : spvTargetEnvNameMap) {
  390. std::string word = sep + name_env.first;
  391. if (line.length() + word.length() > max_line_len) {
  392. // Adding one word wouldn't fit, commit the line in progress and
  393. // start a new one.
  394. ret += line + "\n";
  395. line.assign(pad, ' ');
  396. // The first line is done. The max length now comprises the
  397. // padding.
  398. max_line_len = wrap;
  399. }
  400. line += word;
  401. sep = "|";
  402. }
  403. ret += line;
  404. return ret;
  405. }