Edit

kc3-lang/angle/samples/translator

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2014-07-02 15:31:19
    Hash : 183bde55
    Message : Return shader variable information using GLenum values. Instead of duplicating GL header define values, explictly return GLenum for variable queries in the shader inspection API. This reduces the duplicate defines in the shader compiler header. BUG=angle:466 Change-Id: Iddaaff597b188251fa2e546f352bf77ab3ac43bc Reviewed-on: https://chromium-review.googlesource.com/205860 Tested-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org> Reviewed-by: Nicolas Capens <capn@chromium.org>

  • translator.cpp
  • //
    // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "GLSLANG/ShaderLang.h"
    
    #include <assert.h>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <vector>
    #include "angle_gl.h"
    
    //
    // Return codes from main.
    //
    enum TFailCode {
        ESuccess = 0,
        EFailUsage,
        EFailCompile,
        EFailCompilerCreate,
    };
    
    static void usage();
    static sh::GLenum FindShaderType(const char* fileName);
    static bool CompileFile(char* fileName, ShHandle compiler, int compileOptions);
    static void LogMsg(const char* msg, const char* name, const int num, const char* logName);
    static void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType);
    
    // If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is
    // broken into that many chunks.
    const unsigned int NUM_SOURCE_STRINGS = 2;
    typedef std::vector<char*> ShaderSource;
    static bool ReadShaderSource(const char* fileName, ShaderSource& source);
    static void FreeShaderSource(ShaderSource& source);
    
    //
    // Set up the per compile resources
    //
    void GenerateResources(ShBuiltInResources* resources)
    {
        ShInitBuiltInResources(resources);
    
        resources->MaxVertexAttribs = 8;
        resources->MaxVertexUniformVectors = 128;
        resources->MaxVaryingVectors = 8;
        resources->MaxVertexTextureImageUnits = 0;
        resources->MaxCombinedTextureImageUnits = 8;
        resources->MaxTextureImageUnits = 8;
        resources->MaxFragmentUniformVectors = 16;
        resources->MaxDrawBuffers = 1;
    
        resources->OES_standard_derivatives = 0;
        resources->OES_EGL_image_external = 0;
    }
    
    int main(int argc, char* argv[])
    {
        TFailCode failCode = ESuccess;
    
        int compileOptions = 0;
        int numCompiles = 0;
        ShHandle vertexCompiler = 0;
        ShHandle fragmentCompiler = 0;
        char* buffer = 0;
        size_t bufferLen = 0;
        ShShaderSpec spec = SH_GLES2_SPEC;
        ShShaderOutput output = SH_ESSL_OUTPUT;
    
        ShInitialize();
    
        ShBuiltInResources resources;
        GenerateResources(&resources);
    
        argc--;
        argv++;
        for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++) {
            if (argv[0][0] == '-') {
                switch (argv[0][1]) {
                case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break;
                case 'o': compileOptions |= SH_OBJECT_CODE; break;
                case 'u': compileOptions |= SH_VARIABLES; break;
                case 'l': compileOptions |= SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; break;
                case 'e': compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; break;
                case 'd': compileOptions |= SH_DEPENDENCY_GRAPH; break;
                case 't': compileOptions |= SH_TIMING_RESTRICTIONS; break;
                case 's':
                    if (argv[0][2] == '=') {
                        switch (argv[0][3]) {
                            case 'e': spec = SH_GLES2_SPEC; break;
                            case 'w': spec = SH_WEBGL_SPEC; break;
                            case 'c': spec = SH_CSS_SHADERS_SPEC; break;
                            default: failCode = EFailUsage;
                        }                    
                    } else {
                        failCode = EFailUsage;
                    }
                    break;
                case 'b':
                    if (argv[0][2] == '=') {
                        switch (argv[0][3]) {
                        case 'e': output = SH_ESSL_OUTPUT; break;
                        case 'g': output = SH_GLSL_OUTPUT; break;
                        case 'h':
                            if (argv[0][4] == '1' && argv[0][5] == '1')
                            {
                                output = SH_HLSL11_OUTPUT;
                            }
                            else
                            {
                                output = SH_HLSL9_OUTPUT;
                            }
                            break;
                        default: failCode = EFailUsage;
                        }
                    } else {
                        failCode = EFailUsage;
                    }
                    break;
                case 'x':
                    if (argv[0][2] == '=') {
                        switch (argv[0][3]) {
                        case 'i': resources.OES_EGL_image_external = 1; break;
                        case 'd': resources.OES_standard_derivatives = 1; break;
                        case 'r': resources.ARB_texture_rectangle = 1; break;
                        case 'l': resources.EXT_shader_texture_lod = 1; break;
                        default: failCode = EFailUsage;
                        }
                    } else {
                        failCode = EFailUsage;
                    }
                    break;
                default: failCode = EFailUsage;
                }
            } else {
                ShHandle compiler = 0;
                switch (FindShaderType(argv[0])) {
                case GL_VERTEX_SHADER:
                    if (vertexCompiler == 0)
                        vertexCompiler = ShConstructCompiler(
                            GL_VERTEX_SHADER, spec, output, &resources);
                    compiler = vertexCompiler;
                    break;
                case GL_FRAGMENT_SHADER:
                    if (fragmentCompiler == 0)
                        fragmentCompiler = ShConstructCompiler(
                            GL_FRAGMENT_SHADER, spec, output, &resources);
                    compiler = fragmentCompiler;
                    break;
                default: break;
                }
                if (compiler) {
                  bool compiled = CompileFile(argv[0], compiler, compileOptions);
    
                  LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG");
                  ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen);
                  buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
                  ShGetInfoLog(compiler, buffer);
                  puts(buffer);
                  LogMsg("END", "COMPILER", numCompiles, "INFO LOG");
                  printf("\n\n");
    
                  if (compiled && (compileOptions & SH_OBJECT_CODE)) {
                      LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE");
                      ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &bufferLen);
                      buffer = (char*) realloc(buffer, bufferLen * sizeof(char));
                      ShGetObjectCode(compiler, buffer);
                      puts(buffer);
                      LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");
                      printf("\n\n");
                  }
                  if (compiled && (compileOptions & SH_VARIABLES)) {
                      LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
                      PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES);
                      LogMsg("END", "COMPILER", numCompiles, "ACTIVE ATTRIBS");
                      printf("\n\n");
    
                      LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
                      PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS);
                      LogMsg("END", "COMPILER", numCompiles, "ACTIVE UNIFORMS");
                      printf("\n\n");
                  }
                  if (!compiled)
                      failCode = EFailCompile;
                  ++numCompiles;
                } else {
                    failCode = EFailCompilerCreate;
                }
            }
        }
    
        if ((vertexCompiler == 0) && (fragmentCompiler == 0))
            failCode = EFailUsage;
        if (failCode == EFailUsage)
            usage();
    
        if (vertexCompiler)
            ShDestruct(vertexCompiler);
        if (fragmentCompiler)
            ShDestruct(fragmentCompiler);
        if (buffer)
            free(buffer);
        ShFinalize();
    
        return failCode;
    }
    
    //
    //   print usage to stdout
    //
    void usage()
    {
        printf("Usage: translate [-i -m -o -u -l -e -b=e -b=g -b=h -x=i -x=d] file1 file2 ...\n"
            "Where: filename : filename ending in .frag or .vert\n"
            "       -i       : print intermediate tree\n"
            "       -m       : map long variable names\n"
            "       -o       : print translated code\n"
            "       -u       : print active attribs and uniforms\n"
            "       -l       : unroll for-loops with integer indices\n"
            "       -e       : emulate certain built-in functions (workaround for driver bugs)\n"
            "       -t       : enforce experimental timing restrictions\n"
            "       -d       : print dependency graph used to enforce timing restrictions\n"
            "       -s=e     : use GLES2 spec (this is by default)\n"
            "       -s=w     : use WebGL spec\n"
            "       -s=c     : use CSS Shaders spec\n"
            "       -b=e     : output GLSL ES code (this is by default)\n"
            "       -b=g     : output GLSL code\n"
            "       -b=h9    : output HLSL9 code\n"
            "       -b=h11   : output HLSL11 code\n"
            "       -x=i     : enable GL_OES_EGL_image_external\n"
            "       -x=d     : enable GL_OES_EGL_standard_derivatives\n"
            "       -x=r     : enable ARB_texture_rectangle\n"
            "       -x=l     : enable EXT_shader_texture_lod\n");
    }
    
    //
    //   Deduce the shader type from the filename.  Files must end in one of the
    //   following extensions:
    //
    //   .frag*    = fragment shader
    //   .vert*    = vertex shader
    //
    sh::GLenum FindShaderType(const char* fileName)
    {
        assert(fileName);
    
        const char* ext = strrchr(fileName, '.');
    
        if (ext && strcmp(ext, ".sl") == 0)
            for (; ext > fileName && ext[0] != '.'; ext--);
    
        ext = strrchr(fileName, '.');
        if (ext) {
            if (strncmp(ext, ".frag", 4) == 0) return GL_FRAGMENT_SHADER;
            if (strncmp(ext, ".vert", 4) == 0) return GL_VERTEX_SHADER;
        }
    
        return GL_FRAGMENT_SHADER;
    }
    
    //
    //   Read a file's data into a string, and compile it using ShCompile
    //
    bool CompileFile(char* fileName, ShHandle compiler, int compileOptions)
    {
        ShaderSource source;
        if (!ReadShaderSource(fileName, source))
            return false;
    
        int ret = ShCompile(compiler, &source[0], source.size(), compileOptions);
    
        FreeShaderSource(source);
        return ret ? true : false;
    }
    
    void LogMsg(const char* msg, const char* name, const int num, const char* logName)
    {
        printf("#### %s %s %d %s ####\n", msg, name, num, logName);
    }
    
    void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType)
    {
        size_t nameSize = 0;
        switch (varType) {
            case SH_ACTIVE_ATTRIBUTES:
                ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &nameSize);
                break;
            case SH_ACTIVE_UNIFORMS:
                ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &nameSize);
                break;
            default: assert(0);
        }
        if (nameSize <= 1) return;
        char* name = new char[nameSize];
    
        size_t activeVars = 0;
        int size = 0;
        sh::GLenum type = GL_NONE;
        ShPrecisionType precision = SH_PRECISION_UNDEFINED;
        int staticUse = 0;
        const char* typeName = NULL;
        ShGetInfo(compiler, varType, &activeVars);
        for (size_t i = 0; i < activeVars; ++i) {
            switch (varType) {
                case SH_ACTIVE_ATTRIBUTES:
                    ShGetVariableInfo(compiler, SH_ACTIVE_ATTRIBUTES, static_cast<int>(i), NULL, &size, &type, &precision, &staticUse, name, NULL);
                    break;
                case SH_ACTIVE_UNIFORMS:
                    ShGetVariableInfo(compiler, SH_ACTIVE_UNIFORMS, static_cast<int>(i), NULL, &size, &type, &precision, &staticUse, name, NULL);
                    break;
                default: assert(0);
            }
            switch (type) {
                case GL_FLOAT: typeName = "GL_FLOAT"; break;
                case GL_FLOAT_VEC2: typeName = "GL_FLOAT_VEC2"; break;
                case GL_FLOAT_VEC3: typeName = "GL_FLOAT_VEC3"; break;
                case GL_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break;
                case GL_INT: typeName = "GL_INT"; break;
                case GL_INT_VEC2: typeName = "GL_INT_VEC2"; break;
                case GL_INT_VEC3: typeName = "GL_INT_VEC3"; break;
                case GL_INT_VEC4: typeName = "GL_INT_VEC4"; break;
                case GL_UNSIGNED_INT: typeName = "GL_UNSIGNED_INT"; break;
                case GL_UNSIGNED_INT_VEC2: typeName = "GL_UNSIGNED_INT_VEC2"; break;
                case GL_UNSIGNED_INT_VEC3: typeName = "GL_UNSIGNED_INT_VEC3"; break;
                case GL_UNSIGNED_INT_VEC4: typeName = "GL_UNSIGNED_INT_VEC4"; break;
                case GL_BOOL: typeName = "GL_BOOL"; break;
                case GL_BOOL_VEC2: typeName = "GL_BOOL_VEC2"; break;
                case GL_BOOL_VEC3: typeName = "GL_BOOL_VEC3"; break;
                case GL_BOOL_VEC4: typeName = "GL_BOOL_VEC4"; break;
                case GL_FLOAT_MAT2: typeName = "GL_FLOAT_MAT2"; break;
                case GL_FLOAT_MAT3: typeName = "GL_FLOAT_MAT3"; break;
                case GL_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break;
                case GL_FLOAT_MAT2x3: typeName = "GL_FLOAT_MAT2x3"; break;
                case GL_FLOAT_MAT3x2: typeName = "GL_FLOAT_MAT3x2"; break;
                case GL_FLOAT_MAT4x2: typeName = "GL_FLOAT_MAT4x2"; break;
                case GL_FLOAT_MAT2x4: typeName = "GL_FLOAT_MAT2x4"; break;
                case GL_FLOAT_MAT3x4: typeName = "GL_FLOAT_MAT3x4"; break;
                case GL_FLOAT_MAT4x3: typeName = "GL_FLOAT_MAT4x3"; break;
                case GL_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break;
                case GL_SAMPLER_CUBE: typeName = "GL_SAMPLER_CUBE"; break;
                case GL_SAMPLER_EXTERNAL_OES: typeName = "GL_SAMPLER_EXTERNAL_OES"; break;
                default: assert(0);
            }
            printf("%lu: name:%s type:%s size:%d\n", i, name, typeName, size);
        }
        delete [] name;
    }
    
    static bool ReadShaderSource(const char* fileName, ShaderSource& source) {
        FILE* in = fopen(fileName, "rb");
        if (!in) {
            printf("Error: unable to open input file: %s\n", fileName);
            return false;
        }
    
        // Obtain file size.
        fseek(in, 0, SEEK_END);
        size_t count = ftell(in);
        rewind(in);
    
        int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS);
        source.reserve(NUM_SOURCE_STRINGS);
        // Notice the usage of do-while instead of a while loop here.
        // It is there to handle empty files in which case a single empty
        // string is added to vector.
        do {
            char* data = new char[len + 1];
            size_t nread = fread(data, 1, len, in);
            data[nread] = '\0';
            source.push_back(data);
    
            count -= nread;
        } while (count > 0);
    
        fclose(in);
        return true;
    }
    
    static void FreeShaderSource(ShaderSource& source) {
        for (ShaderSource::size_type i = 0; i < source.size(); ++i) {
            delete [] source[i];
        }
        source.clear();
    }