spirv_target_env.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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);
  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. }
  72. return "";
  73. }
  74. uint32_t spvVersionForTargetEnv(spv_target_env env) {
  75. switch (env) {
  76. case SPV_ENV_UNIVERSAL_1_0:
  77. case SPV_ENV_VULKAN_1_0:
  78. case SPV_ENV_OPENCL_1_2:
  79. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  80. case SPV_ENV_OPENCL_2_0:
  81. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  82. case SPV_ENV_OPENCL_2_1:
  83. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  84. case SPV_ENV_OPENGL_4_0:
  85. case SPV_ENV_OPENGL_4_1:
  86. case SPV_ENV_OPENGL_4_2:
  87. case SPV_ENV_OPENGL_4_3:
  88. case SPV_ENV_OPENGL_4_5:
  89. return SPV_SPIRV_VERSION_WORD(1, 0);
  90. case SPV_ENV_UNIVERSAL_1_1:
  91. return SPV_SPIRV_VERSION_WORD(1, 1);
  92. case SPV_ENV_UNIVERSAL_1_2:
  93. case SPV_ENV_OPENCL_2_2:
  94. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  95. return SPV_SPIRV_VERSION_WORD(1, 2);
  96. case SPV_ENV_UNIVERSAL_1_3:
  97. case SPV_ENV_VULKAN_1_1:
  98. return SPV_SPIRV_VERSION_WORD(1, 3);
  99. case SPV_ENV_WEBGPU_0:
  100. assert(false);
  101. break;
  102. case SPV_ENV_UNIVERSAL_1_4:
  103. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  104. return SPV_SPIRV_VERSION_WORD(1, 4);
  105. case SPV_ENV_UNIVERSAL_1_5:
  106. case SPV_ENV_VULKAN_1_2:
  107. return SPV_SPIRV_VERSION_WORD(1, 5);
  108. }
  109. return SPV_SPIRV_VERSION_WORD(0, 0);
  110. }
  111. static const std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] = {
  112. {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
  113. {"vulkan1.0", SPV_ENV_VULKAN_1_0},
  114. {"vulkan1.1", SPV_ENV_VULKAN_1_1},
  115. {"vulkan1.2", SPV_ENV_VULKAN_1_2},
  116. {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
  117. {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
  118. {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
  119. {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
  120. {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
  121. {"spv1.5", SPV_ENV_UNIVERSAL_1_5},
  122. {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
  123. {"opencl1.2", SPV_ENV_OPENCL_1_2},
  124. {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
  125. {"opencl2.0", SPV_ENV_OPENCL_2_0},
  126. {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
  127. {"opencl2.1", SPV_ENV_OPENCL_2_1},
  128. {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
  129. {"opencl2.2", SPV_ENV_OPENCL_2_2},
  130. {"opengl4.0", SPV_ENV_OPENGL_4_0},
  131. {"opengl4.1", SPV_ENV_OPENGL_4_1},
  132. {"opengl4.2", SPV_ENV_OPENGL_4_2},
  133. {"opengl4.3", SPV_ENV_OPENGL_4_3},
  134. {"opengl4.5", SPV_ENV_OPENGL_4_5},
  135. };
  136. bool spvParseTargetEnv(const char* s, spv_target_env* env) {
  137. auto match = [s](const char* b) {
  138. return s && (0 == strncmp(s, b, strlen(b)));
  139. };
  140. for (auto& name_env : spvTargetEnvNameMap) {
  141. if (match(name_env.first)) {
  142. if (env) {
  143. *env = name_env.second;
  144. }
  145. return true;
  146. }
  147. }
  148. if (env) *env = SPV_ENV_UNIVERSAL_1_0;
  149. return false;
  150. }
  151. #define VULKAN_VER(MAJOR, MINOR) ((MAJOR << 22) | (MINOR << 12))
  152. #define SPIRV_VER(MAJOR, MINOR) ((MAJOR << 16) | (MINOR << 8))
  153. struct VulkanEnv {
  154. spv_target_env vulkan_env;
  155. uint32_t vulkan_ver;
  156. uint32_t spirv_ver;
  157. };
  158. // Maps each Vulkan target environment enum to the Vulkan version, and the
  159. // maximum supported SPIR-V version for that Vulkan environment.
  160. // Keep this ordered from least capable to most capable.
  161. static const VulkanEnv ordered_vulkan_envs[] = {
  162. {SPV_ENV_VULKAN_1_0, VULKAN_VER(1, 0), SPIRV_VER(1, 0)},
  163. {SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)},
  164. {SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)},
  165. {SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)}};
  166. bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver,
  167. spv_target_env* env) {
  168. for (auto triple : ordered_vulkan_envs) {
  169. if (triple.vulkan_ver >= vulkan_ver && triple.spirv_ver >= spirv_ver) {
  170. *env = triple.vulkan_env;
  171. return true;
  172. }
  173. }
  174. return false;
  175. }
  176. bool spvIsVulkanEnv(spv_target_env env) {
  177. switch (env) {
  178. case SPV_ENV_UNIVERSAL_1_0:
  179. case SPV_ENV_OPENCL_1_2:
  180. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  181. case SPV_ENV_OPENCL_2_0:
  182. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  183. case SPV_ENV_OPENCL_2_1:
  184. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  185. case SPV_ENV_OPENGL_4_0:
  186. case SPV_ENV_OPENGL_4_1:
  187. case SPV_ENV_OPENGL_4_2:
  188. case SPV_ENV_OPENGL_4_3:
  189. case SPV_ENV_OPENGL_4_5:
  190. case SPV_ENV_UNIVERSAL_1_1:
  191. case SPV_ENV_UNIVERSAL_1_2:
  192. case SPV_ENV_OPENCL_2_2:
  193. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  194. case SPV_ENV_UNIVERSAL_1_3:
  195. case SPV_ENV_UNIVERSAL_1_4:
  196. case SPV_ENV_UNIVERSAL_1_5:
  197. return false;
  198. case SPV_ENV_VULKAN_1_0:
  199. case SPV_ENV_VULKAN_1_1:
  200. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  201. case SPV_ENV_VULKAN_1_2:
  202. return true;
  203. case SPV_ENV_WEBGPU_0:
  204. assert(false);
  205. break;
  206. }
  207. return false;
  208. }
  209. bool spvIsOpenCLEnv(spv_target_env env) {
  210. switch (env) {
  211. case SPV_ENV_UNIVERSAL_1_0:
  212. case SPV_ENV_VULKAN_1_0:
  213. case SPV_ENV_UNIVERSAL_1_1:
  214. case SPV_ENV_OPENGL_4_0:
  215. case SPV_ENV_OPENGL_4_1:
  216. case SPV_ENV_OPENGL_4_2:
  217. case SPV_ENV_OPENGL_4_3:
  218. case SPV_ENV_OPENGL_4_5:
  219. case SPV_ENV_UNIVERSAL_1_2:
  220. case SPV_ENV_UNIVERSAL_1_3:
  221. case SPV_ENV_VULKAN_1_1:
  222. case SPV_ENV_UNIVERSAL_1_4:
  223. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  224. case SPV_ENV_UNIVERSAL_1_5:
  225. case SPV_ENV_VULKAN_1_2:
  226. return false;
  227. case SPV_ENV_OPENCL_1_2:
  228. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  229. case SPV_ENV_OPENCL_2_0:
  230. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  231. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  232. case SPV_ENV_OPENCL_EMBEDDED_2_2:
  233. case SPV_ENV_OPENCL_2_1:
  234. case SPV_ENV_OPENCL_2_2:
  235. return true;
  236. case SPV_ENV_WEBGPU_0:
  237. assert(false);
  238. break;
  239. }
  240. return false;
  241. }
  242. bool spvIsOpenGLEnv(spv_target_env env) {
  243. switch (env) {
  244. case SPV_ENV_UNIVERSAL_1_0:
  245. case SPV_ENV_VULKAN_1_0:
  246. case SPV_ENV_UNIVERSAL_1_1:
  247. case SPV_ENV_UNIVERSAL_1_2:
  248. case SPV_ENV_UNIVERSAL_1_3:
  249. case SPV_ENV_VULKAN_1_1:
  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. case SPV_ENV_UNIVERSAL_1_4:
  259. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  260. case SPV_ENV_UNIVERSAL_1_5:
  261. case SPV_ENV_VULKAN_1_2:
  262. return false;
  263. case SPV_ENV_OPENGL_4_0:
  264. case SPV_ENV_OPENGL_4_1:
  265. case SPV_ENV_OPENGL_4_2:
  266. case SPV_ENV_OPENGL_4_3:
  267. case SPV_ENV_OPENGL_4_5:
  268. return true;
  269. case SPV_ENV_WEBGPU_0:
  270. assert(false);
  271. break;
  272. }
  273. return false;
  274. }
  275. std::string spvLogStringForEnv(spv_target_env env) {
  276. switch (env) {
  277. case SPV_ENV_OPENCL_1_2:
  278. case SPV_ENV_OPENCL_2_0:
  279. case SPV_ENV_OPENCL_2_1:
  280. case SPV_ENV_OPENCL_2_2:
  281. case SPV_ENV_OPENCL_EMBEDDED_1_2:
  282. case SPV_ENV_OPENCL_EMBEDDED_2_0:
  283. case SPV_ENV_OPENCL_EMBEDDED_2_1:
  284. case SPV_ENV_OPENCL_EMBEDDED_2_2: {
  285. return "OpenCL";
  286. }
  287. case SPV_ENV_OPENGL_4_0:
  288. case SPV_ENV_OPENGL_4_1:
  289. case SPV_ENV_OPENGL_4_2:
  290. case SPV_ENV_OPENGL_4_3:
  291. case SPV_ENV_OPENGL_4_5: {
  292. return "OpenGL";
  293. }
  294. case SPV_ENV_VULKAN_1_0:
  295. case SPV_ENV_VULKAN_1_1:
  296. case SPV_ENV_VULKAN_1_1_SPIRV_1_4: {
  297. case SPV_ENV_VULKAN_1_2:
  298. return "Vulkan";
  299. }
  300. case SPV_ENV_UNIVERSAL_1_0:
  301. case SPV_ENV_UNIVERSAL_1_1:
  302. case SPV_ENV_UNIVERSAL_1_2:
  303. case SPV_ENV_UNIVERSAL_1_3:
  304. case SPV_ENV_UNIVERSAL_1_4:
  305. case SPV_ENV_UNIVERSAL_1_5: {
  306. return "Universal";
  307. }
  308. case SPV_ENV_WEBGPU_0:
  309. assert(false);
  310. break;
  311. }
  312. return "Unknown";
  313. }
  314. std::string spvTargetEnvList(const int pad, const int wrap) {
  315. std::string ret;
  316. size_t max_line_len = wrap - pad; // The first line isn't padded
  317. std::string line;
  318. std::string sep = "";
  319. for (auto& name_env : spvTargetEnvNameMap) {
  320. std::string word = sep + name_env.first;
  321. if (line.length() + word.length() > max_line_len) {
  322. // Adding one word wouldn't fit, commit the line in progress and
  323. // start a new one.
  324. ret += line + "\n";
  325. line.assign(pad, ' ');
  326. // The first line is done. The max length now comprises the
  327. // padding.
  328. max_line_len = wrap;
  329. }
  330. line += word;
  331. sep = "|";
  332. }
  333. ret += line;
  334. return ret;
  335. }