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