spirv_target_env.cpp 12 KB

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