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