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