• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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