spirv_target_env.cpp 13 KB

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