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         mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL;
    311     }
    312 }
    313 
    314 void Shader::resetVaryingsRegisterAssignment()
    315 {
    316     for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
    317     {
    318         var->reg = -1;
    319         var->col = -1;
    320     }
    321 }
    322 
    323 // initialize/clean up previous state
    324 void Shader::uncompile()
    325 {
    326     // set by compileToHLSL
    327     delete[] mHlsl;
    328     mHlsl = NULL;
    329     delete[] mInfoLog;
    330     mInfoLog = NULL;
    331 
    332     // set by parseVaryings
    333     mVaryings.clear();
    334 
    335     mUsesMultipleRenderTargets = false;
    336     mUsesFragColor = false;
    337     mUsesFragData = false;
    338     mUsesFragCoord = false;
    339     mUsesFrontFacing = false;
    340     mUsesPointSize = false;
    341     mUsesPointCoord = false;
    342     mUsesDepthRange = false;
    343     mUsesFragDepth = false;
    344     mUsesDiscardRewriting = false;
    345 
    346     mActiveUniforms.clear();
    347 }
    348 
    349 void Shader::compileToHLSL(void *compiler)
    350 {
    351     // ensure we don't pass a NULL source to the compiler
    352     const char *source = "\0";
    353     if (mSource)
    354     {
    355         source = mSource;
    356     }
    357 
    358     // ensure the compiler is loaded
    359     initializeCompiler();
    360 
    361     int compileOptions = SH_OBJECT_CODE;
    362     std::string sourcePath;
    363     if (perfActive())
    364     {
    365         sourcePath = getTempPath();
    366         writeFile(sourcePath.c_str(), source, strlen(source));
    367         compileOptions |= SH_LINE_DIRECTIVES;
    368     }
    369 
    370     int result;
    371     if (sourcePath.empty())
    372     {
    373         result = ShCompile(compiler, &source, 1, compileOptions);
    374     }
    375     else
    376     {
    377         const char* sourceStrings[2] =
    378         {
    379             sourcePath.c_str(),
    380             source
    381         };
    382 
    383         result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
    384     }
    385 
    386     if (result)
    387     {
    388         size_t objCodeLen = 0;
    389         ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
    390         mHlsl = new char[objCodeLen];
    391         ShGetObjectCode(compiler, mHlsl);
    392 
    393         void *activeUniforms;
    394         ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
    395         mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
    396     }
    397     else
    398     {
    399         size_t infoLogLen = 0;
    400         ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
    401         mInfoLog = new char[infoLogLen];
    402         ShGetInfoLog(compiler, mInfoLog);
    403 
    404         TRACE("\n%s", mInfoLog);
    405     }
    406 }
    407 
    408 GLenum Shader::parseType(const std::string &type)
    409 {
    410     if (type == "float")
    411     {
    412         return GL_FLOAT;
    413     }
    414     else if (type == "float2")
    415     {
    416         return GL_FLOAT_VEC2;
    417     }
    418     else if (type == "float3")
    419     {
    420         return GL_FLOAT_VEC3;
    421     }
    422     else if (type == "float4")
    423     {
    424         return GL_FLOAT_VEC4;
    425     }
    426     else if (type == "float2x2")
    427     {
    428         return GL_FLOAT_MAT2;
    429     }
    430     else if (type == "float3x3")
    431     {
    432         return GL_FLOAT_MAT3;
    433     }
    434     else if (type == "float4x4")
    435     {
    436         return GL_FLOAT_MAT4;
    437     }
    438     else UNREACHABLE();
    439 
    440     return GL_NONE;
    441 }
    442 
    443 // true if varying x has a higher priority in packing than y
    444 bool Shader::compareVarying(const Varying &x, const Varying &y)
    445 {
    446     if(x.type == y.type)
    447     {
    448         return x.size > y.size;
    449     }
    450 
    451     switch (x.type)
    452     {
    453       case GL_FLOAT_MAT4: return true;
    454       case GL_FLOAT_MAT2:
    455         switch(y.type)
    456         {
    457           case GL_FLOAT_MAT4: return false;
    458           case GL_FLOAT_MAT2: return true;
    459           case GL_FLOAT_VEC4: return true;
    460           case GL_FLOAT_MAT3: return true;
    461           case GL_FLOAT_VEC3: return true;
    462           case GL_FLOAT_VEC2: return true;
    463           case GL_FLOAT:      return true;
    464           default: UNREACHABLE();
    465         }
    466         break;
    467       case GL_FLOAT_VEC4:
    468         switch(y.type)
    469         {
    470           case GL_FLOAT_MAT4: return false;
    471           case GL_FLOAT_MAT2: return false;
    472           case GL_FLOAT_VEC4: return true;
    473           case GL_FLOAT_MAT3: return true;
    474           case GL_FLOAT_VEC3: return true;
    475           case GL_FLOAT_VEC2: return true;
    476           case GL_FLOAT:      return true;
    477           default: UNREACHABLE();
    478         }
    479         break;
    480       case GL_FLOAT_MAT3:
    481         switch(y.type)
    482         {
    483           case GL_FLOAT_MAT4: return false;
    484           case GL_FLOAT_MAT2: return false;
    485           case GL_FLOAT_VEC4: return false;
    486           case GL_FLOAT_MAT3: return true;
    487           case GL_FLOAT_VEC3: return true;
    488           case GL_FLOAT_VEC2: return true;
    489           case GL_FLOAT:      return true;
    490           default: UNREACHABLE();
    491         }
    492         break;
    493       case GL_FLOAT_VEC3:
    494         switch(y.type)
    495         {
    496           case GL_FLOAT_MAT4: return false;
    497           case GL_FLOAT_MAT2: return false;
    498           case GL_FLOAT_VEC4: return false;
    499           case GL_FLOAT_MAT3: return false;
    500           case GL_FLOAT_VEC3: return true;
    501           case GL_FLOAT_VEC2: return true;
    502           case GL_FLOAT:      return true;
    503           default: UNREACHABLE();
    504         }
    505         break;
    506       case GL_FLOAT_VEC2:
    507         switch(y.type)
    508         {
    509           case GL_FLOAT_MAT4: return false;
    510           case GL_FLOAT_MAT2: return false;
    511           case GL_FLOAT_VEC4: return false;
    512           case GL_FLOAT_MAT3: return false;
    513           case GL_FLOAT_VEC3: return false;
    514           case GL_FLOAT_VEC2: return true;
    515           case GL_FLOAT:      return true;
    516           default: UNREACHABLE();
    517         }
    518         break;
    519       case GL_FLOAT: return false;
    520       default: UNREACHABLE();
    521     }
    522 
    523     return false;
    524 }
    525 
    526 VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
    527     : Shader(manager, renderer, handle)
    528 {
    529 }
    530 
    531 VertexShader::~VertexShader()
    532 {
    533 }
    534 
    535 GLenum VertexShader::getType()
    536 {
    537     return GL_VERTEX_SHADER;
    538 }
    539 
    540 void VertexShader::uncompile()
    541 {
    542     Shader::uncompile();
    543 
    544     // set by ParseAttributes
    545     mAttributes.clear();
    546 }
    547 
    548 void VertexShader::compile()
    549 {
    550     uncompile();
    551 
    552     compileToHLSL(mVertexCompiler);
    553     parseAttributes();
    554     parseVaryings();
    555 }
    556 
    557 int VertexShader::getSemanticIndex(const std::string &attributeName)
    558 {
    559     if (!attributeName.empty())
    560     {
    561         int semanticIndex = 0;
    562         for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
    563         {
    564             if (attribute->name == attributeName)
    565             {
    566                 return semanticIndex;
    567             }
    568 
    569             semanticIndex += VariableRowCount(attribute->type);
    570         }
    571     }
    572 
    573     return -1;
    574 }
    575 
    576 void VertexShader::parseAttributes()
    577 {
    578     const char *hlsl = getHLSL();
    579     if (hlsl)
    580     {
    581         const char *input = strstr(hlsl, "// Attributes") + 14;
    582 
    583         while(true)
    584         {
    585             char attributeType[256];
    586             char attributeName[256];
    587 
    588             int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
    589 
    590             if (matches != 2)
    591             {
    592                 break;
    593             }
    594 
    595             mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
    596 
    597             input = strstr(input, ";") + 2;
    598         }
    599     }
    600 }
    601 
    602 FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
    603     : Shader(manager, renderer, handle)
    604 {
    605 }
    606 
    607 FragmentShader::~FragmentShader()
    608 {
    609 }
    610 
    611 GLenum FragmentShader::getType()
    612 {
    613     return GL_FRAGMENT_SHADER;
    614 }
    615 
    616 void FragmentShader::compile()
    617 {
    618     uncompile();
    619 
    620     compileToHLSL(mFragmentCompiler);
    621     parseVaryings();
    622     mVaryings.sort(compareVarying);
    623 }
    624 }
    625