spirv_target_env.cpp 12 KB

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