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