176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
28204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org// Use of this source code is governed by a BSD-style license that can be
476b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org// found in the LICENSE file.
576b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
676b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org#include "GLSLANG/ShaderLang.h"
876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
9ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org#include <assert.h>
1076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org#include <math.h>
1176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org#include <stdio.h>
1276b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org#include <stdlib.h>
1376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org#include <string.h>
14d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org#include <vector>
1576b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
1676b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
1776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org// Return codes from main.
1876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
1976b820852b116d79187e5af5457a45065f656bdaalokp@chromium.orgenum TFailCode {
2076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    ESuccess = 0,
2176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    EFailUsage,
2276b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    EFailCompile,
2376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    EFailCompilerCreate,
2476b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org};
2576b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
264888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.orgstatic void usage();
27d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgstatic ShShaderType FindShaderType(const char* fileName);
28d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgstatic bool CompileFile(char* fileName, ShHandle compiler, int compileOptions);
294a02078ac0e55041b345c68aea05790103aa1f96alokp@chromium.orgstatic void LogMsg(const char* msg, const char* name, const int num, const char* logName);
30d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.comstatic void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType, bool mapLongVariableNames);
31e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org
32d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org// If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is
33d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org// broken into that many chunks.
34d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgconst unsigned int NUM_SOURCE_STRINGS = 2;
35d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgtypedef std::vector<char*> ShaderSource;
36d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgstatic bool ReadShaderSource(const char* fileName, ShaderSource& source);
37d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgstatic void FreeShaderSource(ShaderSource& source);
3876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
3976b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
4076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org// Set up the per compile resources
4176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
424888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.orgvoid GenerateResources(ShBuiltInResources* resources)
4376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org{
444888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org    ShInitBuiltInResources(resources);
4594a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org
4694a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxVertexAttribs = 8;
4794a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxVertexUniformVectors = 128;
4894a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxVaryingVectors = 8;
4994a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxVertexTextureImageUnits = 0;
5094a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxCombinedTextureImageUnits = 8;
5194a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxTextureImageUnits = 8;
5294a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxFragmentUniformVectors = 16;
5394a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->MaxDrawBuffers = 1;
5494a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org
5594a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    resources->OES_standard_derivatives = 0;
5609c323a40ad0de489eee946bfe171d337616e09czmo@google.com    resources->OES_EGL_image_external = 0;
5776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org}
5876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
59c54bf507cdd389d91fb3379e463b1e41b248fe62alokp@chromium.orgint main(int argc, char* argv[])
6076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org{
61e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    TFailCode failCode = ESuccess;
62e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org
637beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org    int compileOptions = 0;
64e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    int numCompiles = 0;
65e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    ShHandle vertexCompiler = 0;
66e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    ShHandle fragmentCompiler = 0;
677beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org    char* buffer = 0;
6806e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com    size_t bufferLen = 0;
69ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    int numAttribs = 0, numUniforms = 0;
7066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com    ShShaderSpec spec = SH_GLES2_SPEC;
715601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com    ShShaderOutput output = SH_ESSL_OUTPUT;
7276b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
7376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    ShInitialize();
7476b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
754888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org    ShBuiltInResources resources;
7694a86ad8f1ace86e9dc08088cd2e85d0b9f842f0alokp@chromium.org    GenerateResources(&resources);
77e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org
7876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    argc--;
79774d70630a690b2449afdccfb29612393c65f212alokp@chromium.org    argv++;
80e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++) {
81fe2aff1094d9d3129b5d919b0da983e1330ce040kbr@chromium.org        if (argv[0][0] == '-') {
8276b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org            switch (argv[0][1]) {
834888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org            case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break;
84d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com            case 'm': compileOptions |= SH_MAP_LONG_VARIABLE_NAMES; break;
854888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org            case 'o': compileOptions |= SH_OBJECT_CODE; break;
864888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org            case 'u': compileOptions |= SH_ATTRIBUTES_UNIFORMS; break;
870c6bb7a653f52baa3dab4492a3599ddcacf076edzmo@google.com            case 'l': compileOptions |= SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; break;
8832e97315e2a55557ad7c372239e0823a81243221zmo@google.com            case 'e': compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; break;
8966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com            case 'd': compileOptions |= SH_DEPENDENCY_GRAPH; break;
9066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com            case 't': compileOptions |= SH_TIMING_RESTRICTIONS; break;
9166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com            case 's':
9266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                if (argv[0][2] == '=') {
9366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                    switch (argv[0][3]) {
9466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                        case 'e': spec = SH_GLES2_SPEC; break;
9566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                        case 'w': spec = SH_WEBGL_SPEC; break;
96430f5e0c75ade69935befb55d2592635f70255cemaxvujovic@gmail.com                        case 'c': spec = SH_CSS_SHADERS_SPEC; break;
9766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                        default: failCode = EFailUsage;
9866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                    }
99430f5e0c75ade69935befb55d2592635f70255cemaxvujovic@gmail.com                } else {
100430f5e0c75ade69935befb55d2592635f70255cemaxvujovic@gmail.com                    failCode = EFailUsage;
10166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                }
10266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                break;
1035601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com            case 'b':
1045601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                if (argv[0][2] == '=') {
1055601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    switch (argv[0][3]) {
1065601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    case 'e': output = SH_ESSL_OUTPUT; break;
1075601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    case 'g': output = SH_GLSL_OUTPUT; break;
1088204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                    case 'h':
1098204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        if (argv[0][4] == '1' && argv[0][5] == '1')
1108204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        {
1118204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                            output = SH_HLSL11_OUTPUT;
1128204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        }
1138204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        else
1148204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        {
1158204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                            output = SH_HLSL9_OUTPUT;
1168204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        }
1178204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com                        break;
1185601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    default: failCode = EFailUsage;
1195601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    }
1205601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                } else {
1215601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    failCode = EFailUsage;
1225601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                }
1235601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                break;
124f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com            case 'x':
125f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                if (argv[0][2] == '=') {
126f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                    switch (argv[0][3]) {
127f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                    case 'i': resources.OES_EGL_image_external = 1; break;
128f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                    case 'd': resources.OES_standard_derivatives = 1; break;
1298b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com                    case 'r': resources.ARB_texture_rectangle = 1; break;
130f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                    default: failCode = EFailUsage;
131f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                    }
132f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                } else {
133f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                    failCode = EFailUsage;
134f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                }
135f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com                break;
136e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            default: failCode = EFailUsage;
13776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org            }
13876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org        } else {
139e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            ShHandle compiler = 0;
1404888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org            switch (FindShaderType(argv[0])) {
1414888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org            case SH_VERTEX_SHADER:
142e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                if (vertexCompiler == 0)
1435601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    vertexCompiler = ShConstructCompiler(
14466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                        SH_VERTEX_SHADER, spec, output, &resources);
145e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                compiler = vertexCompiler;
146e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                break;
1474888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org            case SH_FRAGMENT_SHADER:
148e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                if (fragmentCompiler == 0)
1495601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com                    fragmentCompiler = ShConstructCompiler(
15066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com                        SH_FRAGMENT_SHADER, spec, output, &resources);
151e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                compiler = fragmentCompiler;
152e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                break;
153e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            default: break;
154e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            }
155e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            if (compiler) {
1567beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org              bool compiled = CompileFile(argv[0], compiler, compileOptions);
157e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org
158e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org              LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG");
1597beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org              ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen);
1607beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org              buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
1617beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org              ShGetInfoLog(compiler, buffer);
1627beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org              puts(buffer);
163e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org              LogMsg("END", "COMPILER", numCompiles, "INFO LOG");
164ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org              printf("\n\n");
165e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org
1664888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org              if (compiled && (compileOptions & SH_OBJECT_CODE)) {
167e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                  LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE");
1687beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org                  ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &bufferLen);
1697beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org                  buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
1707beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org                  ShGetObjectCode(compiler, buffer);
1717beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org                  puts(buffer);
172e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                  LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");
173ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  printf("\n\n");
174ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org              }
1754888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org              if (compiled && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
176ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
1777f02008ad8eb40ae76516301ef3327101ad693c1daniel@transgaming.com                  PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0);
178ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  LogMsg("END", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
179ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  printf("\n\n");
180ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org
181ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
1827f02008ad8eb40ae76516301ef3327101ad693c1daniel@transgaming.com                  PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0);
183ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  LogMsg("END", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
184ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                  printf("\n\n");
185e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org              }
186e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org              if (!compiled)
187e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                  failCode = EFailCompile;
188e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org              ++numCompiles;
189e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            } else {
190e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org                failCode = EFailCompilerCreate;
191e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org            }
19276b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org        }
19376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    }
19476b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
195e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    if ((vertexCompiler == 0) && (fragmentCompiler == 0))
196e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org        failCode = EFailUsage;
197e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    if (failCode == EFailUsage)
19876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org        usage();
19976b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
200e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    if (vertexCompiler)
201e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org        ShDestruct(vertexCompiler);
202e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    if (fragmentCompiler)
203e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org        ShDestruct(fragmentCompiler);
2047beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org    if (buffer)
2057beea4084f47ae019b5a93b03a5136c9265dc444alokp@chromium.org        free(buffer);
206774d70630a690b2449afdccfb29612393c65f212alokp@chromium.org    ShFinalize();
207e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org
208e4249f0217bed043d645b6e01ae7d26f7c3e0093alokp@chromium.org    return failCode;
20976b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org}
21076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
21176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
212d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org//   print usage to stdout
213d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org//
214d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgvoid usage()
215d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org{
216f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com    printf("Usage: translate [-i -m -o -u -l -e -b=e -b=g -b=h -x=i -x=d] file1 file2 ...\n"
2175601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "Where: filename : filename ending in .frag or .vert\n"
2185601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "       -i       : print intermediate tree\n"
2195601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "       -m       : map long variable names\n"
2205601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "       -o       : print translated code\n"
2215601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "       -u       : print active attribs and uniforms\n"
2220c6bb7a653f52baa3dab4492a3599ddcacf076edzmo@google.com        "       -l       : unroll for-loops with integer indices\n"
22332e97315e2a55557ad7c372239e0823a81243221zmo@google.com        "       -e       : emulate certain built-in functions (workaround for driver bugs)\n"
22466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com        "       -t       : enforce experimental timing restrictions\n"
22566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com        "       -d       : print dependency graph used to enforce timing restrictions\n"
22666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com        "       -s=e     : use GLES2 spec (this is by default)\n"
22766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com        "       -s=w     : use WebGL spec\n"
228430f5e0c75ade69935befb55d2592635f70255cemaxvujovic@gmail.com        "       -s=c     : use CSS Shaders spec\n"
2295601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "       -b=e     : output GLSL ES code (this is by default)\n"
2305601ea0d66442518d4745bb02b7619485b9d305bzmo@google.com        "       -b=g     : output GLSL code\n"
2318204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com        "       -b=h9    : output HLSL9 code\n"
2328204334b61162ce1b575e179265b90fbe8d23ef1shannon.woods@transgaming.com        "       -b=h11   : output HLSL11 code\n"
233f54509100ee8587a1338443a26209e2b7e436d76zmo@google.com        "       -x=i     : enable GL_OES_EGL_image_external\n"
2348b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com        "       -x=d     : enable GL_OES_EGL_standard_derivatives\n"
2358b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com        "       -x=r     : enable ARB_texture_rectangle\n");
236d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org}
237d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
238d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org//
2394888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org//   Deduce the shader type from the filename.  Files must end in one of the
24076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//   following extensions:
24176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
2424888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org//   .frag*    = fragment shader
2434888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org//   .vert*    = vertex shader
24476b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
245d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgShShaderType FindShaderType(const char* fileName)
24676b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org{
247d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    assert(fileName);
24876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
249d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    const char* ext = strrchr(fileName, '.');
25076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
25176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    if (ext && strcmp(ext, ".sl") == 0)
252d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        for (; ext > fileName && ext[0] != '.'; ext--);
25376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
254a1d8059d676046ff9a35e15341866f1e93944132apatrick@chromium.org    ext = strrchr(fileName, '.');
255a1d8059d676046ff9a35e15341866f1e93944132apatrick@chromium.org    if (ext) {
2564888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org        if (strncmp(ext, ".frag", 4) == 0) return SH_FRAGMENT_SHADER;
2574888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org        if (strncmp(ext, ".vert", 4) == 0) return SH_VERTEX_SHADER;
25876b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    }
25976b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
2604888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org    return SH_FRAGMENT_SHADER;
26176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org}
26276b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
26376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
26476b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//   Read a file's data into a string, and compile it using ShCompile
26576b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org//
266d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgbool CompileFile(char* fileName, ShHandle compiler, int compileOptions)
26776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org{
268d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    ShaderSource source;
269d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    if (!ReadShaderSource(fileName, source))
27076b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org        return false;
27176b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
272d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    int ret = ShCompile(compiler, &source[0], source.size(), compileOptions);
27376b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
274d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    FreeShaderSource(source);
27576b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org    return ret ? true : false;
27676b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org}
27776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
2784a02078ac0e55041b345c68aea05790103aa1f96alokp@chromium.orgvoid LogMsg(const char* msg, const char* name, const int num, const char* logName)
27976b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org{
280ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    printf("#### %s %s %d %s ####\n", msg, name, num, logName);
281ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org}
282ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org
283d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.comvoid PrintActiveVariables(ShHandle compiler, ShShaderInfo varType, bool mapLongVariableNames)
284ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org{
28506e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com    size_t nameSize = 0;
286ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    switch (varType) {
287ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        case SH_ACTIVE_ATTRIBUTES:
288ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &nameSize);
289ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            break;
290ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        case SH_ACTIVE_UNIFORMS:
291ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &nameSize);
292ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            break;
293ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        default: assert(0);
294ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    }
295ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    if (nameSize <= 1) return;
296d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    char* name = new char[nameSize];
297ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org
298d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com    char* mappedName = NULL;
299d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com    if (mapLongVariableNames) {
30006e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com        size_t mappedNameSize = 0;
301d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com        ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameSize);
302d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com        mappedName = new char[mappedNameSize];
303d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com    }
304d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com
30506e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com    size_t activeVars = 0;
30606e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com    int size = 0;
3074888ceb6681c3668d3afcbdafdbe2b7efdaa3d04alokp@chromium.org    ShDataType type = SH_NONE;
3084a02078ac0e55041b345c68aea05790103aa1f96alokp@chromium.org    const char* typeName = NULL;
309ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    ShGetInfo(compiler, varType, &activeVars);
31006e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com    for (size_t i = 0; i < activeVars; ++i) {
311ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        switch (varType) {
312ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_ACTIVE_ATTRIBUTES:
31306e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com                ShGetActiveAttrib(compiler, static_cast<int>(i), NULL, &size, &type, name, mappedName);
314ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                break;
315ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_ACTIVE_UNIFORMS:
31606e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com                ShGetActiveUniform(compiler, static_cast<int>(i), NULL, &size, &type, name, mappedName);
317ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org                break;
318ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            default: assert(0);
319ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        }
320ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        switch (type) {
321ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT: typeName = "GL_FLOAT"; break;
322ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT_VEC2: typeName = "GL_FLOAT_VEC2"; break;
323ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT_VEC3: typeName = "GL_FLOAT_VEC3"; break;
324ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break;
325ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_INT: typeName = "GL_INT"; break;
326ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_INT_VEC2: typeName = "GL_INT_VEC2"; break;
327ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_INT_VEC3: typeName = "GL_INT_VEC3"; break;
328ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_INT_VEC4: typeName = "GL_INT_VEC4"; break;
329ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_BOOL: typeName = "GL_BOOL"; break;
330ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_BOOL_VEC2: typeName = "GL_BOOL_VEC2"; break;
331ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_BOOL_VEC3: typeName = "GL_BOOL_VEC3"; break;
332ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_BOOL_VEC4: typeName = "GL_BOOL_VEC4"; break;
333ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT_MAT2: typeName = "GL_FLOAT_MAT2"; break;
334ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT_MAT3: typeName = "GL_FLOAT_MAT3"; break;
335ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break;
336ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break;
337ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            case SH_SAMPLER_CUBE: typeName = "GL_SAMPLER_CUBE"; break;
3386575602ea68a323f4255c5c968f94c6830ae68a0apatrick@chromium.org            case SH_SAMPLER_EXTERNAL_OES: typeName = "GL_SAMPLER_EXTERNAL_OES"; break;
339ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org            default: assert(0);
340ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org        }
34106e0df0b7ad3adb3201f74803371dbf807c656a4shannon.woods@transgaming.com        printf("%u: name:%s type:%s size:%d", i, name, typeName, size);
342d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com        if (mapLongVariableNames)
343d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com            printf(" mapped name:%s", mappedName);
344d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com        printf("\n");
345ee76f6af4554615109916db541cd1e613d553214alokp@chromium.org    }
346d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    delete [] name;
347d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com    if (mappedName)
348d7468be16fd653a41ed264bfb4d801e769fa0c15zmo@google.com        delete [] mappedName;
349d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org}
350d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
351d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgstatic bool ReadShaderSource(const char* fileName, ShaderSource& source) {
352d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    FILE* in = fopen(fileName, "rb");
353d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    if (!in) {
354d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        printf("Error: unable to open input file: %s\n", fileName);
355d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        return false;
356d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    }
357d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
358d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    // Obtain file size.
359d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    fseek(in, 0, SEEK_END);
360d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    int count = ftell(in);
361d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    rewind(in);
362d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
363d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS);
364d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    source.reserve(NUM_SOURCE_STRINGS);
365d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    // Notice the usage of do-while instead of a while loop here.
366d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    // It is there to handle empty files in which case a single empty
367d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    // string is added to vector.
368d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    do {
369d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        char* data = new char[len + 1];
370d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        int nread = fread(data, 1, len, in);
371d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        data[nread] = '\0';
372d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        source.push_back(data);
373d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
374d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        count -= nread;
375d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    } while (count > 0);
376d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
377d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    fclose(in);
378d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    return true;
379d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org}
380d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org
381d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.orgstatic void FreeShaderSource(ShaderSource& source) {
382d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    for (ShaderSource::size_type i = 0; i < source.size(); ++i) {
383d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org        delete [] source[i];
384d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    }
385d1e10e602e7e659adca6f8167f4d24c210ebbe84alokp@chromium.org    source.clear();
38676b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org}
38776b820852b116d79187e5af5457a45065f656bdaalokp@chromium.org
388