Home | History | Annotate | Download | only in libGLESv2
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // Shader.cpp: Implements the gl::Shader class and its  derived classes
      9 // VertexShader and FragmentShader. Implements GL shader objects and related
     10 // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
     11 
     12 #include "libGLESv2/Shader.h"
     13 
     14 #include "GLSLANG/ShaderLang.h"
     15 #include "libGLESv2/utilities.h"
     16 #include "libGLESv2/renderer/Renderer.h"
     17 #include "libGLESv2/Constants.h"
     18 #include "libGLESv2/ResourceManager.h"
     19 
     20 namespace gl
     21 {
     22 void *Shader::mFragmentCompiler = NULL;
     23 void *Shader::mVertexCompiler = NULL;
     24 
     25 Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
     26     : mHandle(handle), mRenderer(renderer), mResourceManager(manager)
     27 {
     28     mSource = NULL;
     29     mHlsl = NULL;
     30     mInfoLog = NULL;
     31 
     32     uncompile();
     33     initializeCompiler();
     34 
     35     mRefCount = 0;
     36     mDeleteStatus = false;
     37 }
     38 
     39 Shader::~Shader()
     40 {
     41     delete[] mSource;
     42     delete[] mHlsl;
     43     delete[] mInfoLog;
     44 }
     45 
     46 GLuint Shader::getHandle() const
     47 {
     48     return mHandle;
     49 }
     50 
     51 void Shader::setSource(GLsizei count, const char **string, const GLint *length)
     52 {
     53     delete[] mSource;
     54     int totalLength = 0;
     55 
     56     for (int i = 0; i < count; i++)
     57     {
     58         if (length && length[i] >= 0)
     59         {
     60             totalLength += length[i];
     61         }
     62         else
     63         {
     64             totalLength += (int)strlen(string[i]);
     65         }
     66     }
     67 
     68     mSource = new char[totalLength + 1];
     69     char *code = mSource;
     70 
     71     for (int i = 0; i < count; i++)
     72     {
     73         int stringLength;
     74 
     75         if (length && length[i] >= 0)
     76         {
     77             stringLength = length[i];
     78         }
     79         else
     80         {
     81             stringLength = (int)strlen(string[i]);
     82         }
     83 
     84         strncpy(code, string[i], stringLength);
     85         code += stringLength;
     86     }
     87 
     88     mSource[totalLength] = '\0';
     89 }
     90 
     91 int Shader::getInfoLogLength() const
     92 {
     93     if (!mInfoLog)
     94     {
     95         return 0;
     96     }
     97     else
     98     {
     99        return strlen(mInfoLog) + 1;
    100     }
    101 }
    102 
    103 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
    104 {
    105     int index = 0;
    106 
    107     if (bufSize > 0)
    108     {
    109         if (mInfoLog)
    110         {
    111             index = std::min(bufSize - 1, (int)strlen(mInfoLog));
    112             memcpy(infoLog, mInfoLog, index);
    113         }
    114 
    115         infoLog[index] = '\0';
    116     }
    117 
    118     if (length)
    119     {
    120         *length = index;
    121     }
    122 }
    123 
    124 int Shader::getSourceLength() const
    125 {
    126     if (!mSource)
    127     {
    128         return 0;
    129     }
    130     else
    131     {
    132        return strlen(mSource) + 1;
    133     }
    134 }
    135 
    136 int Shader::getTranslatedSourceLength() const
    137 {
    138     if (!mHlsl)
    139     {
    140         return 0;
    141     }
    142     else
    143     {
    144        return strlen(mHlsl) + 1;
    145     }
    146 }
    147 
    148 void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
    149 {
    150     int index = 0;
    151 
    152     if (bufSize > 0)
    153     {
    154         if (source)
    155         {
    156             index = std::min(bufSize - 1, (int)strlen(source));
    157             memcpy(buffer, source, index);
    158         }
    159 
    160         buffer[index] = '\0';
    161     }
    162 
    163     if (length)
    164     {
    165         *length = index;
    166     }
    167 }
    168 
    169 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
    170 {
    171     getSourceImpl(mSource, bufSize, length, buffer);
    172 }
    173 
    174 void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
    175 {
    176     getSourceImpl(mHlsl, bufSize, length, buffer);
    177 }
    178 
    179 const sh::ActiveUniforms &Shader::getUniforms()
    180 {
    181     return mActiveUniforms;
    182 }
    183 
    184 bool Shader::isCompiled()
    185 {
    186     return mHlsl != NULL;
    187 }
    188 
    189 const char *Shader::getHLSL()
    190 {
    191     return mHlsl;
    192 }
    193 
    194 void Shader::addRef()
    195 {
    196     mRefCount++;
    197 }
    198 
    199 void Shader::release()
    200 {
    201     mRefCount--;
    202 
    203     if (mRefCount == 0 && mDeleteStatus)
    204     {
    205         mResourceManager->deleteShader(mHandle);
    206     }
    207 }
    208 
    209 unsigned int Shader::getRefCount() const
    210 {
    211     return mRefCount;
    212 }
    213 
    214 bool Shader::isFlaggedForDeletion() const
    215 {
    216     return mDeleteStatus;
    217 }
    218 
    219 void Shader::flagForDeletion()
    220 {
    221     mDeleteStatus = true;
    222 }
    223 
    224 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
    225 void Shader::initializeCompiler()
    226 {
    227     if (!mFragmentCompiler)
    228     {
    229         int result = ShInitialize();
    230 
    231         if (result)
    232         {
    233             ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
    234 
    235             ShBuiltInResources resources;
    236             ShInitBuiltInResources(&resources);
    237 
    238             resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
    239             resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
    240             resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
    241             resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
    242             resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
    243             resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
    244             resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
    245             resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
    246             resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
    247             resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
    248             // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
    249             resources.FragmentPrecisionHigh = 1;   // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
    250             resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
    251 
    252             mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
    253             mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
    254         }
    255     }
    256 }
    257 
    258 void Shader::releaseCompiler()
    259 {
    260     ShDestruct(mFragmentCompiler);
    261     ShDestruct(mVertexCompiler);
    262 
    263     mFragmentCompiler = NULL;
    264     mVertexCompiler = NULL;
    265 
    266     ShFinalize();
    267 }
    268 
    269 void Shader::parseVaryings()
    270 {
    271     if (mHlsl)
    272     {
    273         const char *input = strstr(mHlsl, "// Varyings") + 12;
    274 
    275         while(true)
    276         {
    277             char varyingType[256];
    278             char varyingName[256];
    279 
    280             int matches = sscanf(input, "static %255s %255s", varyingType, varyingName);
    281 
    282             if (matches != 2)
    283             {
    284                 break;
    285             }
    286 
    287             char *array = strstr(varyingName, "[");
    288             int size = 1;
    289 
    290             if (array)
    291             {
    292                 size = atoi(array + 1);
    293                 *array = '\0';
    294             }
    295 
    296             mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
    297 
    298             input = strstr(input, ";") + 2;
    299         }
    300 
    301         mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL;
    302         mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL;
    303         mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL;
    304         mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
    305         mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
    306         mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
    307         mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
    308         mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
    309         mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
    310     }
    311 }
    312 
    313 void Shader::resetVaryingsRegisterAssignment()
    314 {
    315     for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
    316     {
    317         var->reg = -1;
    318         var->col = -1;
    319     }
    320 }
    321 
    322 // initialize/clean up previous state
    323 void Shader::uncompile()
    324 {
    325     // set by compileToHLSL
    326     delete[] mHlsl;
    327     mHlsl = NULL;
    328     delete[] mInfoLog;
    329     mInfoLog = NULL;
    330 
    331     // set by parseVaryings
    332     mVaryings.clear();
    333 
    334     mUsesMultipleRenderTargets = false;
    335     mUsesFragColor = false;
    336     mUsesFragData = false;
    337     mUsesFragCoord = false;
    338     mUsesFrontFacing = false;
    339     mUsesPointSize = false;
    340     mUsesPointCoord = false;
    341     mUsesDepthRange = false;
    342     mUsesFragDepth = false;
    343 
    344     mActiveUniforms.clear();
    345 }
    346 
    347 void Shader::compileToHLSL(void *compiler)
    348 {
    349     // ensure we don't pass a NULL source to the compiler
    350     const char *source = "\0";
    351     if (mSource)
    352     {
    353         source = mSource;
    354     }
    355 
    356     // ensure the compiler is loaded
    357     initializeCompiler();
    358 
    359     int compileOptions = SH_OBJECT_CODE;
    360     std::string sourcePath;
    361     if (perfActive())
    362     {
    363         sourcePath = getTempPath();
    364         writeFile(sourcePath.c_str(), source, strlen(source));
    365         compileOptions |= SH_LINE_DIRECTIVES;
    366     }
    367 
    368     int result;
    369     if (sourcePath.empty())
    370     {
    371         result = ShCompile(compiler, &source, 1, compileOptions);
    372     }
    373     else
    374     {
    375         const char* sourceStrings[2] =
    376         {
    377             sourcePath.c_str(),
    378             source
    379         };
    380 
    381         result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
    382     }
    383 
    384     if (result)
    385     {
    386         size_t objCodeLen = 0;
    387         ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
    388         mHlsl = new char[objCodeLen];
    389         ShGetObjectCode(compiler, mHlsl);
    390 
    391         void *activeUniforms;
    392         ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
    393         mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
    394     }
    395     else
    396     {
    397         size_t infoLogLen = 0;
    398         ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
    399         mInfoLog = new char[infoLogLen];
    400         ShGetInfoLog(compiler, mInfoLog);
    401 
    402         TRACE("\n%s", mInfoLog);
    403     }
    404 }
    405 
    406 GLenum Shader::parseType(const std::string &type)
    407 {
    408     if (type == "float")
    409     {
    410         return GL_FLOAT;
    411     }
    412     else if (type == "float2")
    413     {
    414         return GL_FLOAT_VEC2;
    415     }
    416     else if (type == "float3")
    417     {
    418         return GL_FLOAT_VEC3;
    419     }
    420     else if (type == "float4")
    421     {
    422         return GL_FLOAT_VEC4;
    423     }
    424     else if (type == "float2x2")
    425     {
    426         return GL_FLOAT_MAT2;
    427     }
    428     else if (type == "float3x3")
    429     {
    430         return GL_FLOAT_MAT3;
    431     }
    432     else if (type == "float4x4")
    433     {
    434         return GL_FLOAT_MAT4;
    435     }
    436     else UNREACHABLE();
    437 
    438     return GL_NONE;
    439 }
    440 
    441 // true if varying x has a higher priority in packing than y
    442 bool Shader::compareVarying(const Varying &x, const Varying &y)
    443 {
    444     if(x.type == y.type)
    445     {
    446         return x.size > y.size;
    447     }
    448 
    449     switch (x.type)
    450     {
    451       case GL_FLOAT_MAT4: return true;
    452       case GL_FLOAT_MAT2:
    453         switch(y.type)
    454         {
    455           case GL_FLOAT_MAT4: return false;
    456           case GL_FLOAT_MAT2: return true;
    457           case GL_FLOAT_VEC4: return true;
    458           case GL_FLOAT_MAT3: return true;
    459           case GL_FLOAT_VEC3: return true;
    460           case GL_FLOAT_VEC2: return true;
    461           case GL_FLOAT:      return true;
    462           default: UNREACHABLE();
    463         }
    464         break;
    465       case GL_FLOAT_VEC4:
    466         switch(y.type)
    467         {
    468           case GL_FLOAT_MAT4: return false;
    469           case GL_FLOAT_MAT2: return false;
    470           case GL_FLOAT_VEC4: return true;
    471           case GL_FLOAT_MAT3: return true;
    472           case GL_FLOAT_VEC3: return true;
    473           case GL_FLOAT_VEC2: return true;
    474           case GL_FLOAT:      return true;
    475           default: UNREACHABLE();
    476         }
    477         break;
    478       case GL_FLOAT_MAT3:
    479         switch(y.type)
    480         {
    481           case GL_FLOAT_MAT4: return false;
    482           case GL_FLOAT_MAT2: return false;
    483           case GL_FLOAT_VEC4: return false;
    484           case GL_FLOAT_MAT3: return true;
    485           case GL_FLOAT_VEC3: return true;
    486           case GL_FLOAT_VEC2: return true;
    487           case GL_FLOAT:      return true;
    488           default: UNREACHABLE();
    489         }
    490         break;
    491       case GL_FLOAT_VEC3:
    492         switch(y.type)
    493         {
    494           case GL_FLOAT_MAT4: return false;
    495           case GL_FLOAT_MAT2: return false;
    496           case GL_FLOAT_VEC4: return false;
    497           case GL_FLOAT_MAT3: return false;
    498           case GL_FLOAT_VEC3: return true;
    499           case GL_FLOAT_VEC2: return true;
    500           case GL_FLOAT:      return true;
    501           default: UNREACHABLE();
    502         }
    503         break;
    504       case GL_FLOAT_VEC2:
    505         switch(y.type)
    506         {
    507           case GL_FLOAT_MAT4: return false;
    508           case GL_FLOAT_MAT2: return false;
    509           case GL_FLOAT_VEC4: return false;
    510           case GL_FLOAT_MAT3: return false;
    511           case GL_FLOAT_VEC3: return false;
    512           case GL_FLOAT_VEC2: return true;
    513           case GL_FLOAT:      return true;
    514           default: UNREACHABLE();
    515         }
    516         break;
    517       case GL_FLOAT: return false;
    518       default: UNREACHABLE();
    519     }
    520 
    521     return false;
    522 }
    523 
    524 VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
    525     : Shader(manager, renderer, handle)
    526 {
    527 }
    528 
    529 VertexShader::~VertexShader()
    530 {
    531 }
    532 
    533 GLenum VertexShader::getType()
    534 {
    535     return GL_VERTEX_SHADER;
    536 }
    537 
    538 void VertexShader::uncompile()
    539 {
    540     Shader::uncompile();
    541 
    542     // set by ParseAttributes
    543     mAttributes.clear();
    544 }
    545 
    546 void VertexShader::compile()
    547 {
    548     uncompile();
    549 
    550     compileToHLSL(mVertexCompiler);
    551     parseAttributes();
    552     parseVaryings();
    553 }
    554 
    555 int VertexShader::getSemanticIndex(const std::string &attributeName)
    556 {
    557     if (!attributeName.empty())
    558     {
    559         int semanticIndex = 0;
    560         for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
    561         {
    562             if (attribute->name == attributeName)
    563             {
    564                 return semanticIndex;
    565             }
    566 
    567             semanticIndex += VariableRowCount(attribute->type);
    568         }
    569     }
    570 
    571     return -1;
    572 }
    573 
    574 void VertexShader::parseAttributes()
    575 {
    576     const char *hlsl = getHLSL();
    577     if (hlsl)
    578     {
    579         const char *input = strstr(hlsl, "// Attributes") + 14;
    580 
    581         while(true)
    582         {
    583             char attributeType[256];
    584             char attributeName[256];
    585 
    586             int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
    587 
    588             if (matches != 2)
    589             {
    590                 break;
    591             }
    592 
    593             mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
    594 
    595             input = strstr(input, ";") + 2;
    596         }
    597     }
    598 }
    599 
    600 FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
    601     : Shader(manager, renderer, handle)
    602 {
    603 }
    604 
    605 FragmentShader::~FragmentShader()
    606 {
    607 }
    608 
    609 GLenum FragmentShader::getType()
    610 {
    611     return GL_FRAGMENT_SHADER;
    612 }
    613 
    614 void FragmentShader::compile()
    615 {
    616     uncompile();
    617 
    618     compileToHLSL(mFragmentCompiler);
    619     parseVaryings();
    620     mVaryings.sort(compareVarying);
    621 }
    622 }
    623