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