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 "common/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     uncompile();
     29     initializeCompiler();
     30 
     31     mRefCount = 0;
     32     mDeleteStatus = false;
     33     mShaderVersion = 100;
     34 }
     35 
     36 Shader::~Shader()
     37 {
     38 }
     39 
     40 GLuint Shader::getHandle() const
     41 {
     42     return mHandle;
     43 }
     44 
     45 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
     46 {
     47     std::ostringstream stream;
     48 
     49     for (int i = 0; i < count; i++)
     50     {
     51         stream << string[i];
     52     }
     53 
     54     mSource = stream.str();
     55 }
     56 
     57 int Shader::getInfoLogLength() const
     58 {
     59     return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1);
     60 }
     61 
     62 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
     63 {
     64     int index = 0;
     65 
     66     if (bufSize > 0)
     67     {
     68         index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
     69         memcpy(infoLog, mInfoLog.c_str(), index);
     70 
     71         infoLog[index] = '\0';
     72     }
     73 
     74     if (length)
     75     {
     76         *length = index;
     77     }
     78 }
     79 
     80 int Shader::getSourceLength() const
     81 {
     82     return mSource.empty() ? 0 : (mSource.length() + 1);
     83 }
     84 
     85 int Shader::getTranslatedSourceLength() const
     86 {
     87     return mHlsl.empty() ? 0 : (mHlsl.length() + 1);
     88 }
     89 
     90 void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const
     91 {
     92     int index = 0;
     93 
     94     if (bufSize > 0)
     95     {
     96         index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
     97         memcpy(buffer, source.c_str(), index);
     98 
     99         buffer[index] = '\0';
    100     }
    101 
    102     if (length)
    103     {
    104         *length = index;
    105     }
    106 }
    107 
    108 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
    109 {
    110     getSourceImpl(mSource, bufSize, length, buffer);
    111 }
    112 
    113 void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
    114 {
    115     getSourceImpl(mHlsl, bufSize, length, buffer);
    116 }
    117 
    118 const std::vector<Uniform> &Shader::getUniforms() const
    119 {
    120     return mActiveUniforms;
    121 }
    122 
    123 const std::vector<InterfaceBlock> &Shader::getInterfaceBlocks() const
    124 {
    125     return mActiveInterfaceBlocks;
    126 }
    127 
    128 std::vector<PackedVarying> &Shader::getVaryings()
    129 {
    130     return mVaryings;
    131 }
    132 
    133 bool Shader::isCompiled() const
    134 {
    135     return !mHlsl.empty();
    136 }
    137 
    138 const std::string &Shader::getHLSL() const
    139 {
    140     return mHlsl;
    141 }
    142 
    143 void Shader::addRef()
    144 {
    145     mRefCount++;
    146 }
    147 
    148 void Shader::release()
    149 {
    150     mRefCount--;
    151 
    152     if (mRefCount == 0 && mDeleteStatus)
    153     {
    154         mResourceManager->deleteShader(mHandle);
    155     }
    156 }
    157 
    158 unsigned int Shader::getRefCount() const
    159 {
    160     return mRefCount;
    161 }
    162 
    163 bool Shader::isFlaggedForDeletion() const
    164 {
    165     return mDeleteStatus;
    166 }
    167 
    168 void Shader::flagForDeletion()
    169 {
    170     mDeleteStatus = true;
    171 }
    172 
    173 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
    174 void Shader::initializeCompiler()
    175 {
    176     if (!mFragmentCompiler)
    177     {
    178         int result = ShInitialize();
    179 
    180         if (result)
    181         {
    182             ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
    183 
    184             ShBuiltInResources resources;
    185             ShInitBuiltInResources(&resources);
    186 
    187             resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
    188             resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
    189             resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
    190             resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
    191             resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
    192             resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
    193             resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
    194             resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
    195             resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
    196             resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
    197             resources.EXT_shader_texture_lod = 1;
    198             // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
    199             resources.FragmentPrecisionHigh = 1;   // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
    200             resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
    201             // GLSL ES 3.0 constants
    202             resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
    203             resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
    204             resources.MinProgramTexelOffset = -8;   // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
    205             resources.MaxProgramTexelOffset = 7;    // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
    206 
    207             mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
    208             mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
    209         }
    210     }
    211 }
    212 
    213 void Shader::releaseCompiler()
    214 {
    215     ShDestruct(mFragmentCompiler);
    216     ShDestruct(mVertexCompiler);
    217 
    218     mFragmentCompiler = NULL;
    219     mVertexCompiler = NULL;
    220 
    221     ShFinalize();
    222 }
    223 
    224 void Shader::parseVaryings(void *compiler)
    225 {
    226     if (!mHlsl.empty())
    227     {
    228         std::vector<Varying> *activeVaryings;
    229         ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast<void**>(&activeVaryings));
    230 
    231         for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++)
    232         {
    233             mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex]));
    234         }
    235 
    236         mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT")          != std::string::npos;
    237         mUsesFragColor             = mHlsl.find("GL_USES_FRAG_COLOR")   != std::string::npos;
    238         mUsesFragData              = mHlsl.find("GL_USES_FRAG_DATA")    != std::string::npos;
    239         mUsesFragCoord             = mHlsl.find("GL_USES_FRAG_COORD")   != std::string::npos;
    240         mUsesFrontFacing           = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
    241         mUsesPointSize             = mHlsl.find("GL_USES_POINT_SIZE")   != std::string::npos;
    242         mUsesPointCoord            = mHlsl.find("GL_USES_POINT_COORD")  != std::string::npos;
    243         mUsesDepthRange            = mHlsl.find("GL_USES_DEPTH_RANGE")  != std::string::npos;
    244         mUsesFragDepth             = mHlsl.find("GL_USES_FRAG_DEPTH")   != std::string::npos;
    245         mUsesDiscardRewriting      = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
    246         mUsesNestedBreak           = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
    247     }
    248 }
    249 
    250 void Shader::resetVaryingsRegisterAssignment()
    251 {
    252     for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
    253     {
    254         mVaryings[varyingIndex].resetRegisterAssignment();
    255     }
    256 }
    257 
    258 // initialize/clean up previous state
    259 void Shader::uncompile()
    260 {
    261     // set by compileToHLSL
    262     mHlsl.clear();
    263     mInfoLog.clear();
    264 
    265     // set by parseVaryings
    266     mVaryings.clear();
    267 
    268     mUsesMultipleRenderTargets = false;
    269     mUsesFragColor = false;
    270     mUsesFragData = false;
    271     mUsesFragCoord = false;
    272     mUsesFrontFacing = false;
    273     mUsesPointSize = false;
    274     mUsesPointCoord = false;
    275     mUsesDepthRange = false;
    276     mUsesFragDepth = false;
    277     mShaderVersion = 100;
    278     mUsesDiscardRewriting = false;
    279     mUsesNestedBreak = false;
    280 
    281     mActiveUniforms.clear();
    282     mActiveInterfaceBlocks.clear();
    283 }
    284 
    285 void Shader::compileToHLSL(void *compiler)
    286 {
    287     // ensure the compiler is loaded
    288     initializeCompiler();
    289 
    290     int compileOptions = SH_OBJECT_CODE;
    291     std::string sourcePath;
    292     if (perfActive())
    293     {
    294         sourcePath = getTempPath();
    295         writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length());
    296         compileOptions |= SH_LINE_DIRECTIVES;
    297     }
    298 
    299     int result;
    300     if (sourcePath.empty())
    301     {
    302         const char* sourceStrings[] =
    303         {
    304             mSource.c_str(),
    305         };
    306 
    307         result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
    308     }
    309     else
    310     {
    311         const char* sourceStrings[] =
    312         {
    313             sourcePath.c_str(),
    314             mSource.c_str(),
    315         };
    316 
    317         result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
    318     }
    319 
    320     size_t shaderVersion = 100;
    321     ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
    322 
    323     mShaderVersion = static_cast<int>(shaderVersion);
    324 
    325     if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
    326     {
    327         mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
    328         TRACE("\n%s", mInfoLog.c_str());
    329     }
    330     else if (result)
    331     {
    332         size_t objCodeLen = 0;
    333         ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
    334 
    335         char* outputHLSL = new char[objCodeLen];
    336         ShGetObjectCode(compiler, outputHLSL);
    337 
    338 #ifdef _DEBUG
    339         std::ostringstream hlslStream;
    340         hlslStream << "// GLSL\n";
    341         hlslStream << "//\n";
    342 
    343         size_t curPos = 0;
    344         while (curPos != std::string::npos)
    345         {
    346             size_t nextLine = mSource.find("\n", curPos);
    347             size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
    348 
    349             hlslStream << "// " << mSource.substr(curPos, len);
    350 
    351             curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
    352         }
    353         hlslStream << "\n\n";
    354         hlslStream << outputHLSL;
    355         mHlsl = hlslStream.str();
    356 #else
    357         mHlsl = outputHLSL;
    358 #endif
    359 
    360         delete[] outputHLSL;
    361 
    362         void *activeUniforms;
    363         ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
    364         mActiveUniforms = *(std::vector<Uniform>*)activeUniforms;
    365 
    366         void *activeInterfaceBlocks;
    367         ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
    368         mActiveInterfaceBlocks = *(std::vector<InterfaceBlock>*)activeInterfaceBlocks;
    369     }
    370     else
    371     {
    372         size_t infoLogLen = 0;
    373         ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
    374 
    375         char* infoLog = new char[infoLogLen];
    376         ShGetInfoLog(compiler, infoLog);
    377         mInfoLog = infoLog;
    378 
    379         TRACE("\n%s", mInfoLog.c_str());
    380     }
    381 }
    382 
    383 rx::D3DWorkaroundType Shader::getD3DWorkarounds() const
    384 {
    385     if (mUsesDiscardRewriting)
    386     {
    387         // ANGLE issue 486:
    388         // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
    389         return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
    390     }
    391 
    392     if (mUsesNestedBreak)
    393     {
    394         // ANGLE issue 603:
    395         // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
    396         // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
    397         return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
    398     }
    399 
    400     return rx::ANGLE_D3D_WORKAROUND_NONE;
    401 }
    402 
    403 // [OpenGL ES SL 3.00.4] Section 11 p. 120
    404 // Vertex Outs/Fragment Ins packing priorities
    405 static const GLenum varyingPriorityList[] =
    406 {
    407     // 1. Arrays of mat4 and mat4
    408     GL_FLOAT_MAT4,
    409 
    410     // Non-square matrices of type matCxR consume the same space as a square
    411     // matrix of type matN where N is the greater of C and R
    412     GL_FLOAT_MAT3x4,
    413     GL_FLOAT_MAT4x3,
    414     GL_FLOAT_MAT2x4,
    415     GL_FLOAT_MAT4x2,
    416 
    417     // 2. Arrays of mat2 and mat2 (since they occupy full rows)
    418     GL_FLOAT_MAT2,
    419 
    420     // 3. Arrays of vec4 and vec4
    421     GL_FLOAT_VEC4,
    422     GL_INT_VEC4,
    423     GL_UNSIGNED_INT_VEC4,
    424 
    425     // 4. Arrays of mat3 and mat3
    426     GL_FLOAT_MAT3,
    427     GL_FLOAT_MAT2x3,
    428     GL_FLOAT_MAT3x2,
    429 
    430     // 5. Arrays of vec3 and vec3
    431     GL_FLOAT_VEC3,
    432     GL_INT_VEC3,
    433     GL_UNSIGNED_INT_VEC3,
    434 
    435     // 6. Arrays of vec2 and vec2
    436     GL_FLOAT_VEC2,
    437     GL_INT_VEC2,
    438     GL_UNSIGNED_INT_VEC2,
    439 
    440     // 7. Arrays of float and float
    441     GL_FLOAT,
    442     GL_INT,
    443     GL_UNSIGNED_INT,
    444 };
    445 
    446 // true if varying x has a higher priority in packing than y
    447 bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y)
    448 {
    449     if (x.type == y.type)
    450     {
    451         return x.arraySize > y.arraySize;
    452     }
    453 
    454     // Special case for handling structs: we sort these to the end of the list
    455     if (x.type == GL_STRUCT_ANGLEX)
    456     {
    457         return false;
    458     }
    459 
    460     unsigned int xPriority = GL_INVALID_INDEX;
    461     unsigned int yPriority = GL_INVALID_INDEX;
    462 
    463     for (unsigned int priorityIndex = 0; priorityIndex < ArraySize(varyingPriorityList); priorityIndex++)
    464     {
    465         if (varyingPriorityList[priorityIndex] == x.type) xPriority = priorityIndex;
    466         if (varyingPriorityList[priorityIndex] == y.type) yPriority = priorityIndex;
    467         if (xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX) break;
    468     }
    469 
    470     ASSERT(xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX);
    471 
    472     return xPriority <= yPriority;
    473 }
    474 
    475 int Shader::getShaderVersion() const
    476 {
    477     return mShaderVersion;
    478 }
    479 
    480 VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
    481     : Shader(manager, renderer, handle)
    482 {
    483 }
    484 
    485 VertexShader::~VertexShader()
    486 {
    487 }
    488 
    489 GLenum VertexShader::getType()
    490 {
    491     return GL_VERTEX_SHADER;
    492 }
    493 
    494 void VertexShader::uncompile()
    495 {
    496     Shader::uncompile();
    497 
    498     // set by ParseAttributes
    499     mActiveAttributes.clear();
    500 }
    501 
    502 void VertexShader::compile()
    503 {
    504     uncompile();
    505 
    506     compileToHLSL(mVertexCompiler);
    507     parseAttributes();
    508     parseVaryings(mVertexCompiler);
    509 }
    510 
    511 int VertexShader::getSemanticIndex(const std::string &attributeName)
    512 {
    513     if (!attributeName.empty())
    514     {
    515         int semanticIndex = 0;
    516         for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
    517         {
    518             const ShaderVariable &attribute = mActiveAttributes[attributeIndex];
    519 
    520             if (attribute.name == attributeName)
    521             {
    522                 return semanticIndex;
    523             }
    524 
    525             semanticIndex += AttributeRegisterCount(attribute.type);
    526         }
    527     }
    528 
    529     return -1;
    530 }
    531 
    532 void VertexShader::parseAttributes()
    533 {
    534     const std::string &hlsl = getHLSL();
    535     if (!hlsl.empty())
    536     {
    537         void *activeAttributes;
    538         ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
    539         mActiveAttributes = *(std::vector<Attribute>*)activeAttributes;
    540     }
    541 }
    542 
    543 FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
    544     : Shader(manager, renderer, handle)
    545 {
    546 }
    547 
    548 FragmentShader::~FragmentShader()
    549 {
    550 }
    551 
    552 GLenum FragmentShader::getType()
    553 {
    554     return GL_FRAGMENT_SHADER;
    555 }
    556 
    557 void FragmentShader::compile()
    558 {
    559     uncompile();
    560 
    561     compileToHLSL(mFragmentCompiler);
    562     parseVaryings(mFragmentCompiler);
    563     std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
    564 
    565     const std::string &hlsl = getHLSL();
    566     if (!hlsl.empty())
    567     {
    568         void *activeOutputVariables;
    569         ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
    570         mActiveOutputVariables = *(std::vector<Attribute>*)activeOutputVariables;
    571     }
    572 }
    573 
    574 void FragmentShader::uncompile()
    575 {
    576     Shader::uncompile();
    577 
    578     mActiveOutputVariables.clear();
    579 }
    580 
    581 const std::vector<Attribute> &FragmentShader::getOutputVariables() const
    582 {
    583     return mActiveOutputVariables;
    584 }
    585 
    586 ShShaderOutput Shader::getCompilerOutputType(GLenum shader)
    587 {
    588     void *compiler = NULL;
    589 
    590     switch (shader)
    591     {
    592       case GL_VERTEX_SHADER:   compiler = mVertexCompiler;   break;
    593       case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break;
    594       default: UNREACHABLE();  return SH_HLSL9_OUTPUT;
    595     }
    596 
    597     size_t outputType = 0;
    598     ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType);
    599 
    600     return static_cast<ShShaderOutput>(outputType);
    601 }
    602 
    603 }
    604