Edit

kc3-lang/angle/src/compiler/ShaderLang.cpp

Branch :

  • Show log

    Commit

  • Author : daniel@transgaming.com
    Date : 2012-11-28 19:42:57
    Hash : c23f4611
    Message : Interface design for user-defined name hashing. 1) We use BuiltInResources to pass the hash function to ANGLE, deciding whether we applies hash function or not. 2) We use 64 bits hashing function, because 64 bits is 16 bytes using hex representation, plus the "webgl_" prefix, we can keep the names under 128 (WebGL allows 5 levels of nesting in structures). If chooseing 128 bits, we will go beyond 128 characters, and some drivers can't handle that safely. ANGLEBUG=315 Review URL: https://codereview.appspot.com/6822077 git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1466 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/ShaderLang.cpp
  • //
    // Copyright (c) 2002-2011 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.
    //
    
    //
    // Implement the top-level of interface to the compiler,
    // as defined in ShaderLang.h
    //
    
    #include "GLSLANG/ShaderLang.h"
    
    #include "compiler/InitializeDll.h"
    #include "compiler/preprocessor/length_limits.h"
    #include "compiler/ShHandle.h"
    
    //
    // This is the platform independent interface between an OGL driver
    // and the shading language compiler.
    //
    
    static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
                                                      int expectedValue)
    {
        int activeUniformLimit = 0;
        ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
        int activeAttribLimit = 0;
        ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
        return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
    }
    
    static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue)
    {
        int mappedNameMaxLength = 0;
        ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
        return (expectedValue == mappedNameMaxLength);
    }
    
    static void getVariableInfo(ShShaderInfo varType,
                                const ShHandle handle,
                                int index,
                                int* length,
                                int* size,
                                ShDataType* type,
                                char* name,
                                char* mappedName)
    {
        if (!handle || !size || !type || !name)
            return;
        ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
               (varType == SH_ACTIVE_UNIFORMS));
    
        TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
        TCompiler* compiler = base->getAsCompiler();
        if (compiler == 0)
            return;
    
        const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
            compiler->getAttribs() : compiler->getUniforms();
        if (index < 0 || index >= static_cast<int>(varList.size()))
            return;
    
        const TVariableInfo& varInfo = varList[index];
        if (length) *length = varInfo.name.size();
        *size = varInfo.size;
        *type = varInfo.type;
    
        // This size must match that queried by
        // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
        // in ShGetInfo, below.
        int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
        ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
        strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
        name[activeUniformAndAttribLength - 1] = 0;
        if (mappedName) {
            // This size must match that queried by
            // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
            int maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
            ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
            strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
            mappedName[maxMappedNameLength - 1] = 0;
        }
    }
    
    //
    // Driver must call this first, once, before doing any other
    // compiler operations.
    //
    int ShInitialize()
    {
        if (!InitProcess())
            return 0;
    
        return 1;
    }
    
    //
    // Cleanup symbol tables
    //
    int ShFinalize()
    {
        if (!DetachProcess())
            return 0;
    
        return 1;
    }
    
    //
    // Initialize built-in resources with minimum expected values.
    //
    void ShInitBuiltInResources(ShBuiltInResources* resources)
    {
        // Constants.
        resources->MaxVertexAttribs = 8;
        resources->MaxVertexUniformVectors = 128;
        resources->MaxVaryingVectors = 8;
        resources->MaxVertexTextureImageUnits = 0;
        resources->MaxCombinedTextureImageUnits = 8;
        resources->MaxTextureImageUnits = 8;
        resources->MaxFragmentUniformVectors = 16;
        resources->MaxDrawBuffers = 1;
    
        // Extensions.
        resources->OES_standard_derivatives = 0;
        resources->OES_EGL_image_external = 0;
        resources->ARB_texture_rectangle = 0;
    
        // Disable name hashing by default.
        resources->HashFunction = NULL;
    }
    
    //
    // Driver calls these to create and destroy compiler objects.
    //
    ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
                                 ShShaderOutput output,
                                 const ShBuiltInResources* resources)
    {
        if (!InitThread())
            return 0;
    
        TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
        TCompiler* compiler = base->getAsCompiler();
        if (compiler == 0)
            return 0;
    
        // Generate built-in symbol table.
        if (!compiler->Init(*resources)) {
            ShDestruct(base);
            return 0;
        }
    
        return reinterpret_cast<void*>(base);
    }
    
    void ShDestruct(ShHandle handle)
    {
        if (handle == 0)
            return;
    
        TShHandleBase* base = static_cast<TShHandleBase*>(handle);
    
        if (base->getAsCompiler())
            DeleteCompiler(base->getAsCompiler());
    }
    
    //
    // Do an actual compile on the given strings.  The result is left 
    // in the given compile object.
    //
    // Return:  The return value of ShCompile is really boolean, indicating
    // success or failure.
    //
    int ShCompile(
        const ShHandle handle,
        const char* const shaderStrings[],
        const int numStrings,
        int compileOptions)
    {
        if (!InitThread())
            return 0;
    
        if (handle == 0)
            return 0;
    
        TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
        TCompiler* compiler = base->getAsCompiler();
        if (compiler == 0)
            return 0;
    
        bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
        return success ? 1 : 0;
    }
    
    void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
    {
        if (!handle || !params)
            return;
    
        TShHandleBase* base = static_cast<TShHandleBase*>(handle);
        TCompiler* compiler = base->getAsCompiler();
        if (!compiler) return;
    
        switch(pname)
        {
        case SH_INFO_LOG_LENGTH:
            *params = compiler->getInfoSink().info.size() + 1;
            break;
        case SH_OBJECT_CODE_LENGTH:
            *params = compiler->getInfoSink().obj.size() + 1;
            break;
        case SH_ACTIVE_UNIFORMS:
            *params = compiler->getUniforms().size();
            break;
        case SH_ACTIVE_UNIFORM_MAX_LENGTH:
            *params = 1 +  MAX_SYMBOL_NAME_LEN;
            break;
        case SH_ACTIVE_ATTRIBUTES:
            *params = compiler->getAttribs().size();
            break;
        case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
            *params = 1 + MAX_SYMBOL_NAME_LEN;
            break;
        case SH_MAPPED_NAME_MAX_LENGTH:
            // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
            // handle array and struct dereferences.
            *params = 1 + MAX_SYMBOL_NAME_LEN;
            break;
        case SH_NAME_MAX_LENGTH:
            *params = 1 + MAX_SYMBOL_NAME_LEN;
            break;
        case SH_HASHED_NAME_MAX_LENGTH:
            if (compiler->getHashFunction() == NULL) {
                *params = 0;
            } else {
                // 64 bits hashing output requires 16 bytes for hex 
                // representation.
                const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
                *params = 16 + sizeof(HashedNamePrefix);
            }
            break;
        case SH_HASHED_NAMES_COUNT:
            *params = compiler->getNameMap().size();
            break;
        default: UNREACHABLE();
        }
    }
    
    //
    // Return any compiler log of messages for the application.
    //
    void ShGetInfoLog(const ShHandle handle, char* infoLog)
    {
        if (!handle || !infoLog)
            return;
    
        TShHandleBase* base = static_cast<TShHandleBase*>(handle);
        TCompiler* compiler = base->getAsCompiler();
        if (!compiler) return;
    
        TInfoSink& infoSink = compiler->getInfoSink();
        strcpy(infoLog, infoSink.info.c_str());
    }
    
    //
    // Return any object code.
    //
    void ShGetObjectCode(const ShHandle handle, char* objCode)
    {
        if (!handle || !objCode)
            return;
    
        TShHandleBase* base = static_cast<TShHandleBase*>(handle);
        TCompiler* compiler = base->getAsCompiler();
        if (!compiler) return;
    
        TInfoSink& infoSink = compiler->getInfoSink();
        strcpy(objCode, infoSink.obj.c_str());
    }
    
    void ShGetActiveAttrib(const ShHandle handle,
                           int index,
                           int* length,
                           int* size,
                           ShDataType* type,
                           char* name,
                           char* mappedName)
    {
        getVariableInfo(SH_ACTIVE_ATTRIBUTES,
                        handle, index, length, size, type, name, mappedName);
    }
    
    void ShGetActiveUniform(const ShHandle handle,
                            int index,
                            int* length,
                            int* size,
                            ShDataType* type,
                            char* name,
                            char* mappedName)
    {
        getVariableInfo(SH_ACTIVE_UNIFORMS,
                        handle, index, length, size, type, name, mappedName);
    }
    
    void ShGetNameHashingEntry(const ShHandle handle,
                               int index,
                               char* name,
                               char* hashedName)
    {
        if (!handle || !name || !hashedName || index < 0)
            return;
    
        TShHandleBase* base = static_cast<TShHandleBase*>(handle);
        TCompiler* compiler = base->getAsCompiler();
        if (!compiler) return;
    
        const NameMap& nameMap = compiler->getNameMap();
        if (index >= static_cast<int>(nameMap.size()))
            return;
    
        NameMap::const_iterator it = nameMap.begin();
        for (int i = 0; i < index; ++i)
            ++it;
    
        size_t len = it->first.length() + 1;
        int max_len = 0;
        ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
        if (static_cast<int>(len) > max_len) {
            ASSERT(false);
            len = max_len;
        }
        strncpy(name, it->first.c_str(), len);
        // To be on the safe side in case the source is longer than expected.
        name[len] = '\0';
    
        len = it->second.length() + 1;
        max_len = 0;
        ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
        if (static_cast<int>(len) > max_len) {
            ASSERT(false);
            len = max_len;
        }
        strncpy(hashedName, it->second.c_str(), len);
        // To be on the safe side in case the source is longer than expected.
        hashedName[len] = '\0';
    }