1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "GLSLANG/ShaderLang.h"
8
9 #include <assert.h>
10 #include <math.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sstream>
15 #include <vector>
16 #include "angle_gl.h"
17
18 #if defined(ANGLE_ENABLE_VULKAN)
19 // SPIR-V tools include for disassembly.
20 # include <spirv-tools/libspirv.hpp>
21 #endif
22
23 //
24 // Return codes from main.
25 //
26 enum TFailCode
27 {
28 ESuccess = 0,
29 EFailUsage,
30 EFailCompile,
31 EFailCompilerCreate,
32 };
33
34 static void usage();
35 static sh::GLenum FindShaderType(const char *fileName);
36 static bool CompileFile(char *fileName, ShHandle compiler, const ShCompileOptions &compileOptions);
37 static void LogMsg(const char *msg, const char *name, const int num, const char *logName);
38 static void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVariable &var);
39 static void PrintActiveVariables(ShHandle compiler);
40
41 // If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is
42 // broken into that many chunks. This will affect file/line numbering in
43 // the preprocessor.
44 const unsigned int NUM_SOURCE_STRINGS = 1;
45 typedef std::vector<char *> ShaderSource;
46 static bool ReadShaderSource(const char *fileName, ShaderSource &source);
47 static void FreeShaderSource(ShaderSource &source);
48
49 static bool ParseGLSLOutputVersion(const std::string &, ShShaderOutput *outResult);
50 static bool ParseIntValue(const std::string &, int emptyDefault, int *outValue);
51
52 static void PrintSpirv(const sh::BinaryBlob &blob);
53
54 //
55 // Set up the per compile resources
56 //
GenerateResources(ShBuiltInResources * resources)57 void GenerateResources(ShBuiltInResources *resources)
58 {
59 sh::InitBuiltInResources(resources);
60
61 resources->MaxVertexAttribs = 8;
62 resources->MaxVertexUniformVectors = 128;
63 resources->MaxVaryingVectors = 8;
64 resources->MaxVertexTextureImageUnits = 0;
65 resources->MaxCombinedTextureImageUnits = 8;
66 resources->MaxTextureImageUnits = 8;
67 resources->MaxFragmentUniformVectors = 16;
68 resources->MaxDrawBuffers = 1;
69 resources->MaxDualSourceDrawBuffers = 1;
70
71 resources->OES_standard_derivatives = 0;
72 resources->OES_EGL_image_external = 0;
73 resources->EXT_geometry_shader = 1;
74 resources->ANGLE_texture_multisample = 0;
75 resources->APPLE_clip_distance = 0;
76 }
77
main(int argc,char * argv[])78 int main(int argc, char *argv[])
79 {
80 TFailCode failCode = ESuccess;
81
82 ShCompileOptions compileOptions = {};
83 int numCompiles = 0;
84 ShHandle vertexCompiler = 0;
85 ShHandle fragmentCompiler = 0;
86 ShHandle computeCompiler = 0;
87 ShHandle geometryCompiler = 0;
88 ShHandle tessEvalCompiler = 0;
89 ShHandle tessControlCompiler = 0;
90 ShShaderSpec spec = SH_GLES2_SPEC;
91 ShShaderOutput output = SH_ESSL_OUTPUT;
92
93 sh::Initialize();
94
95 ShBuiltInResources resources;
96 GenerateResources(&resources);
97
98 bool printActiveVariables = false;
99
100 argc--;
101 argv++;
102 for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++)
103 {
104 if (argv[0][0] == '-')
105 {
106 switch (argv[0][1])
107 {
108 case 'i':
109 compileOptions.intermediateTree = true;
110 break;
111 case 'o':
112 compileOptions.objectCode = true;
113 break;
114 case 'u':
115 printActiveVariables = true;
116 break;
117 case 's':
118 if (argv[0][2] == '=')
119 {
120 switch (argv[0][3])
121 {
122 case 'e':
123 if (argv[0][4] == '3')
124 {
125 if (argv[0][5] == '1')
126 {
127 spec = SH_GLES3_1_SPEC;
128 }
129 else if (argv[0][5] == '2')
130 {
131 spec = SH_GLES3_2_SPEC;
132 }
133 else
134 {
135 spec = SH_GLES3_SPEC;
136 }
137 }
138 else
139 {
140 spec = SH_GLES2_SPEC;
141 }
142 break;
143 case 'w':
144 if (argv[0][4] == '3')
145 {
146 spec = SH_WEBGL3_SPEC;
147 }
148 else if (argv[0][4] == '2')
149 {
150 spec = SH_WEBGL2_SPEC;
151 }
152 else if (argv[0][4] == 'n')
153 {
154 spec = SH_WEBGL_SPEC;
155 }
156 else
157 {
158 spec = SH_WEBGL_SPEC;
159 resources.FragmentPrecisionHigh = 1;
160 }
161 break;
162 case 'd':
163 if (argv[0][4] == 'c')
164 {
165 spec = SH_GL_COMPATIBILITY_SPEC;
166 }
167 else
168 {
169 spec = SH_GL_CORE_SPEC;
170 }
171 break;
172 default:
173 failCode = EFailUsage;
174 }
175 }
176 else
177 {
178 failCode = EFailUsage;
179 }
180 break;
181 case 'b':
182 if (argv[0][2] == '=')
183 {
184 switch (argv[0][3])
185 {
186 case 'e':
187 output = SH_ESSL_OUTPUT;
188 compileOptions.initializeUninitializedLocals = true;
189 break;
190 case 'g':
191 if (!ParseGLSLOutputVersion(&argv[0][sizeof("-b=g") - 1], &output))
192 {
193 failCode = EFailUsage;
194 }
195 compileOptions.initializeUninitializedLocals = true;
196 break;
197 case 'v':
198 output = SH_SPIRV_VULKAN_OUTPUT;
199 compileOptions.initializeUninitializedLocals = true;
200 break;
201 case 'h':
202 if (argv[0][4] == '1' && argv[0][5] == '1')
203 {
204 output = SH_HLSL_4_1_OUTPUT;
205 }
206 else
207 {
208 output = SH_HLSL_3_0_OUTPUT;
209 }
210 break;
211 case 'm':
212 output = SH_MSL_METAL_OUTPUT;
213 break;
214 default:
215 failCode = EFailUsage;
216 }
217 }
218 else
219 {
220 failCode = EFailUsage;
221 }
222 break;
223 case 'x':
224 if (argv[0][2] == '=')
225 {
226 // clang-format off
227 switch (argv[0][3])
228 {
229 case 'i': resources.OES_EGL_image_external = 1; break;
230 case 'd': resources.OES_standard_derivatives = 1; break;
231 case 'r': resources.ARB_texture_rectangle = 1; break;
232 case 'b':
233 if (ParseIntValue(&argv[0][sizeof("-x=b") - 1], 1,
234 &resources.MaxDualSourceDrawBuffers))
235 {
236 resources.EXT_blend_func_extended = 1;
237 }
238 else
239 {
240 failCode = EFailUsage;
241 }
242 break;
243 case 'w':
244 if (ParseIntValue(&argv[0][sizeof("-x=w") - 1], 1,
245 &resources.MaxDrawBuffers))
246 {
247 resources.EXT_draw_buffers = 1;
248 }
249 else
250 {
251 failCode = EFailUsage;
252 }
253 break;
254 case 'g': resources.EXT_frag_depth = 1; break;
255 case 'l': resources.EXT_shader_texture_lod = 1; break;
256 case 'f': resources.EXT_shader_framebuffer_fetch = 1; break;
257 case 'n': resources.NV_shader_framebuffer_fetch = 1; break;
258 case 'a': resources.ARM_shader_framebuffer_fetch = 1; break;
259 case 'm':
260 resources.OVR_multiview2 = 1;
261 resources.OVR_multiview = 1;
262 compileOptions.initializeBuiltinsForInstancedMultiview = true;
263 compileOptions.selectViewInNvGLSLVertexShader = true;
264 break;
265 case 'y': resources.EXT_YUV_target = 1; break;
266 case 's': resources.OES_sample_variables = 1; break;
267 default: failCode = EFailUsage;
268 }
269 // clang-format on
270 }
271 else
272 {
273 failCode = EFailUsage;
274 }
275 break;
276 default:
277 failCode = EFailUsage;
278 }
279 }
280 else
281 {
282 if (spec != SH_GLES2_SPEC && spec != SH_WEBGL_SPEC)
283 {
284 resources.MaxDrawBuffers = 8;
285 resources.MaxVertexTextureImageUnits = 16;
286 resources.MaxTextureImageUnits = 16;
287 }
288 ShHandle compiler = 0;
289 switch (FindShaderType(argv[0]))
290 {
291 case GL_VERTEX_SHADER:
292 if (vertexCompiler == 0)
293 {
294 vertexCompiler =
295 sh::ConstructCompiler(GL_VERTEX_SHADER, spec, output, &resources);
296 }
297 compiler = vertexCompiler;
298 break;
299 case GL_FRAGMENT_SHADER:
300 if (fragmentCompiler == 0)
301 {
302 fragmentCompiler =
303 sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);
304 }
305 compiler = fragmentCompiler;
306 break;
307 case GL_COMPUTE_SHADER:
308 if (computeCompiler == 0)
309 {
310 computeCompiler =
311 sh::ConstructCompiler(GL_COMPUTE_SHADER, spec, output, &resources);
312 }
313 compiler = computeCompiler;
314 break;
315 case GL_GEOMETRY_SHADER_EXT:
316 if (geometryCompiler == 0)
317 {
318 resources.EXT_geometry_shader = 1;
319 geometryCompiler =
320 sh::ConstructCompiler(GL_GEOMETRY_SHADER_EXT, spec, output, &resources);
321 }
322 compiler = geometryCompiler;
323 break;
324 case GL_TESS_CONTROL_SHADER_EXT:
325 if (tessControlCompiler == 0)
326 {
327 assert(spec == SH_GLES3_1_SPEC || spec == SH_GLES3_2_SPEC);
328 resources.EXT_tessellation_shader = 1;
329 tessControlCompiler = sh::ConstructCompiler(GL_TESS_CONTROL_SHADER_EXT,
330 spec, output, &resources);
331 }
332 compiler = tessControlCompiler;
333 break;
334 case GL_TESS_EVALUATION_SHADER_EXT:
335 if (tessEvalCompiler == 0)
336 {
337 assert(spec == SH_GLES3_1_SPEC || spec == SH_GLES3_2_SPEC);
338 resources.EXT_tessellation_shader = 1;
339 tessEvalCompiler = sh::ConstructCompiler(GL_TESS_EVALUATION_SHADER_EXT,
340 spec, output, &resources);
341 }
342 compiler = tessEvalCompiler;
343 break;
344 default:
345 break;
346 }
347 if (compiler)
348 {
349 switch (output)
350 {
351 case SH_HLSL_3_0_OUTPUT:
352 case SH_HLSL_4_1_OUTPUT:
353 case SH_HLSL_4_0_FL9_3_OUTPUT:
354 compileOptions.selectViewInNvGLSLVertexShader = false;
355 break;
356 default:
357 break;
358 }
359
360 bool compiled = CompileFile(argv[0], compiler, compileOptions);
361
362 LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG");
363 std::string log = sh::GetInfoLog(compiler);
364 puts(log.c_str());
365 LogMsg("END", "COMPILER", numCompiles, "INFO LOG");
366 printf("\n\n");
367
368 if (compiled && compileOptions.objectCode)
369 {
370 LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE");
371 if (output != SH_SPIRV_VULKAN_OUTPUT)
372 {
373 const std::string &code = sh::GetObjectCode(compiler);
374 puts(code.c_str());
375 }
376 else
377 {
378 const sh::BinaryBlob &blob = sh::GetObjectBinaryBlob(compiler);
379 PrintSpirv(blob);
380 }
381 LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");
382 printf("\n\n");
383 }
384 if (compiled && printActiveVariables)
385 {
386 LogMsg("BEGIN", "COMPILER", numCompiles, "VARIABLES");
387 PrintActiveVariables(compiler);
388 LogMsg("END", "COMPILER", numCompiles, "VARIABLES");
389 printf("\n\n");
390 }
391 if (!compiled)
392 failCode = EFailCompile;
393 ++numCompiles;
394 }
395 else
396 {
397 failCode = EFailCompilerCreate;
398 }
399 }
400 }
401
402 if ((vertexCompiler == 0) && (fragmentCompiler == 0) && (computeCompiler == 0) &&
403 (geometryCompiler == 0) && (tessControlCompiler == 0) && (tessEvalCompiler == 0))
404 {
405 failCode = EFailUsage;
406 }
407 if (failCode == EFailUsage)
408 {
409 usage();
410 }
411
412 if (vertexCompiler)
413 {
414 sh::Destruct(vertexCompiler);
415 }
416 if (fragmentCompiler)
417 {
418 sh::Destruct(fragmentCompiler);
419 }
420 if (computeCompiler)
421 {
422 sh::Destruct(computeCompiler);
423 }
424 if (geometryCompiler)
425 {
426 sh::Destruct(geometryCompiler);
427 }
428 if (tessControlCompiler)
429 {
430 sh::Destruct(tessControlCompiler);
431 }
432 if (tessEvalCompiler)
433 {
434 sh::Destruct(tessEvalCompiler);
435 }
436
437 sh::Finalize();
438
439 return failCode;
440 }
441
442 //
443 // print usage to stdout
444 //
usage()445 void usage()
446 {
447 // clang-format off
448 printf(
449 "Usage: translate [-i -o -u -l -b=e -b=g -b=h9 -x=i -x=d] file1 file2 ...\n"
450 "Where: filename : filename ending in .frag*, .vert*, .comp*, .geom*, .tcs* or .tes*\n"
451 " -i : print intermediate tree\n"
452 " -o : print translated code\n"
453 " -u : print active attribs, uniforms, varyings and program outputs\n"
454 " -s=e2 : use GLES2 spec (this is by default)\n"
455 " -s=e3 : use GLES3 spec\n"
456 " -s=e31 : use GLES31 spec (in development)\n"
457 " -s=e32 : use GLES32 spec (in development)\n"
458 " -s=w : use WebGL 1.0 spec\n"
459 " -s=wn : use WebGL 1.0 spec with no highp support in fragment shaders\n"
460 " -s=w2 : use WebGL 2.0 spec\n"
461 " -s=d : use Desktop Core spec (in development)\n"
462 " -s=dc : use Desktop Compatibility spec (in development)\n"
463 " -b=e : output GLSL ES code (this is by default)\n"
464 " -b=g : output GLSL code (compatibility profile)\n"
465 " -b=g[NUM]: output GLSL code (NUM can be 130, 140, 150, 330, 400, 410, 420, 430, "
466 "440, 450)\n"
467 " -b=v : output Vulkan SPIR-V code\n"
468 " -b=h9 : output HLSL9 code\n"
469 " -b=h11 : output HLSL11 code\n"
470 " -b=m : output MSL code (direct)\n"
471 " -x=i : enable GL_OES_EGL_image_external\n"
472 " -x=d : enable GL_OES_EGL_standard_derivatives\n"
473 " -x=r : enable ARB_texture_rectangle\n"
474 " -x=b[NUM]: enable EXT_blend_func_extended (NUM default 1)\n"
475 " -x=w[NUM]: enable EXT_draw_buffers (NUM default 1)\n"
476 " -x=g : enable EXT_frag_depth\n"
477 " -x=l : enable EXT_shader_texture_lod\n"
478 " -x=f : enable EXT_shader_framebuffer_fetch\n"
479 " -x=n : enable NV_shader_framebuffer_fetch\n"
480 " -x=a : enable ARM_shader_framebuffer_fetch\n"
481 " -x=m : enable OVR_multiview\n"
482 " -x=y : enable YUV_target\n"
483 " -x=s : enable OES_sample_variables\n");
484 // clang-format on
485 }
486
487 //
488 // Deduce the shader type from the filename. Files must end in one of the
489 // following extensions:
490 //
491 // .frag* = fragment shader
492 // .vert* = vertex shader
493 // .comp* = compute shader
494 // .geom* = geometry shader
495 // .tcs* = tessellation control shader
496 // .tes* = tessellation evaluation shader
497 //
FindShaderType(const char * fileName)498 sh::GLenum FindShaderType(const char *fileName)
499 {
500 assert(fileName);
501
502 const char *ext = strrchr(fileName, '.');
503
504 if (ext && strcmp(ext, ".sl") == 0)
505 for (; ext > fileName && ext[0] != '.'; ext--)
506 ;
507
508 ext = strrchr(fileName, '.');
509 if (ext)
510 {
511 if (strncmp(ext, ".frag", 5) == 0)
512 return GL_FRAGMENT_SHADER;
513 if (strncmp(ext, ".vert", 5) == 0)
514 return GL_VERTEX_SHADER;
515 if (strncmp(ext, ".comp", 5) == 0)
516 return GL_COMPUTE_SHADER;
517 if (strncmp(ext, ".geom", 5) == 0)
518 return GL_GEOMETRY_SHADER_EXT;
519 if (strncmp(ext, ".tcs", 5) == 0)
520 return GL_TESS_CONTROL_SHADER_EXT;
521 if (strncmp(ext, ".tes", 5) == 0)
522 return GL_TESS_EVALUATION_SHADER_EXT;
523 }
524
525 return GL_FRAGMENT_SHADER;
526 }
527
528 //
529 // Read a file's data into a string, and compile it using sh::Compile
530 //
CompileFile(char * fileName,ShHandle compiler,const ShCompileOptions & compileOptions)531 bool CompileFile(char *fileName, ShHandle compiler, const ShCompileOptions &compileOptions)
532 {
533 ShaderSource source;
534 if (!ReadShaderSource(fileName, source))
535 return false;
536
537 int ret = sh::Compile(compiler, &source[0], source.size(), compileOptions);
538
539 FreeShaderSource(source);
540 return ret ? true : false;
541 }
542
LogMsg(const char * msg,const char * name,const int num,const char * logName)543 void LogMsg(const char *msg, const char *name, const int num, const char *logName)
544 {
545 printf("#### %s %s %d %s ####\n", msg, name, num, logName);
546 }
547
PrintVariable(const std::string & prefix,size_t index,const sh::ShaderVariable & var)548 void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVariable &var)
549 {
550 std::string typeName;
551 switch (var.type)
552 {
553 case GL_FLOAT:
554 typeName = "GL_FLOAT";
555 break;
556 case GL_FLOAT_VEC2:
557 typeName = "GL_FLOAT_VEC2";
558 break;
559 case GL_FLOAT_VEC3:
560 typeName = "GL_FLOAT_VEC3";
561 break;
562 case GL_FLOAT_VEC4:
563 typeName = "GL_FLOAT_VEC4";
564 break;
565 case GL_INT:
566 typeName = "GL_INT";
567 break;
568 case GL_INT_VEC2:
569 typeName = "GL_INT_VEC2";
570 break;
571 case GL_INT_VEC3:
572 typeName = "GL_INT_VEC3";
573 break;
574 case GL_INT_VEC4:
575 typeName = "GL_INT_VEC4";
576 break;
577 case GL_UNSIGNED_INT:
578 typeName = "GL_UNSIGNED_INT";
579 break;
580 case GL_UNSIGNED_INT_VEC2:
581 typeName = "GL_UNSIGNED_INT_VEC2";
582 break;
583 case GL_UNSIGNED_INT_VEC3:
584 typeName = "GL_UNSIGNED_INT_VEC3";
585 break;
586 case GL_UNSIGNED_INT_VEC4:
587 typeName = "GL_UNSIGNED_INT_VEC4";
588 break;
589 case GL_BOOL:
590 typeName = "GL_BOOL";
591 break;
592 case GL_BOOL_VEC2:
593 typeName = "GL_BOOL_VEC2";
594 break;
595 case GL_BOOL_VEC3:
596 typeName = "GL_BOOL_VEC3";
597 break;
598 case GL_BOOL_VEC4:
599 typeName = "GL_BOOL_VEC4";
600 break;
601 case GL_FLOAT_MAT2:
602 typeName = "GL_FLOAT_MAT2";
603 break;
604 case GL_FLOAT_MAT3:
605 typeName = "GL_FLOAT_MAT3";
606 break;
607 case GL_FLOAT_MAT4:
608 typeName = "GL_FLOAT_MAT4";
609 break;
610 case GL_FLOAT_MAT2x3:
611 typeName = "GL_FLOAT_MAT2x3";
612 break;
613 case GL_FLOAT_MAT3x2:
614 typeName = "GL_FLOAT_MAT3x2";
615 break;
616 case GL_FLOAT_MAT4x2:
617 typeName = "GL_FLOAT_MAT4x2";
618 break;
619 case GL_FLOAT_MAT2x4:
620 typeName = "GL_FLOAT_MAT2x4";
621 break;
622 case GL_FLOAT_MAT3x4:
623 typeName = "GL_FLOAT_MAT3x4";
624 break;
625 case GL_FLOAT_MAT4x3:
626 typeName = "GL_FLOAT_MAT4x3";
627 break;
628
629 case GL_SAMPLER_2D:
630 typeName = "GL_SAMPLER_2D";
631 break;
632 case GL_SAMPLER_3D:
633 typeName = "GL_SAMPLER_3D";
634 break;
635 case GL_SAMPLER_CUBE:
636 typeName = "GL_SAMPLER_CUBE";
637 break;
638 case GL_SAMPLER_CUBE_SHADOW:
639 typeName = "GL_SAMPLER_CUBE_SHADOW";
640 break;
641 case GL_SAMPLER_2D_SHADOW:
642 typeName = "GL_SAMPLER_2D_ARRAY_SHADOW";
643 break;
644 case GL_SAMPLER_2D_ARRAY:
645 typeName = "GL_SAMPLER_2D_ARRAY";
646 break;
647 case GL_SAMPLER_2D_ARRAY_SHADOW:
648 typeName = "GL_SAMPLER_2D_ARRAY_SHADOW";
649 break;
650 case GL_SAMPLER_2D_MULTISAMPLE:
651 typeName = "GL_SAMPLER_2D_MULTISAMPLE";
652 break;
653 case GL_IMAGE_2D:
654 typeName = "GL_IMAGE_2D";
655 break;
656 case GL_IMAGE_3D:
657 typeName = "GL_IMAGE_3D";
658 break;
659 case GL_IMAGE_CUBE:
660 typeName = "GL_IMAGE_CUBE";
661 break;
662 case GL_IMAGE_2D_ARRAY:
663 typeName = "GL_IMAGE_2D_ARRAY";
664 break;
665
666 case GL_INT_SAMPLER_2D:
667 typeName = "GL_INT_SAMPLER_2D";
668 break;
669 case GL_INT_SAMPLER_3D:
670 typeName = "GL_INT_SAMPLER_3D";
671 break;
672 case GL_INT_SAMPLER_CUBE:
673 typeName = "GL_INT_SAMPLER_CUBE";
674 break;
675 case GL_INT_SAMPLER_2D_ARRAY:
676 typeName = "GL_INT_SAMPLER_2D_ARRAY";
677 break;
678 case GL_INT_SAMPLER_2D_MULTISAMPLE:
679 typeName = "GL_INT_SAMPLER_2D_MULTISAMPLE";
680 break;
681 case GL_INT_IMAGE_2D:
682 typeName = "GL_INT_IMAGE_2D";
683 break;
684 case GL_INT_IMAGE_3D:
685 typeName = "GL_INT_IMAGE_3D";
686 break;
687 case GL_INT_IMAGE_CUBE:
688 typeName = "GL_INT_IMAGE_CUBE";
689 break;
690 case GL_INT_IMAGE_2D_ARRAY:
691 typeName = "GL_INT_IMAGE_2D_ARRAY";
692 break;
693
694 case GL_UNSIGNED_INT_SAMPLER_2D:
695 typeName = "GL_UNSIGNED_INT_SAMPLER_2D";
696 break;
697 case GL_UNSIGNED_INT_SAMPLER_3D:
698 typeName = "GL_UNSIGNED_INT_SAMPLER_3D";
699 break;
700 case GL_UNSIGNED_INT_SAMPLER_CUBE:
701 typeName = "GL_UNSIGNED_INT_SAMPLER_CUBE";
702 break;
703 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
704 typeName = "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY";
705 break;
706 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
707 typeName = "GL_UNSIGNED_INT_ATOMIC_COUNTER";
708 break;
709 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
710 typeName = "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE";
711 break;
712 case GL_UNSIGNED_INT_IMAGE_2D:
713 typeName = "GL_UNSIGNED_INT_IMAGE_2D";
714 break;
715 case GL_UNSIGNED_INT_IMAGE_3D:
716 typeName = "GL_UNSIGNED_INT_IMAGE_3D";
717 break;
718 case GL_UNSIGNED_INT_IMAGE_CUBE:
719 typeName = "GL_UNSIGNED_INT_IMAGE_CUBE";
720 break;
721 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
722 typeName = "GL_UNSIGNED_INT_IMAGE_2D_ARRAY";
723 break;
724
725 case GL_SAMPLER_EXTERNAL_OES:
726 typeName = "GL_SAMPLER_EXTERNAL_OES";
727 break;
728 case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT:
729 typeName = "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT";
730 break;
731 default:
732 typeName = "UNKNOWN";
733 break;
734 }
735
736 printf("%s %u : name=%s, mappedName=%s, type=%s, arraySizes=", prefix.c_str(),
737 static_cast<unsigned int>(index), var.name.c_str(), var.mappedName.c_str(),
738 typeName.c_str());
739 for (unsigned int arraySize : var.arraySizes)
740 {
741 printf("%u ", arraySize);
742 }
743 printf("\n");
744 if (var.fields.size())
745 {
746 std::string structPrefix;
747 for (size_t i = 0; i < prefix.size(); ++i)
748 structPrefix += ' ';
749 printf("%s struct %s\n", structPrefix.c_str(), var.structOrBlockName.c_str());
750 structPrefix += " field";
751 for (size_t i = 0; i < var.fields.size(); ++i)
752 PrintVariable(structPrefix, i, var.fields[i]);
753 }
754 }
755
PrintActiveVariables(ShHandle compiler)756 static void PrintActiveVariables(ShHandle compiler)
757 {
758 const std::vector<sh::ShaderVariable> *uniforms = sh::GetUniforms(compiler);
759 const std::vector<sh::ShaderVariable> *inputVaryings = sh::GetInputVaryings(compiler);
760 const std::vector<sh::ShaderVariable> *outputVaryings = sh::GetOutputVaryings(compiler);
761 const std::vector<sh::ShaderVariable> *attributes = sh::GetAttributes(compiler);
762 const std::vector<sh::ShaderVariable> *outputs = sh::GetOutputVariables(compiler);
763 for (size_t varCategory = 0; varCategory < 5; ++varCategory)
764 {
765 size_t numVars = 0;
766 std::string varCategoryName;
767 if (varCategory == 0)
768 {
769 numVars = uniforms->size();
770 varCategoryName = "uniform";
771 }
772 else if (varCategory == 1)
773 {
774 numVars = inputVaryings->size();
775 varCategoryName = "input varying";
776 }
777 else if (varCategory == 2)
778 {
779 numVars = outputVaryings->size();
780 varCategoryName = "output varying";
781 }
782 else if (varCategory == 3)
783 {
784 numVars = attributes->size();
785 varCategoryName = "attribute";
786 }
787 else
788 {
789 numVars = outputs->size();
790 varCategoryName = "output";
791 }
792
793 for (size_t i = 0; i < numVars; ++i)
794 {
795 const sh::ShaderVariable *var;
796 if (varCategory == 0)
797 var = &((*uniforms)[i]);
798 else if (varCategory == 1)
799 var = &((*inputVaryings)[i]);
800 else if (varCategory == 2)
801 var = &((*outputVaryings)[i]);
802 else if (varCategory == 3)
803 var = &((*attributes)[i]);
804 else
805 var = &((*outputs)[i]);
806
807 PrintVariable(varCategoryName, i, *var);
808 }
809 printf("\n");
810 }
811 }
812
ReadShaderSource(const char * fileName,ShaderSource & source)813 static bool ReadShaderSource(const char *fileName, ShaderSource &source)
814 {
815 FILE *in = fopen(fileName, "rb");
816 if (!in)
817 {
818 printf("Error: unable to open input file: %s\n", fileName);
819 return false;
820 }
821
822 // Obtain file size.
823 fseek(in, 0, SEEK_END);
824 size_t count = ftell(in);
825 rewind(in);
826
827 int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS);
828 source.reserve(NUM_SOURCE_STRINGS);
829 // Notice the usage of do-while instead of a while loop here.
830 // It is there to handle empty files in which case a single empty
831 // string is added to vector.
832 do
833 {
834 char *data = new char[len + 1];
835 size_t nread = fread(data, 1, len, in);
836 data[nread] = '\0';
837 source.push_back(data);
838
839 count -= nread;
840 } while (count > 0);
841
842 fclose(in);
843 return true;
844 }
845
FreeShaderSource(ShaderSource & source)846 static void FreeShaderSource(ShaderSource &source)
847 {
848 for (ShaderSource::size_type i = 0; i < source.size(); ++i)
849 {
850 delete[] source[i];
851 }
852 source.clear();
853 }
854
ParseGLSLOutputVersion(const std::string & num,ShShaderOutput * outResult)855 static bool ParseGLSLOutputVersion(const std::string &num, ShShaderOutput *outResult)
856 {
857 if (num.length() == 0)
858 {
859 *outResult = SH_GLSL_COMPATIBILITY_OUTPUT;
860 return true;
861 }
862 std::istringstream input(num);
863 int value;
864 if (!(input >> value && input.eof()))
865 {
866 return false;
867 }
868
869 switch (value)
870 {
871 case 130:
872 *outResult = SH_GLSL_130_OUTPUT;
873 return true;
874 case 140:
875 *outResult = SH_GLSL_140_OUTPUT;
876 return true;
877 case 150:
878 *outResult = SH_GLSL_150_CORE_OUTPUT;
879 return true;
880 case 330:
881 *outResult = SH_GLSL_330_CORE_OUTPUT;
882 return true;
883 case 400:
884 *outResult = SH_GLSL_400_CORE_OUTPUT;
885 return true;
886 case 410:
887 *outResult = SH_GLSL_410_CORE_OUTPUT;
888 return true;
889 case 420:
890 *outResult = SH_GLSL_420_CORE_OUTPUT;
891 return true;
892 case 430:
893 *outResult = SH_GLSL_430_CORE_OUTPUT;
894 return true;
895 case 440:
896 *outResult = SH_GLSL_440_CORE_OUTPUT;
897 return true;
898 case 450:
899 *outResult = SH_GLSL_450_CORE_OUTPUT;
900 return true;
901 default:
902 break;
903 }
904 return false;
905 }
906
ParseIntValue(const std::string & num,int emptyDefault,int * outValue)907 static bool ParseIntValue(const std::string &num, int emptyDefault, int *outValue)
908 {
909 if (num.length() == 0)
910 {
911 *outValue = emptyDefault;
912 return true;
913 }
914
915 std::istringstream input(num);
916 int value;
917 if (!(input >> value && input.eof()))
918 {
919 return false;
920 }
921 *outValue = value;
922 return true;
923 }
924
PrintSpirv(const sh::BinaryBlob & blob)925 static void PrintSpirv(const sh::BinaryBlob &blob)
926 {
927 #if defined(ANGLE_ENABLE_VULKAN)
928 spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_1);
929
930 std::string readableSpirv;
931 spirvTools.Disassemble(blob, &readableSpirv, 0);
932
933 puts(readableSpirv.c_str());
934 #endif
935 }
936