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 // Program.cpp: Implements the gl::Program class. Implements GL program objects
      9 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
     10 
     11 #include "libGLESv2/BinaryStream.h"
     12 #include "libGLESv2/ProgramBinary.h"
     13 #include "libGLESv2/renderer/ShaderExecutable.h"
     14 
     15 #include "common/debug.h"
     16 #include "common/version.h"
     17 #include "utilities.h"
     18 
     19 #include "libGLESv2/main.h"
     20 #include "libGLESv2/Shader.h"
     21 #include "libGLESv2/Program.h"
     22 #include "libGLESv2/renderer/Renderer.h"
     23 #include "libGLESv2/renderer/VertexDataManager.h"
     24 
     25 #undef near
     26 #undef far
     27 
     28 namespace gl
     29 {
     30 std::string str(int i)
     31 {
     32     char buffer[20];
     33     snprintf(buffer, sizeof(buffer), "%d", i);
     34     return buffer;
     35 }
     36 
     37 static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard)
     38 {
     39     return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE);
     40 }
     41 
     42 UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
     43     : name(name), element(element), index(index)
     44 {
     45 }
     46 
     47 unsigned int ProgramBinary::mCurrentSerial = 1;
     48 
     49 ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial())
     50 {
     51     mPixelExecutable = NULL;
     52     mVertexExecutable = NULL;
     53     mGeometryExecutable = NULL;
     54 
     55     mValidated = false;
     56 
     57     for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
     58     {
     59         mSemanticIndex[index] = -1;
     60     }
     61 
     62     for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
     63     {
     64         mSamplersPS[index].active = false;
     65     }
     66 
     67     for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
     68     {
     69         mSamplersVS[index].active = false;
     70     }
     71 
     72     mUsedVertexSamplerRange = 0;
     73     mUsedPixelSamplerRange = 0;
     74     mUsesPointSize = false;
     75 }
     76 
     77 ProgramBinary::~ProgramBinary()
     78 {
     79     delete mPixelExecutable;
     80     mPixelExecutable = NULL;
     81 
     82     delete mVertexExecutable;
     83     mVertexExecutable = NULL;
     84 
     85     delete mGeometryExecutable;
     86     mGeometryExecutable = NULL;
     87 
     88     while (!mUniforms.empty())
     89     {
     90         delete mUniforms.back();
     91         mUniforms.pop_back();
     92     }
     93 }
     94 
     95 unsigned int ProgramBinary::getSerial() const
     96 {
     97     return mSerial;
     98 }
     99 
    100 unsigned int ProgramBinary::issueSerial()
    101 {
    102     return mCurrentSerial++;
    103 }
    104 
    105 rx::ShaderExecutable *ProgramBinary::getPixelExecutable()
    106 {
    107     return mPixelExecutable;
    108 }
    109 
    110 rx::ShaderExecutable *ProgramBinary::getVertexExecutable()
    111 {
    112     return mVertexExecutable;
    113 }
    114 
    115 rx::ShaderExecutable *ProgramBinary::getGeometryExecutable()
    116 {
    117     return mGeometryExecutable;
    118 }
    119 
    120 GLuint ProgramBinary::getAttributeLocation(const char *name)
    121 {
    122     if (name)
    123     {
    124         for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
    125         {
    126             if (mLinkedAttribute[index].name == std::string(name))
    127             {
    128                 return index;
    129             }
    130         }
    131     }
    132 
    133     return -1;
    134 }
    135 
    136 int ProgramBinary::getSemanticIndex(int attributeIndex)
    137 {
    138     ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
    139 
    140     return mSemanticIndex[attributeIndex];
    141 }
    142 
    143 // Returns one more than the highest sampler index used.
    144 GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
    145 {
    146     switch (type)
    147     {
    148       case SAMPLER_PIXEL:
    149         return mUsedPixelSamplerRange;
    150       case SAMPLER_VERTEX:
    151         return mUsedVertexSamplerRange;
    152       default:
    153         UNREACHABLE();
    154         return 0;
    155     }
    156 }
    157 
    158 bool ProgramBinary::usesPointSize() const
    159 {
    160     return mUsesPointSize;
    161 }
    162 
    163 bool ProgramBinary::usesPointSpriteEmulation() const
    164 {
    165     return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
    166 }
    167 
    168 bool ProgramBinary::usesGeometryShader() const
    169 {
    170     return usesPointSpriteEmulation();
    171 }
    172 
    173 // Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
    174 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
    175 GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
    176 {
    177     GLint logicalTextureUnit = -1;
    178 
    179     switch (type)
    180     {
    181       case SAMPLER_PIXEL:
    182         ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
    183 
    184         if (mSamplersPS[samplerIndex].active)
    185         {
    186             logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
    187         }
    188         break;
    189       case SAMPLER_VERTEX:
    190         ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
    191 
    192         if (mSamplersVS[samplerIndex].active)
    193         {
    194             logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
    195         }
    196         break;
    197       default: UNREACHABLE();
    198     }
    199 
    200     if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits())
    201     {
    202         return logicalTextureUnit;
    203     }
    204 
    205     return -1;
    206 }
    207 
    208 // Returns the texture type for a given Direct3D 9 sampler type and
    209 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
    210 TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
    211 {
    212     switch (type)
    213     {
    214       case SAMPLER_PIXEL:
    215         ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
    216         ASSERT(mSamplersPS[samplerIndex].active);
    217         return mSamplersPS[samplerIndex].textureType;
    218       case SAMPLER_VERTEX:
    219         ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
    220         ASSERT(mSamplersVS[samplerIndex].active);
    221         return mSamplersVS[samplerIndex].textureType;
    222       default: UNREACHABLE();
    223     }
    224 
    225     return TEXTURE_2D;
    226 }
    227 
    228 GLint ProgramBinary::getUniformLocation(std::string name)
    229 {
    230     unsigned int subscript = 0;
    231 
    232     // Strip any trailing array operator and retrieve the subscript
    233     size_t open = name.find_last_of('[');
    234     size_t close = name.find_last_of(']');
    235     if (open != std::string::npos && close == name.length() - 1)
    236     {
    237         subscript = atoi(name.substr(open + 1).c_str());
    238         name.erase(open);
    239     }
    240 
    241     unsigned int numUniforms = mUniformIndex.size();
    242     for (unsigned int location = 0; location < numUniforms; location++)
    243     {
    244         if (mUniformIndex[location].name == name &&
    245             mUniformIndex[location].element == subscript)
    246         {
    247             return location;
    248         }
    249     }
    250 
    251     return -1;
    252 }
    253 
    254 bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
    255 {
    256     if (location < 0 || location >= (int)mUniformIndex.size())
    257     {
    258         return false;
    259     }
    260 
    261     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    262     targetUniform->dirty = true;
    263 
    264     int elementCount = targetUniform->elementCount();
    265 
    266     if (elementCount == 1 && count > 1)
    267         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    268 
    269     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    270 
    271     if (targetUniform->type == GL_FLOAT)
    272     {
    273         GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
    274 
    275         for (int i = 0; i < count; i++)
    276         {
    277             target[0] = v[0];
    278             target[1] = 0;
    279             target[2] = 0;
    280             target[3] = 0;
    281             target += 4;
    282             v += 1;
    283         }
    284     }
    285     else if (targetUniform->type == GL_BOOL)
    286     {
    287         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    288 
    289         for (int i = 0; i < count; i++)
    290         {
    291             boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
    292             boolParams[1] = GL_FALSE;
    293             boolParams[2] = GL_FALSE;
    294             boolParams[3] = GL_FALSE;
    295             boolParams += 4;
    296             v += 1;
    297         }
    298     }
    299     else
    300     {
    301         return false;
    302     }
    303 
    304     return true;
    305 }
    306 
    307 bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
    308 {
    309     if (location < 0 || location >= (int)mUniformIndex.size())
    310     {
    311         return false;
    312     }
    313 
    314     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    315     targetUniform->dirty = true;
    316 
    317     int elementCount = targetUniform->elementCount();
    318 
    319     if (elementCount == 1 && count > 1)
    320         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    321 
    322     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    323 
    324     if (targetUniform->type == GL_FLOAT_VEC2)
    325     {
    326         GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
    327 
    328         for (int i = 0; i < count; i++)
    329         {
    330             target[0] = v[0];
    331             target[1] = v[1];
    332             target[2] = 0;
    333             target[3] = 0;
    334             target += 4;
    335             v += 2;
    336         }
    337     }
    338     else if (targetUniform->type == GL_BOOL_VEC2)
    339     {
    340         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    341 
    342         for (int i = 0; i < count; i++)
    343         {
    344             boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
    345             boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
    346             boolParams[2] = GL_FALSE;
    347             boolParams[3] = GL_FALSE;
    348             boolParams += 4;
    349             v += 2;
    350         }
    351     }
    352     else
    353     {
    354         return false;
    355     }
    356 
    357     return true;
    358 }
    359 
    360 bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
    361 {
    362     if (location < 0 || location >= (int)mUniformIndex.size())
    363     {
    364         return false;
    365     }
    366 
    367     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    368     targetUniform->dirty = true;
    369 
    370     int elementCount = targetUniform->elementCount();
    371 
    372     if (elementCount == 1 && count > 1)
    373         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    374 
    375     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    376 
    377     if (targetUniform->type == GL_FLOAT_VEC3)
    378     {
    379         GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
    380 
    381         for (int i = 0; i < count; i++)
    382         {
    383             target[0] = v[0];
    384             target[1] = v[1];
    385             target[2] = v[2];
    386             target[3] = 0;
    387             target += 4;
    388             v += 3;
    389         }
    390     }
    391     else if (targetUniform->type == GL_BOOL_VEC3)
    392     {
    393         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    394 
    395         for (int i = 0; i < count; i++)
    396         {
    397             boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
    398             boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
    399             boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE;
    400             boolParams[3] = GL_FALSE;
    401             boolParams += 4;
    402             v += 3;
    403         }
    404     }
    405     else
    406     {
    407         return false;
    408     }
    409 
    410     return true;
    411 }
    412 
    413 bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
    414 {
    415     if (location < 0 || location >= (int)mUniformIndex.size())
    416     {
    417         return false;
    418     }
    419 
    420     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    421     targetUniform->dirty = true;
    422 
    423     int elementCount = targetUniform->elementCount();
    424 
    425     if (elementCount == 1 && count > 1)
    426         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    427 
    428     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    429 
    430     if (targetUniform->type == GL_FLOAT_VEC4)
    431     {
    432         GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
    433 
    434         for (int i = 0; i < count; i++)
    435         {
    436             target[0] = v[0];
    437             target[1] = v[1];
    438             target[2] = v[2];
    439             target[3] = v[3];
    440             target += 4;
    441             v += 4;
    442         }
    443     }
    444     else if (targetUniform->type == GL_BOOL_VEC4)
    445     {
    446         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    447 
    448         for (int i = 0; i < count; i++)
    449         {
    450             boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
    451             boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
    452             boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE;
    453             boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE;
    454             boolParams += 4;
    455             v += 4;
    456         }
    457     }
    458     else
    459     {
    460         return false;
    461     }
    462 
    463     return true;
    464 }
    465 
    466 template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
    467 void transposeMatrix(T *target, const GLfloat *value)
    468 {
    469     int copyWidth = std::min(targetWidth, srcWidth);
    470     int copyHeight = std::min(targetHeight, srcHeight);
    471 
    472     for (int x = 0; x < copyWidth; x++)
    473     {
    474         for (int y = 0; y < copyHeight; y++)
    475         {
    476             target[x * targetWidth + y] = (T)value[y * srcWidth + x];
    477         }
    478     }
    479     // clear unfilled right side
    480     for (int y = 0; y < copyHeight; y++)
    481     {
    482         for (int x = srcWidth; x < targetWidth; x++)
    483         {
    484             target[y * targetWidth + x] = (T)0;
    485         }
    486     }
    487     // clear unfilled bottom.
    488     for (int y = srcHeight; y < targetHeight; y++)
    489     {
    490         for (int x = 0; x < targetWidth; x++)
    491         {
    492             target[y * targetWidth + x] = (T)0;
    493         }
    494     }
    495 }
    496 
    497 bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
    498 {
    499     if (location < 0 || location >= (int)mUniformIndex.size())
    500     {
    501         return false;
    502     }
    503 
    504     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    505     targetUniform->dirty = true;
    506 
    507     if (targetUniform->type != GL_FLOAT_MAT2)
    508     {
    509         return false;
    510     }
    511 
    512     int elementCount = targetUniform->elementCount();
    513 
    514     if (elementCount == 1 && count > 1)
    515         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    516 
    517     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    518     GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
    519 
    520     for (int i = 0; i < count; i++)
    521     {
    522         transposeMatrix<GLfloat,4,2,2,2>(target, value);
    523         target += 8;
    524         value += 4;
    525     }
    526 
    527     return true;
    528 }
    529 
    530 bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
    531 {
    532     if (location < 0 || location >= (int)mUniformIndex.size())
    533     {
    534         return false;
    535     }
    536 
    537     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    538     targetUniform->dirty = true;
    539 
    540     if (targetUniform->type != GL_FLOAT_MAT3)
    541     {
    542         return false;
    543     }
    544 
    545     int elementCount = targetUniform->elementCount();
    546 
    547     if (elementCount == 1 && count > 1)
    548         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    549 
    550     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    551     GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
    552 
    553     for (int i = 0; i < count; i++)
    554     {
    555         transposeMatrix<GLfloat,4,3,3,3>(target, value);
    556         target += 12;
    557         value += 9;
    558     }
    559 
    560     return true;
    561 }
    562 
    563 
    564 bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
    565 {
    566     if (location < 0 || location >= (int)mUniformIndex.size())
    567     {
    568         return false;
    569     }
    570 
    571     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    572     targetUniform->dirty = true;
    573 
    574     if (targetUniform->type != GL_FLOAT_MAT4)
    575     {
    576         return false;
    577     }
    578 
    579     int elementCount = targetUniform->elementCount();
    580 
    581     if (elementCount == 1 && count > 1)
    582         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    583 
    584     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    585     GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
    586 
    587     for (int i = 0; i < count; i++)
    588     {
    589         transposeMatrix<GLfloat,4,4,4,4>(target, value);
    590         target += 16;
    591         value += 16;
    592     }
    593 
    594     return true;
    595 }
    596 
    597 bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
    598 {
    599     if (location < 0 || location >= (int)mUniformIndex.size())
    600     {
    601         return false;
    602     }
    603 
    604     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    605     targetUniform->dirty = true;
    606 
    607     int elementCount = targetUniform->elementCount();
    608 
    609     if (elementCount == 1 && count > 1)
    610         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    611 
    612     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    613 
    614     if (targetUniform->type == GL_INT ||
    615         targetUniform->type == GL_SAMPLER_2D ||
    616         targetUniform->type == GL_SAMPLER_CUBE)
    617     {
    618         GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    619 
    620         for (int i = 0; i < count; i++)
    621         {
    622             target[0] = v[0];
    623             target[1] = 0;
    624             target[2] = 0;
    625             target[3] = 0;
    626             target += 4;
    627             v += 1;
    628         }
    629     }
    630     else if (targetUniform->type == GL_BOOL)
    631     {
    632         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    633 
    634         for (int i = 0; i < count; i++)
    635         {
    636             boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
    637             boolParams[1] = GL_FALSE;
    638             boolParams[2] = GL_FALSE;
    639             boolParams[3] = GL_FALSE;
    640             boolParams += 4;
    641             v += 1;
    642         }
    643     }
    644     else
    645     {
    646         return false;
    647     }
    648 
    649     return true;
    650 }
    651 
    652 bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
    653 {
    654     if (location < 0 || location >= (int)mUniformIndex.size())
    655     {
    656         return false;
    657     }
    658 
    659     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    660     targetUniform->dirty = true;
    661 
    662     int elementCount = targetUniform->elementCount();
    663 
    664     if (elementCount == 1 && count > 1)
    665         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    666 
    667     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    668 
    669     if (targetUniform->type == GL_INT_VEC2)
    670     {
    671         GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    672 
    673         for (int i = 0; i < count; i++)
    674         {
    675             target[0] = v[0];
    676             target[1] = v[1];
    677             target[2] = 0;
    678             target[3] = 0;
    679             target += 4;
    680             v += 2;
    681         }
    682     }
    683     else if (targetUniform->type == GL_BOOL_VEC2)
    684     {
    685         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    686 
    687         for (int i = 0; i < count; i++)
    688         {
    689             boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
    690             boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
    691             boolParams[2] = GL_FALSE;
    692             boolParams[3] = GL_FALSE;
    693             boolParams += 4;
    694             v += 2;
    695         }
    696     }
    697     else
    698     {
    699         return false;
    700     }
    701 
    702     return true;
    703 }
    704 
    705 bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
    706 {
    707     if (location < 0 || location >= (int)mUniformIndex.size())
    708     {
    709         return false;
    710     }
    711 
    712     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    713     targetUniform->dirty = true;
    714 
    715     int elementCount = targetUniform->elementCount();
    716 
    717     if (elementCount == 1 && count > 1)
    718         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    719 
    720     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    721 
    722     if (targetUniform->type == GL_INT_VEC3)
    723     {
    724         GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    725 
    726         for (int i = 0; i < count; i++)
    727         {
    728             target[0] = v[0];
    729             target[1] = v[1];
    730             target[2] = v[2];
    731             target[3] = 0;
    732             target += 4;
    733             v += 3;
    734         }
    735     }
    736     else if (targetUniform->type == GL_BOOL_VEC3)
    737     {
    738         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    739 
    740         for (int i = 0; i < count; i++)
    741         {
    742             boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
    743             boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
    744             boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE;
    745             boolParams[3] = GL_FALSE;
    746             boolParams += 4;
    747             v += 3;
    748         }
    749     }
    750     else
    751     {
    752         return false;
    753     }
    754 
    755     return true;
    756 }
    757 
    758 bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
    759 {
    760     if (location < 0 || location >= (int)mUniformIndex.size())
    761     {
    762         return false;
    763     }
    764 
    765     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    766     targetUniform->dirty = true;
    767 
    768     int elementCount = targetUniform->elementCount();
    769 
    770     if (elementCount == 1 && count > 1)
    771         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    772 
    773     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
    774 
    775     if (targetUniform->type == GL_INT_VEC4)
    776     {
    777         GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    778 
    779         for (int i = 0; i < count; i++)
    780         {
    781             target[0] = v[0];
    782             target[1] = v[1];
    783             target[2] = v[2];
    784             target[3] = v[3];
    785             target += 4;
    786             v += 4;
    787         }
    788     }
    789     else if (targetUniform->type == GL_BOOL_VEC4)
    790     {
    791         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    792 
    793         for (int i = 0; i < count; i++)
    794         {
    795             boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
    796             boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
    797             boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE;
    798             boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE;
    799             boolParams += 4;
    800             v += 4;
    801         }
    802     }
    803     else
    804     {
    805         return false;
    806     }
    807 
    808     return true;
    809 }
    810 
    811 bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
    812 {
    813     if (location < 0 || location >= (int)mUniformIndex.size())
    814     {
    815         return false;
    816     }
    817 
    818     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    819 
    820     // sized queries -- ensure the provided buffer is large enough
    821     if (bufSize)
    822     {
    823         int requiredBytes = UniformExternalSize(targetUniform->type);
    824         if (*bufSize < requiredBytes)
    825         {
    826             return false;
    827         }
    828     }
    829 
    830     switch (targetUniform->type)
    831     {
    832       case GL_FLOAT_MAT2:
    833         transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
    834         break;
    835       case GL_FLOAT_MAT3:
    836         transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
    837         break;
    838       case GL_FLOAT_MAT4:
    839         transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
    840         break;
    841       default:
    842         {
    843             unsigned int size = UniformComponentCount(targetUniform->type);
    844 
    845             switch (UniformComponentType(targetUniform->type))
    846             {
    847               case GL_BOOL:
    848                 {
    849                     GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    850 
    851                     for (unsigned int i = 0; i < size; i++)
    852                     {
    853                         params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
    854                     }
    855                 }
    856                 break;
    857               case GL_FLOAT:
    858                 memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat),
    859                        size * sizeof(GLfloat));
    860                 break;
    861               case GL_INT:
    862                 {
    863                     GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    864 
    865                     for (unsigned int i = 0; i < size; i++)
    866                     {
    867                         params[i] = (float)intParams[i];
    868                     }
    869                 }
    870                 break;
    871               default: UNREACHABLE();
    872             }
    873         }
    874     }
    875 
    876     return true;
    877 }
    878 
    879 bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
    880 {
    881     if (location < 0 || location >= (int)mUniformIndex.size())
    882     {
    883         return false;
    884     }
    885 
    886     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    887 
    888     // sized queries -- ensure the provided buffer is large enough
    889     if (bufSize)
    890     {
    891         int requiredBytes = UniformExternalSize(targetUniform->type);
    892         if (*bufSize < requiredBytes)
    893         {
    894             return false;
    895         }
    896     }
    897 
    898     switch (targetUniform->type)
    899     {
    900       case GL_FLOAT_MAT2:
    901         transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
    902         break;
    903       case GL_FLOAT_MAT3:
    904         transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
    905         break;
    906       case GL_FLOAT_MAT4:
    907         transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
    908         break;
    909       default:
    910         {
    911             unsigned int size = VariableColumnCount(targetUniform->type);
    912 
    913             switch (UniformComponentType(targetUniform->type))
    914             {
    915               case GL_BOOL:
    916                 {
    917                     GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
    918 
    919                     for (unsigned int i = 0; i < size; i++)
    920                     {
    921                         params[i] = boolParams[i];
    922                     }
    923                 }
    924                 break;
    925               case GL_FLOAT:
    926                 {
    927                     GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
    928 
    929                     for (unsigned int i = 0; i < size; i++)
    930                     {
    931                         params[i] = (GLint)floatParams[i];
    932                     }
    933                 }
    934                 break;
    935               case GL_INT:
    936                 memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint),
    937                     size * sizeof(GLint));
    938                 break;
    939               default: UNREACHABLE();
    940             }
    941         }
    942     }
    943 
    944     return true;
    945 }
    946 
    947 void ProgramBinary::dirtyAllUniforms()
    948 {
    949     unsigned int numUniforms = mUniforms.size();
    950     for (unsigned int index = 0; index < numUniforms; index++)
    951     {
    952         mUniforms[index]->dirty = true;
    953     }
    954 }
    955 
    956 // Applies all the uniforms set for this program object to the renderer
    957 void ProgramBinary::applyUniforms()
    958 {
    959     // Retrieve sampler uniform values
    960     for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub)
    961     {
    962         Uniform *targetUniform = *ub;
    963 
    964         if (targetUniform->dirty)
    965         {
    966             if (targetUniform->type == GL_SAMPLER_2D ||
    967                 targetUniform->type == GL_SAMPLER_CUBE)
    968             {
    969                 int count = targetUniform->elementCount();
    970                 GLint (*v)[4] = (GLint(*)[4])targetUniform->data;
    971 
    972                 if (targetUniform->psRegisterIndex >= 0)
    973                 {
    974                     unsigned int firstIndex = targetUniform->psRegisterIndex;
    975 
    976                     for (int i = 0; i < count; i++)
    977                     {
    978                         unsigned int samplerIndex = firstIndex + i;
    979 
    980                         if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
    981                         {
    982                             ASSERT(mSamplersPS[samplerIndex].active);
    983                             mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
    984                         }
    985                     }
    986                 }
    987 
    988                 if (targetUniform->vsRegisterIndex >= 0)
    989                 {
    990                     unsigned int firstIndex = targetUniform->vsRegisterIndex;
    991 
    992                     for (int i = 0; i < count; i++)
    993                     {
    994                         unsigned int samplerIndex = firstIndex + i;
    995 
    996                         if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
    997                         {
    998                             ASSERT(mSamplersVS[samplerIndex].active);
    999                             mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
   1000                         }
   1001                     }
   1002                 }
   1003             }
   1004         }
   1005     }
   1006 
   1007     mRenderer->applyUniforms(this, &mUniforms);
   1008 }
   1009 
   1010 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
   1011 // Returns the number of used varying registers, or -1 if unsuccesful
   1012 int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader)
   1013 {
   1014     const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
   1015 
   1016     fragmentShader->resetVaryingsRegisterAssignment();
   1017 
   1018     for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
   1019     {
   1020         int n = VariableRowCount(varying->type) * varying->size;
   1021         int m = VariableColumnCount(varying->type);
   1022         bool success = false;
   1023 
   1024         if (m == 2 || m == 3 || m == 4)
   1025         {
   1026             for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
   1027             {
   1028                 bool available = true;
   1029 
   1030                 for (int y = 0; y < n && available; y++)
   1031                 {
   1032                     for (int x = 0; x < m && available; x++)
   1033                     {
   1034                         if (packing[r + y][x])
   1035                         {
   1036                             available = false;
   1037                         }
   1038                     }
   1039                 }
   1040 
   1041                 if (available)
   1042                 {
   1043                     varying->reg = r;
   1044                     varying->col = 0;
   1045 
   1046                     for (int y = 0; y < n; y++)
   1047                     {
   1048                         for (int x = 0; x < m; x++)
   1049                         {
   1050                             packing[r + y][x] = &*varying;
   1051                         }
   1052                     }
   1053 
   1054                     success = true;
   1055                 }
   1056             }
   1057 
   1058             if (!success && m == 2)
   1059             {
   1060                 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
   1061                 {
   1062                     bool available = true;
   1063 
   1064                     for (int y = 0; y < n && available; y++)
   1065                     {
   1066                         for (int x = 2; x < 4 && available; x++)
   1067                         {
   1068                             if (packing[r + y][x])
   1069                             {
   1070                                 available = false;
   1071                             }
   1072                         }
   1073                     }
   1074 
   1075                     if (available)
   1076                     {
   1077                         varying->reg = r;
   1078                         varying->col = 2;
   1079 
   1080                         for (int y = 0; y < n; y++)
   1081                         {
   1082                             for (int x = 2; x < 4; x++)
   1083                             {
   1084                                 packing[r + y][x] = &*varying;
   1085                             }
   1086                         }
   1087 
   1088                         success = true;
   1089                     }
   1090                 }
   1091             }
   1092         }
   1093         else if (m == 1)
   1094         {
   1095             int space[4] = {0};
   1096 
   1097             for (int y = 0; y < maxVaryingVectors; y++)
   1098             {
   1099                 for (int x = 0; x < 4; x++)
   1100                 {
   1101                     space[x] += packing[y][x] ? 0 : 1;
   1102                 }
   1103             }
   1104 
   1105             int column = 0;
   1106 
   1107             for (int x = 0; x < 4; x++)
   1108             {
   1109                 if (space[x] >= n && space[x] < space[column])
   1110                 {
   1111                     column = x;
   1112                 }
   1113             }
   1114 
   1115             if (space[column] >= n)
   1116             {
   1117                 for (int r = 0; r < maxVaryingVectors; r++)
   1118                 {
   1119                     if (!packing[r][column])
   1120                     {
   1121                         varying->reg = r;
   1122 
   1123                         for (int y = r; y < r + n; y++)
   1124                         {
   1125                             packing[y][column] = &*varying;
   1126                         }
   1127 
   1128                         break;
   1129                     }
   1130                 }
   1131 
   1132                 varying->col = column;
   1133 
   1134                 success = true;
   1135             }
   1136         }
   1137         else UNREACHABLE();
   1138 
   1139         if (!success)
   1140         {
   1141             infoLog.append("Could not pack varying %s", varying->name.c_str());
   1142 
   1143             return -1;
   1144         }
   1145     }
   1146 
   1147     // Return the number of used registers
   1148     int registers = 0;
   1149 
   1150     for (int r = 0; r < maxVaryingVectors; r++)
   1151     {
   1152         if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
   1153         {
   1154             registers++;
   1155         }
   1156     }
   1157 
   1158     return registers;
   1159 }
   1160 
   1161 bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4],
   1162                                  std::string& pixelHLSL, std::string& vertexHLSL,
   1163                                  FragmentShader *fragmentShader, VertexShader *vertexShader)
   1164 {
   1165     if (pixelHLSL.empty() || vertexHLSL.empty())
   1166     {
   1167         return false;
   1168     }
   1169 
   1170     bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
   1171     bool usesFragColor = fragmentShader->mUsesFragColor;
   1172     bool usesFragData = fragmentShader->mUsesFragData;
   1173     if (usesFragColor && usesFragData)
   1174     {
   1175         infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
   1176         return false;
   1177     }
   1178 
   1179     // Write the HLSL input/output declarations
   1180     const int shaderModel = mRenderer->getMajorShaderModel();
   1181     const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
   1182 
   1183     const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
   1184 
   1185     // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor
   1186     const bool broadcast = fragmentShader->mUsesFragColor;
   1187     const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
   1188 
   1189     if (registersNeeded > maxVaryingVectors)
   1190     {
   1191         infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
   1192 
   1193         return false;
   1194     }
   1195 
   1196     vertexShader->resetVaryingsRegisterAssignment();
   1197 
   1198     for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++)
   1199     {
   1200         bool matched = false;
   1201 
   1202         for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++)
   1203         {
   1204             if (output->name == input->name)
   1205             {
   1206                 if (output->type != input->type || output->size != input->size)
   1207                 {
   1208                     infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
   1209 
   1210                     return false;
   1211                 }
   1212 
   1213                 output->reg = input->reg;
   1214                 output->col = input->col;
   1215 
   1216                 matched = true;
   1217                 break;
   1218             }
   1219         }
   1220 
   1221         if (!matched)
   1222         {
   1223             infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
   1224 
   1225             return false;
   1226         }
   1227     }
   1228 
   1229     mUsesPointSize = vertexShader->mUsesPointSize;
   1230     std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
   1231     std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
   1232     std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
   1233     std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
   1234 
   1235     // special varyings that use reserved registers
   1236     int reservedRegisterIndex = registers;
   1237     std::string fragCoordSemantic;
   1238     std::string pointCoordSemantic;
   1239 
   1240     if (fragmentShader->mUsesFragCoord)
   1241     {
   1242         fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
   1243     }
   1244 
   1245     if (fragmentShader->mUsesPointCoord)
   1246     {
   1247         // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
   1248         // In DX11 we compute this in the GS.
   1249         if (shaderModel == 3)
   1250         {
   1251             pointCoordSemantic = "TEXCOORD0";
   1252         }
   1253         else if (shaderModel >= 4)
   1254         {
   1255             pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
   1256         }
   1257     }
   1258 
   1259     vertexHLSL += "struct VS_INPUT\n"
   1260                   "{\n";
   1261 
   1262     int semanticIndex = 0;
   1263     for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
   1264     {
   1265         switch (attribute->type)
   1266         {
   1267           case GL_FLOAT:      vertexHLSL += "    float ";    break;
   1268           case GL_FLOAT_VEC2: vertexHLSL += "    float2 ";   break;
   1269           case GL_FLOAT_VEC3: vertexHLSL += "    float3 ";   break;
   1270           case GL_FLOAT_VEC4: vertexHLSL += "    float4 ";   break;
   1271           case GL_FLOAT_MAT2: vertexHLSL += "    float2x2 "; break;
   1272           case GL_FLOAT_MAT3: vertexHLSL += "    float3x3 "; break;
   1273           case GL_FLOAT_MAT4: vertexHLSL += "    float4x4 "; break;
   1274           default:  UNREACHABLE();
   1275         }
   1276 
   1277         vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
   1278 
   1279         semanticIndex += VariableRowCount(attribute->type);
   1280     }
   1281 
   1282     vertexHLSL += "};\n"
   1283                   "\n"
   1284                   "struct VS_OUTPUT\n"
   1285                   "{\n";
   1286 
   1287     if (shaderModel < 4)
   1288     {
   1289         vertexHLSL += "    float4 gl_Position : " + positionSemantic + ";\n";
   1290     }
   1291 
   1292     for (int r = 0; r < registers; r++)
   1293     {
   1294         int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
   1295 
   1296         vertexHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
   1297     }
   1298 
   1299     if (fragmentShader->mUsesFragCoord)
   1300     {
   1301         vertexHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
   1302     }
   1303 
   1304     if (vertexShader->mUsesPointSize && shaderModel >= 3)
   1305     {
   1306         vertexHLSL += "    float gl_PointSize : PSIZE;\n";
   1307     }
   1308 
   1309     if (shaderModel >= 4)
   1310     {
   1311         vertexHLSL += "    float4 gl_Position : " + positionSemantic + ";\n";
   1312     }
   1313 
   1314     vertexHLSL += "};\n"
   1315                   "\n"
   1316                   "VS_OUTPUT main(VS_INPUT input)\n"
   1317                   "{\n";
   1318 
   1319     for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
   1320     {
   1321         vertexHLSL += "    " + decorateAttribute(attribute->name) + " = ";
   1322 
   1323         if (VariableRowCount(attribute->type) > 1)   // Matrix
   1324         {
   1325             vertexHLSL += "transpose";
   1326         }
   1327 
   1328         vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
   1329     }
   1330 
   1331     if (shaderModel >= 4)
   1332     {
   1333         vertexHLSL += "\n"
   1334                       "    gl_main();\n"
   1335                       "\n"
   1336                       "    VS_OUTPUT output;\n"
   1337                       "    output.gl_Position.x = gl_Position.x;\n"
   1338                       "    output.gl_Position.y = -gl_Position.y;\n"
   1339                       "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
   1340                       "    output.gl_Position.w = gl_Position.w;\n";
   1341     }
   1342     else
   1343     {
   1344         vertexHLSL += "\n"
   1345                       "    gl_main();\n"
   1346                       "\n"
   1347                       "    VS_OUTPUT output;\n"
   1348                       "    output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
   1349                       "    output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
   1350                       "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
   1351                       "    output.gl_Position.w = gl_Position.w;\n";
   1352     }
   1353 
   1354     if (vertexShader->mUsesPointSize && shaderModel >= 3)
   1355     {
   1356         vertexHLSL += "    output.gl_PointSize = gl_PointSize;\n";
   1357     }
   1358 
   1359     if (fragmentShader->mUsesFragCoord)
   1360     {
   1361         vertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
   1362     }
   1363 
   1364     for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++)
   1365     {
   1366         if (varying->reg >= 0)
   1367         {
   1368             for (int i = 0; i < varying->size; i++)
   1369             {
   1370                 int rows = VariableRowCount(varying->type);
   1371 
   1372                 for (int j = 0; j < rows; j++)
   1373                 {
   1374                     int r = varying->reg + i * rows + j;
   1375                     vertexHLSL += "    output.v" + str(r);
   1376 
   1377                     bool sharedRegister = false;   // Register used by multiple varyings
   1378 
   1379                     for (int x = 0; x < 4; x++)
   1380                     {
   1381                         if (packing[r][x] && packing[r][x] != packing[r][0])
   1382                         {
   1383                             sharedRegister = true;
   1384                             break;
   1385                         }
   1386                     }
   1387 
   1388                     if(sharedRegister)
   1389                     {
   1390                         vertexHLSL += ".";
   1391 
   1392                         for (int x = 0; x < 4; x++)
   1393                         {
   1394                             if (packing[r][x] == &*varying)
   1395                             {
   1396                                 switch(x)
   1397                                 {
   1398                                   case 0: vertexHLSL += "x"; break;
   1399                                   case 1: vertexHLSL += "y"; break;
   1400                                   case 2: vertexHLSL += "z"; break;
   1401                                   case 3: vertexHLSL += "w"; break;
   1402                                 }
   1403                             }
   1404                         }
   1405                     }
   1406 
   1407                     vertexHLSL += " = " + varying->name;
   1408 
   1409                     if (varying->array)
   1410                     {
   1411                         vertexHLSL += "[" + str(i) + "]";
   1412                     }
   1413 
   1414                     if (rows > 1)
   1415                     {
   1416                         vertexHLSL += "[" + str(j) + "]";
   1417                     }
   1418 
   1419                     vertexHLSL += ";\n";
   1420                 }
   1421             }
   1422         }
   1423     }
   1424 
   1425     vertexHLSL += "\n"
   1426                   "    return output;\n"
   1427                   "}\n";
   1428 
   1429     pixelHLSL += "struct PS_INPUT\n"
   1430                  "{\n";
   1431 
   1432     for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
   1433     {
   1434         if (varying->reg >= 0)
   1435         {
   1436             for (int i = 0; i < varying->size; i++)
   1437             {
   1438                 int rows = VariableRowCount(varying->type);
   1439                 for (int j = 0; j < rows; j++)
   1440                 {
   1441                     std::string n = str(varying->reg + i * rows + j);
   1442                     pixelHLSL += "    float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n";
   1443                 }
   1444             }
   1445         }
   1446         else UNREACHABLE();
   1447     }
   1448 
   1449     if (fragmentShader->mUsesFragCoord)
   1450     {
   1451         pixelHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
   1452     }
   1453 
   1454     if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
   1455     {
   1456         pixelHLSL += "    float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
   1457     }
   1458 
   1459     // Must consume the PSIZE element if the geometry shader is not active
   1460     // We won't know if we use a GS until we draw
   1461     if (vertexShader->mUsesPointSize && shaderModel >= 4)
   1462     {
   1463         pixelHLSL += "    float gl_PointSize : PSIZE;\n";
   1464     }
   1465 
   1466     if (fragmentShader->mUsesFragCoord)
   1467     {
   1468         if (shaderModel >= 4)
   1469         {
   1470             pixelHLSL += "    float4 dx_VPos : SV_Position;\n";
   1471         }
   1472         else if (shaderModel >= 3)
   1473         {
   1474             pixelHLSL += "    float2 dx_VPos : VPOS;\n";
   1475         }
   1476     }
   1477 
   1478     pixelHLSL += "};\n"
   1479                  "\n"
   1480                  "struct PS_OUTPUT\n"
   1481                  "{\n";
   1482 
   1483     for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
   1484     {
   1485         pixelHLSL += "    float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
   1486     }
   1487 
   1488     if (fragmentShader->mUsesFragDepth)
   1489     {
   1490         pixelHLSL += "    float gl_Depth : " + depthSemantic + ";\n";
   1491     }
   1492 
   1493     pixelHLSL += "};\n"
   1494                  "\n";
   1495 
   1496     if (fragmentShader->mUsesFrontFacing)
   1497     {
   1498         if (shaderModel >= 4)
   1499         {
   1500             pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
   1501                          "{\n";
   1502         }
   1503         else
   1504         {
   1505             pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
   1506                          "{\n";
   1507         }
   1508     }
   1509     else
   1510     {
   1511         pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
   1512                      "{\n";
   1513     }
   1514 
   1515     if (fragmentShader->mUsesFragCoord)
   1516     {
   1517         pixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
   1518 
   1519         if (shaderModel >= 4)
   1520         {
   1521             pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x;\n"
   1522                          "    gl_FragCoord.y = input.dx_VPos.y;\n";
   1523         }
   1524         else if (shaderModel >= 3)
   1525         {
   1526             pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
   1527                          "    gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
   1528         }
   1529         else
   1530         {
   1531             // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
   1532             pixelHLSL += "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
   1533                          "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
   1534         }
   1535 
   1536         pixelHLSL += "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
   1537                      "    gl_FragCoord.w = rhw;\n";
   1538     }
   1539 
   1540     if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
   1541     {
   1542         pixelHLSL += "    gl_PointCoord.x = input.gl_PointCoord.x;\n";
   1543         pixelHLSL += "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
   1544     }
   1545 
   1546     if (fragmentShader->mUsesFrontFacing)
   1547     {
   1548         if (shaderModel <= 3)
   1549         {
   1550             pixelHLSL += "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
   1551         }
   1552         else
   1553         {
   1554             pixelHLSL += "    gl_FrontFacing = isFrontFace;\n";
   1555         }
   1556     }
   1557 
   1558     for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
   1559     {
   1560         if (varying->reg >= 0)
   1561         {
   1562             for (int i = 0; i < varying->size; i++)
   1563             {
   1564                 int rows = VariableRowCount(varying->type);
   1565                 for (int j = 0; j < rows; j++)
   1566                 {
   1567                     std::string n = str(varying->reg + i * rows + j);
   1568                     pixelHLSL += "    " + varying->name;
   1569 
   1570                     if (varying->array)
   1571                     {
   1572                         pixelHLSL += "[" + str(i) + "]";
   1573                     }
   1574 
   1575                     if (rows > 1)
   1576                     {
   1577                         pixelHLSL += "[" + str(j) + "]";
   1578                     }
   1579 
   1580                     switch (VariableColumnCount(varying->type))
   1581                     {
   1582                       case 1: pixelHLSL += " = input.v" + n + ".x;\n";   break;
   1583                       case 2: pixelHLSL += " = input.v" + n + ".xy;\n";  break;
   1584                       case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
   1585                       case 4: pixelHLSL += " = input.v" + n + ";\n";     break;
   1586                       default: UNREACHABLE();
   1587                     }
   1588                 }
   1589             }
   1590         }
   1591         else UNREACHABLE();
   1592     }
   1593 
   1594     pixelHLSL += "\n"
   1595                  "    gl_main();\n"
   1596                  "\n"
   1597                  "    PS_OUTPUT output;\n";
   1598 
   1599     for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
   1600     {
   1601         unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
   1602 
   1603         pixelHLSL += "    output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
   1604     }
   1605 
   1606     if (fragmentShader->mUsesFragDepth)
   1607     {
   1608         pixelHLSL += "    output.gl_Depth = gl_Depth;\n";
   1609     }
   1610 
   1611     pixelHLSL += "\n"
   1612                  "    return output;\n"
   1613                  "}\n";
   1614 
   1615     return true;
   1616 }
   1617 
   1618 bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
   1619 {
   1620     BinaryInputStream stream(binary, length);
   1621 
   1622     int format = 0;
   1623     stream.read(&format);
   1624     if (format != GL_PROGRAM_BINARY_ANGLE)
   1625     {
   1626         infoLog.append("Invalid program binary format.");
   1627         return false;
   1628     }
   1629 
   1630     int version = 0;
   1631     stream.read(&version);
   1632     if (version != VERSION_DWORD)
   1633     {
   1634         infoLog.append("Invalid program binary version.");
   1635         return false;
   1636     }
   1637 
   1638     int compileFlags = 0;
   1639     stream.read(&compileFlags);
   1640     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
   1641     {
   1642         infoLog.append("Mismatched compilation flags.");
   1643         return false;
   1644     }
   1645 
   1646     for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
   1647     {
   1648         stream.read(&mLinkedAttribute[i].type);
   1649         std::string name;
   1650         stream.read(&name);
   1651         mLinkedAttribute[i].name = name;
   1652         stream.read(&mSemanticIndex[i]);
   1653     }
   1654 
   1655     initAttributesByLayout();
   1656 
   1657     for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
   1658     {
   1659         stream.read(&mSamplersPS[i].active);
   1660         stream.read(&mSamplersPS[i].logicalTextureUnit);
   1661 
   1662         int textureType;
   1663         stream.read(&textureType);
   1664         mSamplersPS[i].textureType = (TextureType) textureType;
   1665     }
   1666 
   1667     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
   1668     {
   1669         stream.read(&mSamplersVS[i].active);
   1670         stream.read(&mSamplersVS[i].logicalTextureUnit);
   1671 
   1672         int textureType;
   1673         stream.read(&textureType);
   1674         mSamplersVS[i].textureType = (TextureType) textureType;
   1675     }
   1676 
   1677     stream.read(&mUsedVertexSamplerRange);
   1678     stream.read(&mUsedPixelSamplerRange);
   1679     stream.read(&mUsesPointSize);
   1680 
   1681     size_t size;
   1682     stream.read(&size);
   1683     if (stream.error())
   1684     {
   1685         infoLog.append("Invalid program binary.");
   1686         return false;
   1687     }
   1688 
   1689     mUniforms.resize(size);
   1690     for (unsigned int i = 0; i < size; ++i)
   1691     {
   1692         GLenum type;
   1693         GLenum precision;
   1694         std::string name;
   1695         unsigned int arraySize;
   1696 
   1697         stream.read(&type);
   1698         stream.read(&precision);
   1699         stream.read(&name);
   1700         stream.read(&arraySize);
   1701 
   1702         mUniforms[i] = new Uniform(type, precision, name, arraySize);
   1703 
   1704         stream.read(&mUniforms[i]->psRegisterIndex);
   1705         stream.read(&mUniforms[i]->vsRegisterIndex);
   1706         stream.read(&mUniforms[i]->registerCount);
   1707     }
   1708 
   1709     stream.read(&size);
   1710     if (stream.error())
   1711     {
   1712         infoLog.append("Invalid program binary.");
   1713         return false;
   1714     }
   1715 
   1716     mUniformIndex.resize(size);
   1717     for (unsigned int i = 0; i < size; ++i)
   1718     {
   1719         stream.read(&mUniformIndex[i].name);
   1720         stream.read(&mUniformIndex[i].element);
   1721         stream.read(&mUniformIndex[i].index);
   1722     }
   1723 
   1724     unsigned int pixelShaderSize;
   1725     stream.read(&pixelShaderSize);
   1726 
   1727     unsigned int vertexShaderSize;
   1728     stream.read(&vertexShaderSize);
   1729 
   1730     unsigned int geometryShaderSize;
   1731     stream.read(&geometryShaderSize);
   1732 
   1733     const char *ptr = (const char*) binary + stream.offset();
   1734 
   1735     const GUID *binaryIdentifier = (const GUID *) ptr;
   1736     ptr += sizeof(GUID);
   1737 
   1738     GUID identifier = mRenderer->getAdapterIdentifier();
   1739     if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
   1740     {
   1741         infoLog.append("Invalid program binary.");
   1742         return false;
   1743     }
   1744 
   1745     const char *pixelShaderFunction = ptr;
   1746     ptr += pixelShaderSize;
   1747 
   1748     const char *vertexShaderFunction = ptr;
   1749     ptr += vertexShaderSize;
   1750 
   1751     const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL;
   1752     ptr += geometryShaderSize;
   1753 
   1754     mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
   1755                                                  pixelShaderSize, rx::SHADER_PIXEL);
   1756     if (!mPixelExecutable)
   1757     {
   1758         infoLog.append("Could not create pixel shader.");
   1759         return false;
   1760     }
   1761 
   1762     mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
   1763                                                   vertexShaderSize, rx::SHADER_VERTEX);
   1764     if (!mVertexExecutable)
   1765     {
   1766         infoLog.append("Could not create vertex shader.");
   1767         delete mPixelExecutable;
   1768         mPixelExecutable = NULL;
   1769         return false;
   1770     }
   1771 
   1772     if (geometryShaderFunction != NULL && geometryShaderSize > 0)
   1773     {
   1774         mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
   1775                                                         geometryShaderSize, rx::SHADER_GEOMETRY);
   1776         if (!mGeometryExecutable)
   1777         {
   1778             infoLog.append("Could not create geometry shader.");
   1779             delete mPixelExecutable;
   1780             mPixelExecutable = NULL;
   1781             delete mVertexExecutable;
   1782             mVertexExecutable = NULL;
   1783             return false;
   1784         }
   1785     }
   1786     else
   1787     {
   1788         mGeometryExecutable = NULL;
   1789     }
   1790 
   1791     return true;
   1792 }
   1793 
   1794 bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
   1795 {
   1796     BinaryOutputStream stream;
   1797 
   1798     stream.write(GL_PROGRAM_BINARY_ANGLE);
   1799     stream.write(VERSION_DWORD);
   1800     stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
   1801 
   1802     for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
   1803     {
   1804         stream.write(mLinkedAttribute[i].type);
   1805         stream.write(mLinkedAttribute[i].name);
   1806         stream.write(mSemanticIndex[i]);
   1807     }
   1808 
   1809     for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
   1810     {
   1811         stream.write(mSamplersPS[i].active);
   1812         stream.write(mSamplersPS[i].logicalTextureUnit);
   1813         stream.write((int) mSamplersPS[i].textureType);
   1814     }
   1815 
   1816     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
   1817     {
   1818         stream.write(mSamplersVS[i].active);
   1819         stream.write(mSamplersVS[i].logicalTextureUnit);
   1820         stream.write((int) mSamplersVS[i].textureType);
   1821     }
   1822 
   1823     stream.write(mUsedVertexSamplerRange);
   1824     stream.write(mUsedPixelSamplerRange);
   1825     stream.write(mUsesPointSize);
   1826 
   1827     stream.write(mUniforms.size());
   1828     for (unsigned int i = 0; i < mUniforms.size(); ++i)
   1829     {
   1830         stream.write(mUniforms[i]->type);
   1831         stream.write(mUniforms[i]->precision);
   1832         stream.write(mUniforms[i]->name);
   1833         stream.write(mUniforms[i]->arraySize);
   1834 
   1835         stream.write(mUniforms[i]->psRegisterIndex);
   1836         stream.write(mUniforms[i]->vsRegisterIndex);
   1837         stream.write(mUniforms[i]->registerCount);
   1838     }
   1839 
   1840     stream.write(mUniformIndex.size());
   1841     for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
   1842     {
   1843         stream.write(mUniformIndex[i].name);
   1844         stream.write(mUniformIndex[i].element);
   1845         stream.write(mUniformIndex[i].index);
   1846     }
   1847 
   1848     UINT pixelShaderSize = mPixelExecutable->getLength();
   1849     stream.write(pixelShaderSize);
   1850 
   1851     UINT vertexShaderSize = mVertexExecutable->getLength();
   1852     stream.write(vertexShaderSize);
   1853 
   1854     UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
   1855     stream.write(geometryShaderSize);
   1856 
   1857     GUID identifier = mRenderer->getAdapterIdentifier();
   1858 
   1859     GLsizei streamLength = stream.length();
   1860     const void *streamData = stream.data();
   1861 
   1862     GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize;
   1863     if (totalLength > bufSize)
   1864     {
   1865         if (length)
   1866         {
   1867             *length = 0;
   1868         }
   1869 
   1870         return false;
   1871     }
   1872 
   1873     if (binary)
   1874     {
   1875         char *ptr = (char*) binary;
   1876 
   1877         memcpy(ptr, streamData, streamLength);
   1878         ptr += streamLength;
   1879 
   1880         memcpy(ptr, &identifier, sizeof(GUID));
   1881         ptr += sizeof(GUID);
   1882 
   1883         memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize);
   1884         ptr += pixelShaderSize;
   1885 
   1886         memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize);
   1887         ptr += vertexShaderSize;
   1888 
   1889         if (mGeometryExecutable != NULL && geometryShaderSize > 0)
   1890         {
   1891             memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize);
   1892             ptr += geometryShaderSize;
   1893         }
   1894 
   1895         ASSERT(ptr - totalLength == binary);
   1896     }
   1897 
   1898     if (length)
   1899     {
   1900         *length = totalLength;
   1901     }
   1902 
   1903     return true;
   1904 }
   1905 
   1906 GLint ProgramBinary::getLength()
   1907 {
   1908     GLint length;
   1909     if (save(NULL, INT_MAX, &length))
   1910     {
   1911         return length;
   1912     }
   1913     else
   1914     {
   1915         return 0;
   1916     }
   1917 }
   1918 
   1919 bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
   1920 {
   1921     if (!fragmentShader || !fragmentShader->isCompiled())
   1922     {
   1923         return false;
   1924     }
   1925 
   1926     if (!vertexShader || !vertexShader->isCompiled())
   1927     {
   1928         return false;
   1929     }
   1930 
   1931     std::string pixelHLSL = fragmentShader->getHLSL();
   1932     std::string vertexHLSL = vertexShader->getHLSL();
   1933 
   1934     // Map the varyings to the register file
   1935     const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
   1936     int registers = packVaryings(infoLog, packing, fragmentShader);
   1937 
   1938     if (registers < 0)
   1939     {
   1940         return false;
   1941     }
   1942 
   1943     if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
   1944     {
   1945         return false;
   1946     }
   1947 
   1948     bool success = true;
   1949 
   1950     if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
   1951     {
   1952         success = false;
   1953     }
   1954 
   1955     if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
   1956     {
   1957         success = false;
   1958     }
   1959 
   1960     // special case for gl_DepthRange, the only built-in uniform (also a struct)
   1961     if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
   1962     {
   1963         mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
   1964         mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
   1965         mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
   1966     }
   1967 
   1968     if (success)
   1969     {
   1970         mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting));
   1971         mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting));
   1972 
   1973         if (usesGeometryShader())
   1974         {
   1975             std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
   1976             mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE);
   1977         }
   1978 
   1979         if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
   1980         {
   1981             infoLog.append("Failed to create D3D shaders.");
   1982             success = false;
   1983 
   1984             delete mVertexExecutable;
   1985             mVertexExecutable = NULL;
   1986             delete mPixelExecutable;
   1987             mPixelExecutable = NULL;
   1988             delete mGeometryExecutable;
   1989             mGeometryExecutable = NULL;
   1990         }
   1991     }
   1992 
   1993     return success;
   1994 }
   1995 
   1996 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
   1997 bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
   1998 {
   1999     unsigned int usedLocations = 0;
   2000 
   2001     // Link attributes that have a binding location
   2002     for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
   2003     {
   2004         int location = attributeBindings.getAttributeBinding(attribute->name);
   2005 
   2006         if (location != -1)   // Set by glBindAttribLocation
   2007         {
   2008             if (!mLinkedAttribute[location].name.empty())
   2009             {
   2010                 // Multiple active attributes bound to the same location; not an error
   2011             }
   2012 
   2013             mLinkedAttribute[location] = *attribute;
   2014 
   2015             int rows = VariableRowCount(attribute->type);
   2016 
   2017             if (rows + location > MAX_VERTEX_ATTRIBS)
   2018             {
   2019                 infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
   2020 
   2021                 return false;
   2022             }
   2023 
   2024             for (int i = 0; i < rows; i++)
   2025             {
   2026                 usedLocations |= 1 << (location + i);
   2027             }
   2028         }
   2029     }
   2030 
   2031     // Link attributes that don't have a binding location
   2032     for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
   2033     {
   2034         int location = attributeBindings.getAttributeBinding(attribute->name);
   2035 
   2036         if (location == -1)   // Not set by glBindAttribLocation
   2037         {
   2038             int rows = VariableRowCount(attribute->type);
   2039             int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
   2040 
   2041             if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
   2042             {
   2043                 infoLog.append("Too many active attributes (%s)", attribute->name.c_str());
   2044 
   2045                 return false;   // Fail to link
   2046             }
   2047 
   2048             mLinkedAttribute[availableIndex] = *attribute;
   2049         }
   2050     }
   2051 
   2052     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
   2053     {
   2054         int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
   2055         int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
   2056 
   2057         for (int r = 0; r < rows; r++)
   2058         {
   2059             mSemanticIndex[attributeIndex++] = index++;
   2060         }
   2061     }
   2062 
   2063     initAttributesByLayout();
   2064 
   2065     return true;
   2066 }
   2067 
   2068 bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms)
   2069 {
   2070     for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++)
   2071     {
   2072         if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog))
   2073         {
   2074             return false;
   2075         }
   2076     }
   2077 
   2078     for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++)
   2079     {
   2080         if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog))
   2081         {
   2082             return false;
   2083         }
   2084     }
   2085 
   2086     return true;
   2087 }
   2088 
   2089 bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog)
   2090 {
   2091     if (constant.type == GL_SAMPLER_2D ||
   2092         constant.type == GL_SAMPLER_CUBE)
   2093     {
   2094         unsigned int samplerIndex = constant.registerIndex;
   2095 
   2096         do
   2097         {
   2098             if (shader == GL_VERTEX_SHADER)
   2099             {
   2100                 if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits())
   2101                 {
   2102                     mSamplersVS[samplerIndex].active = true;
   2103                     mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
   2104                     mSamplersVS[samplerIndex].logicalTextureUnit = 0;
   2105                     mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
   2106                 }
   2107                 else
   2108                 {
   2109                     infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits());
   2110                     return false;
   2111                 }
   2112             }
   2113             else if (shader == GL_FRAGMENT_SHADER)
   2114             {
   2115                 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
   2116                 {
   2117                     mSamplersPS[samplerIndex].active = true;
   2118                     mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
   2119                     mSamplersPS[samplerIndex].logicalTextureUnit = 0;
   2120                     mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
   2121                 }
   2122                 else
   2123                 {
   2124                     infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
   2125                     return false;
   2126                 }
   2127             }
   2128             else UNREACHABLE();
   2129 
   2130             samplerIndex++;
   2131         }
   2132         while (samplerIndex < constant.registerIndex + constant.arraySize);
   2133     }
   2134 
   2135     Uniform *uniform = NULL;
   2136     GLint location = getUniformLocation(constant.name);
   2137 
   2138     if (location >= 0)   // Previously defined, type and precision must match
   2139     {
   2140         uniform = mUniforms[mUniformIndex[location].index];
   2141 
   2142         if (uniform->type != constant.type)
   2143         {
   2144             infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
   2145             return false;
   2146         }
   2147 
   2148         if (uniform->precision != constant.precision)
   2149         {
   2150             infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
   2151             return false;
   2152         }
   2153     }
   2154     else
   2155     {
   2156         uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize);
   2157     }
   2158 
   2159     if (!uniform)
   2160     {
   2161         return false;
   2162     }
   2163 
   2164     if (shader == GL_FRAGMENT_SHADER)
   2165     {
   2166         uniform->psRegisterIndex = constant.registerIndex;
   2167     }
   2168     else if (shader == GL_VERTEX_SHADER)
   2169     {
   2170         uniform->vsRegisterIndex = constant.registerIndex;
   2171     }
   2172     else UNREACHABLE();
   2173 
   2174     if (location >= 0)
   2175     {
   2176         return uniform->type == constant.type;
   2177     }
   2178 
   2179     mUniforms.push_back(uniform);
   2180     unsigned int uniformIndex = mUniforms.size() - 1;
   2181 
   2182     for (unsigned int i = 0; i < uniform->elementCount(); i++)
   2183     {
   2184         mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex));
   2185     }
   2186 
   2187     if (shader == GL_VERTEX_SHADER)
   2188     {
   2189         if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
   2190         {
   2191             infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
   2192             return false;
   2193         }
   2194     }
   2195     else if (shader == GL_FRAGMENT_SHADER)
   2196     {
   2197         if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors())
   2198         {
   2199             infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
   2200             return false;
   2201         }
   2202     }
   2203     else UNREACHABLE();
   2204 
   2205     return true;
   2206 }
   2207 
   2208 std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
   2209 {
   2210     // for now we only handle point sprite emulation
   2211     ASSERT(usesPointSpriteEmulation());
   2212     return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
   2213 }
   2214 
   2215 std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
   2216 {
   2217     ASSERT(registers >= 0);
   2218     ASSERT(vertexShader->mUsesPointSize);
   2219     ASSERT(mRenderer->getMajorShaderModel() >= 4);
   2220 
   2221     std::string geomHLSL;
   2222 
   2223     std::string varyingSemantic = "TEXCOORD";
   2224 
   2225     std::string fragCoordSemantic;
   2226     std::string pointCoordSemantic;
   2227 
   2228     int reservedRegisterIndex = registers;
   2229 
   2230     if (fragmentShader->mUsesFragCoord)
   2231     {
   2232         fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
   2233     }
   2234 
   2235     if (fragmentShader->mUsesPointCoord)
   2236     {
   2237         pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
   2238     }
   2239 
   2240     geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
   2241                 "\n"
   2242                 "struct GS_INPUT\n"
   2243                 "{\n";
   2244 
   2245     for (int r = 0; r < registers; r++)
   2246     {
   2247         int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
   2248 
   2249         geomHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
   2250     }
   2251 
   2252     if (fragmentShader->mUsesFragCoord)
   2253     {
   2254         geomHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
   2255     }
   2256 
   2257     geomHLSL += "    float gl_PointSize : PSIZE;\n"
   2258                 "    float4 gl_Position : SV_Position;\n"
   2259                 "};\n"
   2260                 "\n"
   2261                 "struct GS_OUTPUT\n"
   2262                 "{\n";
   2263 
   2264     for (int r = 0; r < registers; r++)
   2265     {
   2266         int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
   2267 
   2268         geomHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
   2269     }
   2270 
   2271     if (fragmentShader->mUsesFragCoord)
   2272     {
   2273         geomHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
   2274     }
   2275 
   2276     if (fragmentShader->mUsesPointCoord)
   2277     {
   2278         geomHLSL += "    float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
   2279     }
   2280 
   2281     geomHLSL +=   "    float gl_PointSize : PSIZE;\n"
   2282                   "    float4 gl_Position : SV_Position;\n"
   2283                   "};\n"
   2284                   "\n"
   2285                   "static float2 pointSpriteCorners[] = \n"
   2286                   "{\n"
   2287                   "    float2( 0.5f, -0.5f),\n"
   2288                   "    float2( 0.5f,  0.5f),\n"
   2289                   "    float2(-0.5f, -0.5f),\n"
   2290                   "    float2(-0.5f,  0.5f)\n"
   2291                   "};\n"
   2292                   "\n"
   2293                   "static float2 pointSpriteTexcoords[] = \n"
   2294                   "{\n"
   2295                   "    float2(1.0f, 1.0f),\n"
   2296                   "    float2(1.0f, 0.0f),\n"
   2297                   "    float2(0.0f, 1.0f),\n"
   2298                   "    float2(0.0f, 0.0f)\n"
   2299                   "};\n"
   2300                   "\n"
   2301                   "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
   2302                   "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n"
   2303                   "\n"
   2304                   "[maxvertexcount(4)]\n"
   2305                   "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
   2306                   "{\n"
   2307                   "    GS_OUTPUT output = (GS_OUTPUT)0;\n"
   2308                   "    output.gl_PointSize = input[0].gl_PointSize;\n";
   2309 
   2310     for (int r = 0; r < registers; r++)
   2311     {
   2312         geomHLSL += "    output.v" + str(r) + " = input[0].v" + str(r) + ";\n";
   2313     }
   2314 
   2315     if (fragmentShader->mUsesFragCoord)
   2316     {
   2317         geomHLSL += "    output.gl_FragCoord = input[0].gl_FragCoord;\n";
   2318     }
   2319 
   2320     geomHLSL += "    \n"
   2321                 "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
   2322                 "    float4 gl_Position = input[0].gl_Position;\n"
   2323                 "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
   2324 
   2325     for (int corner = 0; corner < 4; corner++)
   2326     {
   2327         geomHLSL += "    \n"
   2328                     "    output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
   2329 
   2330         if (fragmentShader->mUsesPointCoord)
   2331         {
   2332             geomHLSL += "    output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n";
   2333         }
   2334 
   2335         geomHLSL += "    outStream.Append(output);\n";
   2336     }
   2337 
   2338     geomHLSL += "    \n"
   2339                 "    outStream.RestartStrip();\n"
   2340                 "}\n";
   2341 
   2342     return geomHLSL;
   2343 }
   2344 
   2345 // This method needs to match OutputHLSL::decorate
   2346 std::string ProgramBinary::decorateAttribute(const std::string &name)
   2347 {
   2348     if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
   2349     {
   2350         return "_" + name;
   2351     }
   2352 
   2353     return name;
   2354 }
   2355 
   2356 bool ProgramBinary::isValidated() const
   2357 {
   2358     return mValidated;
   2359 }
   2360 
   2361 void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
   2362 {
   2363     // Skip over inactive attributes
   2364     unsigned int activeAttribute = 0;
   2365     unsigned int attribute;
   2366     for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
   2367     {
   2368         if (mLinkedAttribute[attribute].name.empty())
   2369         {
   2370             continue;
   2371         }
   2372 
   2373         if (activeAttribute == index)
   2374         {
   2375             break;
   2376         }
   2377 
   2378         activeAttribute++;
   2379     }
   2380 
   2381     if (bufsize > 0)
   2382     {
   2383         const char *string = mLinkedAttribute[attribute].name.c_str();
   2384 
   2385         strncpy(name, string, bufsize);
   2386         name[bufsize - 1] = '\0';
   2387 
   2388         if (length)
   2389         {
   2390             *length = strlen(name);
   2391         }
   2392     }
   2393 
   2394     *size = 1;   // Always a single 'type' instance
   2395 
   2396     *type = mLinkedAttribute[attribute].type;
   2397 }
   2398 
   2399 GLint ProgramBinary::getActiveAttributeCount() const
   2400 {
   2401     int count = 0;
   2402 
   2403     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
   2404     {
   2405         if (!mLinkedAttribute[attributeIndex].name.empty())
   2406         {
   2407             count++;
   2408         }
   2409     }
   2410 
   2411     return count;
   2412 }
   2413 
   2414 GLint ProgramBinary::getActiveAttributeMaxLength() const
   2415 {
   2416     int maxLength = 0;
   2417 
   2418     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
   2419     {
   2420         if (!mLinkedAttribute[attributeIndex].name.empty())
   2421         {
   2422             maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
   2423         }
   2424     }
   2425 
   2426     return maxLength;
   2427 }
   2428 
   2429 void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
   2430 {
   2431     ASSERT(index < mUniforms.size());   // index must be smaller than getActiveUniformCount()
   2432 
   2433     if (bufsize > 0)
   2434     {
   2435         std::string string = mUniforms[index]->name;
   2436 
   2437         if (mUniforms[index]->isArray())
   2438         {
   2439             string += "[0]";
   2440         }
   2441 
   2442         strncpy(name, string.c_str(), bufsize);
   2443         name[bufsize - 1] = '\0';
   2444 
   2445         if (length)
   2446         {
   2447             *length = strlen(name);
   2448         }
   2449     }
   2450 
   2451     *size = mUniforms[index]->elementCount();
   2452 
   2453     *type = mUniforms[index]->type;
   2454 }
   2455 
   2456 GLint ProgramBinary::getActiveUniformCount() const
   2457 {
   2458     return mUniforms.size();
   2459 }
   2460 
   2461 GLint ProgramBinary::getActiveUniformMaxLength() const
   2462 {
   2463     int maxLength = 0;
   2464 
   2465     unsigned int numUniforms = mUniforms.size();
   2466     for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
   2467     {
   2468         if (!mUniforms[uniformIndex]->name.empty())
   2469         {
   2470             int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
   2471             if (mUniforms[uniformIndex]->isArray())
   2472             {
   2473                 length += 3;  // Counting in "[0]".
   2474             }
   2475             maxLength = std::max(length, maxLength);
   2476         }
   2477     }
   2478 
   2479     return maxLength;
   2480 }
   2481 
   2482 void ProgramBinary::validate(InfoLog &infoLog)
   2483 {
   2484     applyUniforms();
   2485     if (!validateSamplers(&infoLog))
   2486     {
   2487         mValidated = false;
   2488     }
   2489     else
   2490     {
   2491         mValidated = true;
   2492     }
   2493 }
   2494 
   2495 bool ProgramBinary::validateSamplers(InfoLog *infoLog)
   2496 {
   2497     // if any two active samplers in a program are of different types, but refer to the same
   2498     // texture image unit, and this is the current program, then ValidateProgram will fail, and
   2499     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
   2500 
   2501     const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
   2502     TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
   2503 
   2504     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i)
   2505     {
   2506         textureUnitType[i] = TEXTURE_UNKNOWN;
   2507     }
   2508 
   2509     for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
   2510     {
   2511         if (mSamplersPS[i].active)
   2512         {
   2513             unsigned int unit = mSamplersPS[i].logicalTextureUnit;
   2514 
   2515             if (unit >= maxCombinedTextureImageUnits)
   2516             {
   2517                 if (infoLog)
   2518                 {
   2519                     infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
   2520                 }
   2521 
   2522                 return false;
   2523             }
   2524 
   2525             if (textureUnitType[unit] != TEXTURE_UNKNOWN)
   2526             {
   2527                 if (mSamplersPS[i].textureType != textureUnitType[unit])
   2528                 {
   2529                     if (infoLog)
   2530                     {
   2531                         infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
   2532                     }
   2533 
   2534                     return false;
   2535                 }
   2536             }
   2537             else
   2538             {
   2539                 textureUnitType[unit] = mSamplersPS[i].textureType;
   2540             }
   2541         }
   2542     }
   2543 
   2544     for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
   2545     {
   2546         if (mSamplersVS[i].active)
   2547         {
   2548             unsigned int unit = mSamplersVS[i].logicalTextureUnit;
   2549 
   2550             if (unit >= maxCombinedTextureImageUnits)
   2551             {
   2552                 if (infoLog)
   2553                 {
   2554                     infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
   2555                 }
   2556 
   2557                 return false;
   2558             }
   2559 
   2560             if (textureUnitType[unit] != TEXTURE_UNKNOWN)
   2561             {
   2562                 if (mSamplersVS[i].textureType != textureUnitType[unit])
   2563                 {
   2564                     if (infoLog)
   2565                     {
   2566                         infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
   2567                     }
   2568 
   2569                     return false;
   2570                 }
   2571             }
   2572             else
   2573             {
   2574                 textureUnitType[unit] = mSamplersVS[i].textureType;
   2575             }
   2576         }
   2577     }
   2578 
   2579     return true;
   2580 }
   2581 
   2582 ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
   2583 {
   2584 }
   2585 
   2586 struct AttributeSorter
   2587 {
   2588     AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
   2589         : originalIndices(semanticIndices)
   2590     {
   2591     }
   2592 
   2593     bool operator()(int a, int b)
   2594     {
   2595         return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b];
   2596     }
   2597 
   2598     const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
   2599 };
   2600 
   2601 void ProgramBinary::initAttributesByLayout()
   2602 {
   2603     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
   2604     {
   2605         mAttributesByLayout[i] = i;
   2606     }
   2607 
   2608     std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
   2609 }
   2610 
   2611 void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
   2612 {
   2613     rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
   2614 
   2615     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
   2616     {
   2617         oldTranslatedAttributes[i] = attributes[i];
   2618     }
   2619 
   2620     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
   2621     {
   2622         int oldIndex = mAttributesByLayout[i];
   2623         sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
   2624         attributes[i] = oldTranslatedAttributes[oldIndex];
   2625     }
   2626 }
   2627 
   2628 }
   2629