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