Home | History | Annotate | Download | only in d3d
      1 //
      2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 // DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
      7 //
      8 
      9 #include "libGLESv2/renderer/d3d/DynamicHLSL.h"
     10 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
     11 #include "libGLESv2/renderer/Renderer.h"
     12 #include "libGLESv2/Shader.h"
     13 #include "libGLESv2/Program.h"
     14 #include "libGLESv2/ProgramBinary.h"
     15 #include "libGLESv2/formatutils.h"
     16 
     17 #include "common/utilities.h"
     18 #include "common/blocklayout.h"
     19 
     20 // For use with ArrayString, see angleutils.h
     21 META_ASSERT(GL_INVALID_INDEX == UINT_MAX);
     22 
     23 using namespace gl;
     24 
     25 namespace
     26 {
     27 
     28 std::string HLSLComponentTypeString(GLenum componentType)
     29 {
     30     switch (componentType)
     31     {
     32       case GL_UNSIGNED_INT:         return "uint";
     33       case GL_INT:                  return "int";
     34       case GL_UNSIGNED_NORMALIZED:
     35       case GL_SIGNED_NORMALIZED:
     36       case GL_FLOAT:                return "float";
     37       default: UNREACHABLE();       return "not-component-type";
     38     }
     39 }
     40 
     41 std::string HLSLComponentTypeString(GLenum componentType, int componentCount)
     42 {
     43     return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : "");
     44 }
     45 
     46 std::string HLSLMatrixTypeString(GLenum type)
     47 {
     48     switch (type)
     49     {
     50       case GL_FLOAT_MAT2:     return "float2x2";
     51       case GL_FLOAT_MAT3:     return "float3x3";
     52       case GL_FLOAT_MAT4:     return "float4x4";
     53       case GL_FLOAT_MAT2x3:   return "float2x3";
     54       case GL_FLOAT_MAT3x2:   return "float3x2";
     55       case GL_FLOAT_MAT2x4:   return "float2x4";
     56       case GL_FLOAT_MAT4x2:   return "float4x2";
     57       case GL_FLOAT_MAT3x4:   return "float3x4";
     58       case GL_FLOAT_MAT4x3:   return "float4x3";
     59       default: UNREACHABLE(); return "not-matrix-type";
     60     }
     61 }
     62 
     63 std::string HLSLTypeString(GLenum type)
     64 {
     65     if (gl::IsMatrixType(type))
     66     {
     67         return HLSLMatrixTypeString(type);
     68     }
     69 
     70     return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type));
     71 }
     72 
     73 const rx::PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<rx::PixelShaderOutputVariable> &outputVariables,
     74                                                         unsigned int location)
     75 {
     76     for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
     77     {
     78         if (outputVariables[variableIndex].outputIndex == location)
     79         {
     80             return outputVariables[variableIndex];
     81         }
     82     }
     83 
     84     UNREACHABLE();
     85     return outputVariables[0];
     86 }
     87 
     88 }
     89 
     90 namespace rx
     91 {
     92 
     93 const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
     94 const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
     95 
     96 DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
     97     : mRenderer(renderer)
     98 {
     99 }
    100 
    101 static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing)
    102 {
    103     GLenum transposedType = TransposeMatrixType(varying->type);
    104 
    105     // matrices within varying structs are not transposed
    106     int registers = (varying->isStruct() ? HLSLVariableRegisterCount(*varying) : VariableRowCount(transposedType)) * varying->elementCount();
    107     int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
    108 
    109     if (elements >= 2 && elements <= 4)
    110     {
    111         for (int r = 0; r <= maxVaryingVectors - registers; r++)
    112         {
    113             bool available = true;
    114 
    115             for (int y = 0; y < registers && available; y++)
    116             {
    117                 for (int x = 0; x < elements && available; x++)
    118                 {
    119                     if (packing[r + y][x])
    120                     {
    121                         available = false;
    122                     }
    123                 }
    124             }
    125 
    126             if (available)
    127             {
    128                 varying->registerIndex = r;
    129                 varying->columnIndex = 0;
    130 
    131                 for (int y = 0; y < registers; y++)
    132                 {
    133                     for (int x = 0; x < elements; x++)
    134                     {
    135                         packing[r + y][x] = &*varying;
    136                     }
    137                 }
    138 
    139                 return true;
    140             }
    141         }
    142 
    143         if (elements == 2)
    144         {
    145             for (int r = maxVaryingVectors - registers; r >= 0; r--)
    146             {
    147                 bool available = true;
    148 
    149                 for (int y = 0; y < registers && available; y++)
    150                 {
    151                     for (int x = 2; x < 4 && available; x++)
    152                     {
    153                         if (packing[r + y][x])
    154                         {
    155                             available = false;
    156                         }
    157                     }
    158                 }
    159 
    160                 if (available)
    161                 {
    162                     varying->registerIndex = r;
    163                     varying->columnIndex = 2;
    164 
    165                     for (int y = 0; y < registers; y++)
    166                     {
    167                         for (int x = 2; x < 4; x++)
    168                         {
    169                             packing[r + y][x] = &*varying;
    170                         }
    171                     }
    172 
    173                     return true;
    174                 }
    175             }
    176         }
    177     }
    178     else if (elements == 1)
    179     {
    180         int space[4] = { 0 };
    181 
    182         for (int y = 0; y < maxVaryingVectors; y++)
    183         {
    184             for (int x = 0; x < 4; x++)
    185             {
    186                 space[x] += packing[y][x] ? 0 : 1;
    187             }
    188         }
    189 
    190         int column = 0;
    191 
    192         for (int x = 0; x < 4; x++)
    193         {
    194             if (space[x] >= registers && (space[column] < registers || space[x] < space[column]))
    195             {
    196                 column = x;
    197             }
    198         }
    199 
    200         if (space[column] >= registers)
    201         {
    202             for (int r = 0; r < maxVaryingVectors; r++)
    203             {
    204                 if (!packing[r][column])
    205                 {
    206                     varying->registerIndex = r;
    207                     varying->columnIndex = column;
    208 
    209                     for (int y = r; y < r + registers; y++)
    210                     {
    211                         packing[y][column] = &*varying;
    212                     }
    213 
    214                     break;
    215                 }
    216             }
    217 
    218             return true;
    219         }
    220     }
    221     else UNREACHABLE();
    222 
    223     return false;
    224 }
    225 
    226 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
    227 // Returns the number of used varying registers, or -1 if unsuccesful
    228 int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader,
    229                               rx::ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings)
    230 {
    231     // TODO (geofflang):  Use context's caps
    232     const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
    233 
    234     vertexShader->resetVaryingsRegisterAssignment();
    235     fragmentShader->resetVaryingsRegisterAssignment();
    236 
    237     std::set<std::string> packedVaryings;
    238 
    239     std::vector<gl::PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
    240     std::vector<gl::PackedVarying> &vertexVaryings = vertexShader->getVaryings();
    241     for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
    242     {
    243         PackedVarying *varying = &fragmentVaryings[varyingIndex];
    244 
    245         // Do not assign registers to built-in or unreferenced varyings
    246         if (varying->isBuiltIn() || !varying->staticUse)
    247         {
    248             continue;
    249         }
    250 
    251         if (packVarying(varying, maxVaryingVectors, packing))
    252         {
    253             packedVaryings.insert(varying->name);
    254         }
    255         else
    256         {
    257             infoLog.append("Could not pack varying %s", varying->name.c_str());
    258             return -1;
    259         }
    260     }
    261 
    262     for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
    263     {
    264         const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
    265         if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
    266         {
    267             bool found = false;
    268             for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++)
    269             {
    270                 PackedVarying *varying = &vertexVaryings[varyingIndex];
    271                 if (transformFeedbackVarying == varying->name)
    272                 {
    273                     if (!packVarying(varying, maxVaryingVectors, packing))
    274                     {
    275                         infoLog.append("Could not pack varying %s", varying->name.c_str());
    276                         return -1;
    277                     }
    278 
    279                     found = true;
    280                     break;
    281                 }
    282             }
    283 
    284             if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize")
    285             {
    286                 infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str());
    287                 return -1;
    288             }
    289         }
    290     }
    291 
    292     // Return the number of used registers
    293     int registers = 0;
    294 
    295     for (int r = 0; r < maxVaryingVectors; r++)
    296     {
    297         if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
    298         {
    299             registers++;
    300         }
    301     }
    302 
    303     return registers;
    304 }
    305 
    306 std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
    307 {
    308     std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize);
    309     std::string varyingHLSL;
    310 
    311     const std::vector<gl::PackedVarying> &varyings = shader->getVaryings();
    312 
    313     for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++)
    314     {
    315         const PackedVarying &varying = varyings[varyingIndex];
    316         if (varying.registerAssigned())
    317         {
    318             ASSERT(!varying.isBuiltIn());
    319             GLenum transposedType = TransposeMatrixType(varying.type);
    320             int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
    321 
    322             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
    323             {
    324                 for (int row = 0; row < variableRows; row++)
    325                 {
    326                     // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many registers being used.
    327                     // For example, if there are N registers, and we have N vec3 varyings and 1 float varying, then D3D will pack them into N registers.
    328                     // If the float varying has the 'nointerpolation' modifier on it then we would need N + 1 registers, and D3D compilation will fail.
    329 
    330                     switch (varying.interpolation)
    331                     {
    332                       case sh::INTERPOLATION_SMOOTH:   varyingHLSL += "    ";                 break;
    333                       case sh::INTERPOLATION_FLAT:     varyingHLSL += "    nointerpolation "; break;
    334                       case sh::INTERPOLATION_CENTROID: varyingHLSL += "    centroid ";        break;
    335                       default:  UNREACHABLE();
    336                     }
    337 
    338                     unsigned int semanticIndex = elementIndex * variableRows + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + varying.registerIndex + row;
    339                     std::string n = Str(semanticIndex);
    340 
    341                     std::string typeString;
    342 
    343                     if (varying.isStruct())
    344                     {
    345                         // matrices within structs are not transposed, so
    346                         // do not use the special struct prefix "rm"
    347                         typeString = decorateVariable(varying.structName);
    348                     }
    349                     else
    350                     {
    351                         GLenum componentType = VariableComponentType(transposedType);
    352                         int columnCount = VariableColumnCount(transposedType);
    353                         typeString = HLSLComponentTypeString(componentType, columnCount);
    354                     }
    355                     varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
    356                 }
    357             }
    358         }
    359     }
    360 
    361     return varyingHLSL;
    362 }
    363 
    364 std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader,
    365                                                             const VertexFormat inputLayout[],
    366                                                             const sh::Attribute shaderAttributes[]) const
    367 {
    368     std::string structHLSL, initHLSL;
    369 
    370     int semanticIndex = 0;
    371     unsigned int inputIndex = 0;
    372 
    373     for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
    374     {
    375         const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
    376         if (!shaderAttribute.name.empty())
    377         {
    378             ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
    379             const VertexFormat &vertexFormat = inputLayout[inputIndex];
    380 
    381             // HLSL code for input structure
    382             if (IsMatrixType(shaderAttribute.type))
    383             {
    384                 // Matrix types are always transposed
    385                 structHLSL += "    " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
    386             }
    387             else
    388             {
    389                 GLenum componentType = mRenderer->getVertexComponentType(vertexFormat);
    390                 structHLSL += "    " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type));
    391             }
    392 
    393             structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n";
    394             semanticIndex += VariableRegisterCount(shaderAttribute.type);
    395 
    396             // HLSL code for initialization
    397             initHLSL += "    " + decorateVariable(shaderAttribute.name) + " = ";
    398 
    399             // Mismatched vertex attribute to vertex input may result in an undefined
    400             // data reinterpretation (eg for pure integer->float, float->pure integer)
    401             // TODO: issue warning with gl debug info extension, when supported
    402             if (IsMatrixType(shaderAttribute.type) ||
    403                 (mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0)
    404             {
    405                 initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute);
    406             }
    407             else
    408             {
    409                 initHLSL += "input." + decorateVariable(shaderAttribute.name);
    410             }
    411 
    412             initHLSL += ";\n";
    413 
    414             inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
    415         }
    416     }
    417 
    418     std::string replacementHLSL = "struct VS_INPUT\n"
    419                                   "{\n" +
    420                                   structHLSL +
    421                                   "};\n"
    422                                   "\n"
    423                                   "void initAttributes(VS_INPUT input)\n"
    424                                   "{\n" +
    425                                   initHLSL +
    426                                   "}\n";
    427 
    428     std::string vertexHLSL(sourceShader);
    429 
    430     size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
    431     vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL);
    432 
    433     return vertexHLSL;
    434 }
    435 
    436 std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
    437                                                                bool usesFragDepth, const std::vector<GLenum> &outputLayout) const
    438 {
    439     const int shaderModel = mRenderer->getMajorShaderModel();
    440     std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
    441     std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
    442 
    443     std::string declarationHLSL;
    444     std::string copyHLSL;
    445 
    446     for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex)
    447     {
    448         GLenum binding = outputLayout[layoutIndex];
    449 
    450         if (binding != GL_NONE)
    451         {
    452             unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
    453 
    454             const PixelShaderOutputVariable &outputVariable = GetOutputAtLocation(outputVariables, location);
    455 
    456             declarationHLSL += "    " + HLSLTypeString(outputVariable.type) + " " + outputVariable.name +
    457                                " : " + targetSemantic + Str(layoutIndex) + ";\n";
    458 
    459             copyHLSL += "    output." + outputVariable.name + " = " + outputVariable.source + ";\n";
    460         }
    461     }
    462 
    463     if (usesFragDepth)
    464     {
    465         declarationHLSL += "    float gl_Depth : " + depthSemantic + ";\n";
    466         copyHLSL += "    output.gl_Depth = gl_Depth; \n";
    467     }
    468 
    469     std::string replacementHLSL = "struct PS_OUTPUT\n"
    470                                   "{\n" +
    471                                   declarationHLSL +
    472                                   "};\n"
    473                                   "\n"
    474                                   "PS_OUTPUT generateOutput()\n"
    475                                   "{\n"
    476                                   "    PS_OUTPUT output;\n" +
    477                                   copyHLSL +
    478                                   "    return output;\n"
    479                                   "}\n";
    480 
    481     std::string pixelHLSL(sourceShader);
    482 
    483     size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
    484     pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL);
    485 
    486     return pixelHLSL;
    487 }
    488 
    489 std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const
    490 {
    491     // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
    492     // In D3D11 we manually compute gl_PointCoord in the GS.
    493     int shaderModel = mRenderer->getMajorShaderModel();
    494     return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD");
    495 }
    496 
    497 struct DynamicHLSL::SemanticInfo
    498 {
    499     struct BuiltinInfo
    500     {
    501         BuiltinInfo()
    502             : enabled(false),
    503               index(0),
    504               systemValue(false)
    505         {}
    506 
    507         bool enabled;
    508         std::string semantic;
    509         unsigned int index;
    510         bool systemValue;
    511 
    512         std::string str() const
    513         {
    514             return (systemValue ? semantic : (semantic + Str(index)));
    515         }
    516 
    517         void enableSystem(const std::string &systemValueSemantic)
    518         {
    519             enabled = true;
    520             semantic = systemValueSemantic;
    521             systemValue = true;
    522         }
    523 
    524         void enable(const std::string &semanticVal, unsigned int indexVal)
    525         {
    526             enabled = true;
    527             semantic = semanticVal;
    528             index = indexVal;
    529         }
    530     };
    531 
    532     BuiltinInfo dxPosition;
    533     BuiltinInfo glPosition;
    534     BuiltinInfo glFragCoord;
    535     BuiltinInfo glPointCoord;
    536     BuiltinInfo glPointSize;
    537 };
    538 
    539 DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord,
    540                                                        bool pointSize, bool pixelShader) const
    541 {
    542     SemanticInfo info;
    543     bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4);
    544     const std::string &varyingSemantic = getVaryingSemantic(pointSize);
    545 
    546     int reservedRegisterIndex = startRegisters;
    547 
    548     if (hlsl4)
    549     {
    550         info.dxPosition.enableSystem("SV_Position");
    551     }
    552     else if (pixelShader)
    553     {
    554         info.dxPosition.enableSystem("VPOS");
    555     }
    556     else
    557     {
    558         info.dxPosition.enableSystem("POSITION");
    559     }
    560 
    561     info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
    562 
    563     if (fragCoord)
    564     {
    565         info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++);
    566     }
    567 
    568     if (pointCoord)
    569     {
    570         // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
    571         // In D3D11 we manually compute gl_PointCoord in the GS.
    572         if (hlsl4)
    573         {
    574             info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++);
    575         }
    576         else
    577         {
    578             info.glPointCoord.enable("TEXCOORD", 0);
    579         }
    580     }
    581 
    582     // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
    583     if (pointSize && (!pixelShader || hlsl4))
    584     {
    585         info.glPointSize.enableSystem("PSIZE");
    586     }
    587 
    588     return info;
    589 }
    590 
    591 std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const
    592 {
    593     std::string linkHLSL = "{\n";
    594 
    595     ASSERT(info.dxPosition.enabled && info.glPosition.enabled);
    596 
    597     linkHLSL += "    float4 dx_Position : " + info.dxPosition.str() + ";\n";
    598     linkHLSL += "    float4 gl_Position : " + info.glPosition.str() + ";\n";
    599 
    600     if (info.glFragCoord.enabled)
    601     {
    602         linkHLSL += "    float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n";
    603     }
    604 
    605     if (info.glPointCoord.enabled)
    606     {
    607         linkHLSL += "    float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n";
    608     }
    609 
    610     linkHLSL += varyingHLSL;
    611 
    612     if (info.glPointSize.enabled)
    613     {
    614         linkHLSL += "    float gl_PointSize : " + info.glPointSize.str() + ";\n";
    615     }
    616 
    617     linkHLSL += "};\n";
    618 
    619     return linkHLSL;
    620 }
    621 
    622 void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info,
    623                                              std::vector<LinkedVarying> *linkedVaryings) const
    624 {
    625     ASSERT(info.glPosition.enabled);
    626 
    627     linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic,
    628                                             info.glPosition.index, 1));
    629 
    630     if (info.glFragCoord.enabled)
    631     {
    632         linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic,
    633                                                 info.glFragCoord.index, 1));
    634     }
    635 
    636     if (info.glPointSize.enabled)
    637     {
    638         linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
    639     }
    640 }
    641 
    642 void DynamicHLSL::storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader,
    643                                           std::vector<LinkedVarying> *linkedVaryings) const
    644 {
    645     const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize);
    646     const std::vector<PackedVarying> &varyings = vertexShader->getVaryings();
    647 
    648     for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++)
    649     {
    650         const PackedVarying &varying = varyings[varyingIndex];
    651 
    652         if (varying.registerAssigned())
    653         {
    654             ASSERT(!varying.isBuiltIn());
    655             GLenum transposedType = TransposeMatrixType(varying.type);
    656             int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
    657 
    658             linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(),
    659                                                     varyingSemantic, varying.registerIndex,
    660                                                     variableRows * varying.elementCount()));
    661         }
    662     }
    663 }
    664 
    665 bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing,
    666                                          std::string& pixelHLSL, std::string& vertexHLSL,
    667                                          rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader,
    668                                          const std::vector<std::string>& transformFeedbackVaryings,
    669                                          std::vector<LinkedVarying> *linkedVaryings,
    670                                          std::map<int, VariableLocation> *programOutputVars,
    671                                          std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
    672                                          bool *outUsesFragDepth) const
    673 {
    674     if (pixelHLSL.empty() || vertexHLSL.empty())
    675     {
    676         return false;
    677     }
    678 
    679     bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
    680     bool usesFragColor = fragmentShader->mUsesFragColor;
    681     bool usesFragData = fragmentShader->mUsesFragData;
    682     bool usesFragCoord = fragmentShader->mUsesFragCoord;
    683     bool usesPointCoord = fragmentShader->mUsesPointCoord;
    684     bool usesPointSize = vertexShader->mUsesPointSize;
    685 
    686     if (usesFragColor && usesFragData)
    687     {
    688         infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
    689         return false;
    690     }
    691 
    692     // Write the HLSL input/output declarations
    693     const int shaderModel = mRenderer->getMajorShaderModel();
    694 
    695     // TODO (geofflang):  Use context's caps
    696     const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
    697 
    698     const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0);
    699 
    700     // Two cases when writing to gl_FragColor and using ESSL 1.0:
    701     // - with a 3.0 context, the output color is copied to channel 0
    702     // - with a 2.0 context, the output color is broadcast to all channels
    703     const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
    704     const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1);
    705 
    706     int shaderVersion = vertexShader->getShaderVersion();
    707 
    708     if (registersNeeded > maxVaryingVectors)
    709     {
    710         infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
    711         return false;
    712     }
    713 
    714     const std::string &varyingHLSL = generateVaryingHLSL(vertexShader);
    715     const SemanticInfo &vertexSemantics = getSemanticInfo(registers, usesFragCoord,
    716                                                           false, usesPointSize, false);
    717 
    718     storeUserLinkedVaryings(vertexShader, linkedVaryings);
    719     storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings);
    720 
    721     // Add stub string to be replaced when shader is dynamically defined by its layout
    722     vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n"
    723                   "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n"
    724                   "VS_OUTPUT main(VS_INPUT input)\n"
    725                   "{\n"
    726                   "    initAttributes(input);\n";
    727 
    728     if (shaderModel >= 4)
    729     {
    730         vertexHLSL += "\n"
    731                       "    gl_main();\n"
    732                       "\n"
    733                       "    VS_OUTPUT output;\n"
    734                       "    output.gl_Position = gl_Position;\n"
    735                       "    output.dx_Position.x = gl_Position.x;\n"
    736                       "    output.dx_Position.y = -gl_Position.y;\n"
    737                       "    output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
    738                       "    output.dx_Position.w = gl_Position.w;\n";
    739     }
    740     else
    741     {
    742         vertexHLSL += "\n"
    743                       "    gl_main();\n"
    744                       "\n"
    745                       "    VS_OUTPUT output;\n"
    746                       "    output.gl_Position = gl_Position;\n"
    747                       "    output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
    748                       "    output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
    749                       "    output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
    750                       "    output.dx_Position.w = gl_Position.w;\n";
    751     }
    752 
    753     if (usesPointSize && shaderModel >= 3)
    754     {
    755         vertexHLSL += "    output.gl_PointSize = gl_PointSize;\n";
    756     }
    757 
    758     if (usesFragCoord)
    759     {
    760         vertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
    761     }
    762 
    763     const std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
    764     for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
    765     {
    766         const PackedVarying &varying = vertexVaryings[vertVaryingIndex];
    767         if (varying.registerAssigned())
    768         {
    769             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
    770             {
    771                 int variableRows = (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type)));
    772 
    773                 for (int row = 0; row < variableRows; row++)
    774                 {
    775                     int r = varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row;
    776                     vertexHLSL += "    output.v" + Str(r);
    777 
    778                     vertexHLSL += " = _" + varying.name;
    779 
    780                     if (varying.isArray())
    781                     {
    782                         vertexHLSL += ArrayString(elementIndex);
    783                     }
    784 
    785                     if (variableRows > 1)
    786                     {
    787                         vertexHLSL += ArrayString(row);
    788                     }
    789 
    790                     vertexHLSL += ";\n";
    791                 }
    792             }
    793         }
    794     }
    795 
    796     vertexHLSL += "\n"
    797                   "    return output;\n"
    798                   "}\n";
    799 
    800     const SemanticInfo &pixelSemantics = getSemanticInfo(registers, usesFragCoord, usesPointCoord,
    801                                                          usesPointSize, true);
    802 
    803     pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n";
    804 
    805     if (shaderVersion < 300)
    806     {
    807         for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
    808         {
    809             PixelShaderOutputVariable outputKeyVariable;
    810             outputKeyVariable.type = GL_FLOAT_VEC4;
    811             outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
    812             outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
    813             outputKeyVariable.outputIndex = renderTargetIndex;
    814 
    815             outPixelShaderKey->push_back(outputKeyVariable);
    816         }
    817 
    818         *outUsesFragDepth = fragmentShader->mUsesFragDepth;
    819     }
    820     else
    821     {
    822         defineOutputVariables(fragmentShader, programOutputVars);
    823 
    824         const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
    825         for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
    826         {
    827             const VariableLocation &outputLocation = locationIt->second;
    828             const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
    829             const std::string &variableName = "out_" + outputLocation.name;
    830             const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
    831 
    832             ASSERT(outputVariable.staticUse);
    833 
    834             PixelShaderOutputVariable outputKeyVariable;
    835             outputKeyVariable.type = outputVariable.type;
    836             outputKeyVariable.name = variableName + elementString;
    837             outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
    838             outputKeyVariable.outputIndex = locationIt->first;
    839 
    840             outPixelShaderKey->push_back(outputKeyVariable);
    841         }
    842 
    843         *outUsesFragDepth = false;
    844     }
    845 
    846     pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n";
    847 
    848     if (fragmentShader->mUsesFrontFacing)
    849     {
    850         if (shaderModel >= 4)
    851         {
    852             pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
    853                          "{\n";
    854         }
    855         else
    856         {
    857             pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
    858                          "{\n";
    859         }
    860     }
    861     else
    862     {
    863         pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
    864                      "{\n";
    865     }
    866 
    867     if (usesFragCoord)
    868     {
    869         pixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
    870 
    871         if (shaderModel >= 4)
    872         {
    873             pixelHLSL += "    gl_FragCoord.x = input.dx_Position.x;\n"
    874                          "    gl_FragCoord.y = input.dx_Position.y;\n";
    875         }
    876         else if (shaderModel >= 3)
    877         {
    878             pixelHLSL += "    gl_FragCoord.x = input.dx_Position.x + 0.5;\n"
    879                          "    gl_FragCoord.y = input.dx_Position.y + 0.5;\n";
    880         }
    881         else
    882         {
    883             // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
    884             pixelHLSL += "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
    885                          "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
    886         }
    887 
    888         pixelHLSL += "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
    889                      "    gl_FragCoord.w = rhw;\n";
    890     }
    891 
    892     if (usesPointCoord && shaderModel >= 3)
    893     {
    894         pixelHLSL += "    gl_PointCoord.x = input.gl_PointCoord.x;\n";
    895         pixelHLSL += "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
    896     }
    897 
    898     if (fragmentShader->mUsesFrontFacing)
    899     {
    900         if (shaderModel <= 3)
    901         {
    902             pixelHLSL += "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
    903         }
    904         else
    905         {
    906             pixelHLSL += "    gl_FrontFacing = isFrontFace;\n";
    907         }
    908     }
    909 
    910     const std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
    911     for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
    912     {
    913         const PackedVarying &varying = fragmentVaryings[varyingIndex];
    914         if (varying.registerAssigned())
    915         {
    916             ASSERT(!varying.isBuiltIn());
    917             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
    918             {
    919                 GLenum transposedType = TransposeMatrixType(varying.type);
    920                 int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
    921                 for (int row = 0; row < variableRows; row++)
    922                 {
    923                     std::string n = Str(varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row);
    924                     pixelHLSL += "    _" + varying.name;
    925 
    926                     if (varying.isArray())
    927                     {
    928                         pixelHLSL += ArrayString(elementIndex);
    929                     }
    930 
    931                     if (variableRows > 1)
    932                     {
    933                         pixelHLSL += ArrayString(row);
    934                     }
    935 
    936                     if (varying.isStruct())
    937                     {
    938                         pixelHLSL += " = input.v" + n + ";\n";   break;
    939                     }
    940                     else
    941                     {
    942                         switch (VariableColumnCount(transposedType))
    943                         {
    944                           case 1: pixelHLSL += " = input.v" + n + ".x;\n";   break;
    945                           case 2: pixelHLSL += " = input.v" + n + ".xy;\n";  break;
    946                           case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
    947                           case 4: pixelHLSL += " = input.v" + n + ";\n";     break;
    948                           default: UNREACHABLE();
    949                         }
    950                     }
    951                 }
    952             }
    953         }
    954         else
    955         {
    956             ASSERT(varying.isBuiltIn() || !varying.staticUse);
    957         }
    958     }
    959 
    960     pixelHLSL += "\n"
    961                  "    gl_main();\n"
    962                  "\n"
    963                  "    return generateOutput();\n"
    964                  "}\n";
    965 
    966     return true;
    967 }
    968 
    969 void DynamicHLSL::defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
    970 {
    971     const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
    972 
    973     for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++)
    974     {
    975         const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
    976         const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
    977 
    978         ASSERT(outputVariable.staticUse);
    979 
    980         if (outputVariable.arraySize > 0)
    981         {
    982             for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
    983             {
    984                 const int location = baseLocation + elementIndex;
    985                 ASSERT(programOutputVars->count(location) == 0);
    986                 (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
    987             }
    988         }
    989         else
    990         {
    991             ASSERT(programOutputVars->count(baseLocation) == 0);
    992             (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
    993         }
    994     }
    995 }
    996 
    997 std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const
    998 {
    999     // for now we only handle point sprite emulation
   1000     ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
   1001     return generatePointSpriteHLSL(registers, fragmentShader, vertexShader);
   1002 }
   1003 
   1004 std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const
   1005 {
   1006     ASSERT(registers >= 0);
   1007     ASSERT(vertexShader->mUsesPointSize);
   1008     ASSERT(mRenderer->getMajorShaderModel() >= 4);
   1009 
   1010     std::string geomHLSL;
   1011 
   1012     const SemanticInfo &inSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord,
   1013                                                       false, true, false);
   1014     const SemanticInfo &outSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord,
   1015                                                        fragmentShader->mUsesPointCoord, true, false);
   1016 
   1017     std::string varyingHLSL = generateVaryingHLSL(vertexShader);
   1018     std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
   1019     std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
   1020 
   1021     // TODO(geofflang): use context's caps
   1022     geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
   1023                 "\n"
   1024                 "struct GS_INPUT\n" + inLinkHLSL + "\n" +
   1025                 "struct GS_OUTPUT\n" + outLinkHLSL + "\n" +
   1026                 "\n"
   1027                   "static float2 pointSpriteCorners[] = \n"
   1028                   "{\n"
   1029                   "    float2( 0.5f, -0.5f),\n"
   1030                   "    float2( 0.5f,  0.5f),\n"
   1031                   "    float2(-0.5f, -0.5f),\n"
   1032                   "    float2(-0.5f,  0.5f)\n"
   1033                   "};\n"
   1034                   "\n"
   1035                   "static float2 pointSpriteTexcoords[] = \n"
   1036                   "{\n"
   1037                   "    float2(1.0f, 1.0f),\n"
   1038                   "    float2(1.0f, 0.0f),\n"
   1039                   "    float2(0.0f, 1.0f),\n"
   1040                   "    float2(0.0f, 0.0f)\n"
   1041                   "};\n"
   1042                   "\n"
   1043                   "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n"
   1044                   "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"
   1045                   "\n"
   1046                   "[maxvertexcount(4)]\n"
   1047                   "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
   1048                   "{\n"
   1049                   "    GS_OUTPUT output = (GS_OUTPUT)0;\n"
   1050                   "    output.gl_Position = input[0].gl_Position;\n";
   1051                   "    output.gl_PointSize = input[0].gl_PointSize;\n";
   1052 
   1053     for (int r = 0; r < registers; r++)
   1054     {
   1055         geomHLSL += "    output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n";
   1056     }
   1057 
   1058     if (fragmentShader->mUsesFragCoord)
   1059     {
   1060         geomHLSL += "    output.gl_FragCoord = input[0].gl_FragCoord;\n";
   1061     }
   1062 
   1063     geomHLSL += "    \n"
   1064                 "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
   1065                 "    float4 dx_Position = input[0].dx_Position;\n"
   1066                 "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * dx_Position.w;\n";
   1067 
   1068     for (int corner = 0; corner < 4; corner++)
   1069     {
   1070         geomHLSL += "    \n"
   1071                     "    output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
   1072 
   1073         if (fragmentShader->mUsesPointCoord)
   1074         {
   1075             geomHLSL += "    output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n";
   1076         }
   1077 
   1078         geomHLSL += "    outStream.Append(output);\n";
   1079     }
   1080 
   1081     geomHLSL += "    \n"
   1082                 "    outStream.RestartStrip();\n"
   1083                 "}\n";
   1084 
   1085     return geomHLSL;
   1086 }
   1087 
   1088 // This method needs to match OutputHLSL::decorate
   1089 std::string DynamicHLSL::decorateVariable(const std::string &name)
   1090 {
   1091     if (name.compare(0, 3, "gl_") != 0)
   1092     {
   1093         return "_" + name;
   1094     }
   1095 
   1096     return name;
   1097 }
   1098 
   1099 std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const
   1100 {
   1101     std::string attribString = "input." + decorateVariable(shaderAttrib.name);
   1102 
   1103     // Matrix
   1104     if (IsMatrixType(shaderAttrib.type))
   1105     {
   1106         return "transpose(" + attribString + ")";
   1107     }
   1108 
   1109     GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
   1110     int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
   1111 
   1112     // Perform integer to float conversion (if necessary)
   1113     bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT);
   1114 
   1115     if (requiresTypeConversion)
   1116     {
   1117         // TODO: normalization for 32-bit integer formats
   1118         ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger);
   1119         return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
   1120     }
   1121 
   1122     // No conversion necessary
   1123     return attribString;
   1124 }
   1125 
   1126 void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const
   1127 {
   1128     for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
   1129     {
   1130         const VertexFormat &vertexFormat = inputLayout[inputIndex];
   1131 
   1132         if (vertexFormat.mType == GL_NONE)
   1133         {
   1134             signature[inputIndex] = GL_NONE;
   1135         }
   1136         else
   1137         {
   1138             bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0);
   1139             signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE);
   1140         }
   1141     }
   1142 }
   1143 
   1144 }
   1145