Home | History | Annotate | Download | only in compiler
      1 //
      2 // Copyright (c) 2002-2013 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 
      7 #include "compiler/OutputHLSL.h"
      8 
      9 #include "common/angleutils.h"
     10 #include "compiler/debug.h"
     11 #include "compiler/DetectDiscontinuity.h"
     12 #include "compiler/InfoSink.h"
     13 #include "compiler/SearchSymbol.h"
     14 #include "compiler/UnfoldShortCircuit.h"
     15 #include "compiler/NodeSearch.h"
     16 
     17 #include <algorithm>
     18 #include <cfloat>
     19 #include <stdio.h>
     20 
     21 namespace sh
     22 {
     23 // Integer to TString conversion
     24 TString str(int i)
     25 {
     26     char buffer[20];
     27     snprintf(buffer, sizeof(buffer), "%d", i);
     28     return buffer;
     29 }
     30 
     31 OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
     32     : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
     33 {
     34     mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
     35     mInsideFunction = false;
     36 
     37     mUsesTexture2D = false;
     38     mUsesTexture2D_bias = false;
     39     mUsesTexture2DProj = false;
     40     mUsesTexture2DProj_bias = false;
     41     mUsesTexture2DProjLod = false;
     42     mUsesTexture2DLod = false;
     43     mUsesTextureCube = false;
     44     mUsesTextureCube_bias = false;
     45     mUsesTextureCubeLod = false;
     46     mUsesTexture2DLod0 = false;
     47     mUsesTexture2DLod0_bias = false;
     48     mUsesTexture2DProjLod0 = false;
     49     mUsesTexture2DProjLod0_bias = false;
     50     mUsesTextureCubeLod0 = false;
     51     mUsesTextureCubeLod0_bias = false;
     52     mUsesFragColor = false;
     53     mUsesFragData = false;
     54     mUsesDepthRange = false;
     55     mUsesFragCoord = false;
     56     mUsesPointCoord = false;
     57     mUsesFrontFacing = false;
     58     mUsesPointSize = false;
     59     mUsesFragDepth = false;
     60     mUsesXor = false;
     61     mUsesMod1 = false;
     62     mUsesMod2v = false;
     63     mUsesMod2f = false;
     64     mUsesMod3v = false;
     65     mUsesMod3f = false;
     66     mUsesMod4v = false;
     67     mUsesMod4f = false;
     68     mUsesFaceforward1 = false;
     69     mUsesFaceforward2 = false;
     70     mUsesFaceforward3 = false;
     71     mUsesFaceforward4 = false;
     72     mUsesAtan2_1 = false;
     73     mUsesAtan2_2 = false;
     74     mUsesAtan2_3 = false;
     75     mUsesAtan2_4 = false;
     76     mUsesDiscardRewriting = false;
     77 
     78     mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
     79 
     80     mScopeDepth = 0;
     81 
     82     mUniqueIndex = 0;
     83 
     84     mContainsLoopDiscontinuity = false;
     85     mOutputLod0Function = false;
     86     mInsideDiscontinuousLoop = false;
     87 
     88     mExcessiveLoopIndex = NULL;
     89 
     90     if (mOutputType == SH_HLSL9_OUTPUT)
     91     {
     92         if (mContext.shaderType == SH_FRAGMENT_SHADER)
     93         {
     94             mUniformRegister = 3;   // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
     95         }
     96         else
     97         {
     98             mUniformRegister = 2;   // Reserve registers for dx_DepthRange and dx_ViewAdjust
     99         }
    100     }
    101     else
    102     {
    103         mUniformRegister = 0;
    104     }
    105 
    106     mSamplerRegister = 0;
    107 }
    108 
    109 OutputHLSL::~OutputHLSL()
    110 {
    111     delete mUnfoldShortCircuit;
    112 }
    113 
    114 void OutputHLSL::output()
    115 {
    116     mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
    117 
    118     mContext.treeRoot->traverse(this);   // Output the body first to determine what has to go in the header
    119     header();
    120 
    121     mContext.infoSink().obj << mHeader.c_str();
    122     mContext.infoSink().obj << mBody.c_str();
    123 }
    124 
    125 TInfoSinkBase &OutputHLSL::getBodyStream()
    126 {
    127     return mBody;
    128 }
    129 
    130 const ActiveUniforms &OutputHLSL::getUniforms()
    131 {
    132     return mActiveUniforms;
    133 }
    134 
    135 int OutputHLSL::vectorSize(const TType &type) const
    136 {
    137     int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
    138     int arraySize = type.isArray() ? type.getArraySize() : 1;
    139 
    140     return elementSize * arraySize;
    141 }
    142 
    143 void OutputHLSL::header()
    144 {
    145     ShShaderType shaderType = mContext.shaderType;
    146     TInfoSinkBase &out = mHeader;
    147 
    148     for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
    149     {
    150         out << *structDeclaration;
    151     }
    152 
    153     for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
    154     {
    155         out << *constructor;
    156     }
    157 
    158     TString uniforms;
    159     TString varyings;
    160     TString attributes;
    161 
    162     for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++)
    163     {
    164         const TType &type = uniform->second->getType();
    165         const TString &name = uniform->second->getSymbol();
    166 
    167         if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
    168         {
    169             int index = samplerRegister(mReferencedUniforms[name]);
    170 
    171             uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) +
    172                         " : register(s" + str(index) + ");\n";
    173 
    174             uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
    175                         " : register(t" + str(index) + ");\n";
    176         }
    177         else
    178         {
    179             uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) +
    180                         " : register(" + registerString(mReferencedUniforms[name]) + ");\n";
    181         }
    182     }
    183 
    184     for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
    185     {
    186         const TType &type = varying->second->getType();
    187         const TString &name = varying->second->getSymbol();
    188 
    189         // Program linking depends on this exact format
    190         varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
    191     }
    192 
    193     for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
    194     {
    195         const TType &type = attribute->second->getType();
    196         const TString &name = attribute->second->getSymbol();
    197 
    198         attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
    199     }
    200 
    201     if (mUsesDiscardRewriting)
    202     {
    203         out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
    204     }
    205 
    206     if (shaderType == SH_FRAGMENT_SHADER)
    207     {
    208         TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
    209         const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
    210 
    211         const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
    212 
    213         out << "// Varyings\n";
    214         out <<  varyings;
    215         out << "\n"
    216                "static float4 gl_Color[" << numColorValues << "] =\n"
    217                "{\n";
    218         for (unsigned int i = 0; i < numColorValues; i++)
    219         {
    220             out << "    float4(0, 0, 0, 0)";
    221             if (i + 1 != numColorValues)
    222             {
    223                 out << ",";
    224             }
    225             out << "\n";
    226         }
    227         out << "};\n";
    228 
    229         if (mUsesFragDepth)
    230         {
    231             out << "static float gl_Depth = 0.0;\n";
    232         }
    233 
    234         if (mUsesFragCoord)
    235         {
    236             out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
    237         }
    238 
    239         if (mUsesPointCoord)
    240         {
    241             out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
    242         }
    243 
    244         if (mUsesFrontFacing)
    245         {
    246             out << "static bool gl_FrontFacing = false;\n";
    247         }
    248 
    249         out << "\n";
    250 
    251         if (mUsesDepthRange)
    252         {
    253             out << "struct gl_DepthRangeParameters\n"
    254                    "{\n"
    255                    "    float near;\n"
    256                    "    float far;\n"
    257                    "    float diff;\n"
    258                    "};\n"
    259                    "\n";
    260         }
    261 
    262         if (mOutputType == SH_HLSL11_OUTPUT)
    263         {
    264             out << "cbuffer DriverConstants : register(b1)\n"
    265                    "{\n";
    266 
    267             if (mUsesDepthRange)
    268             {
    269                 out << "    float3 dx_DepthRange : packoffset(c0);\n";
    270             }
    271 
    272             if (mUsesFragCoord)
    273             {
    274                 out << "    float4 dx_ViewCoords : packoffset(c1);\n";
    275             }
    276 
    277             if (mUsesFragCoord || mUsesFrontFacing)
    278             {
    279                 out << "    float3 dx_DepthFront : packoffset(c2);\n";
    280             }
    281 
    282             out << "};\n";
    283         }
    284         else
    285         {
    286             if (mUsesDepthRange)
    287             {
    288                 out << "uniform float3 dx_DepthRange : register(c0);";
    289             }
    290 
    291             if (mUsesFragCoord)
    292             {
    293                 out << "uniform float4 dx_ViewCoords : register(c1);\n";
    294             }
    295 
    296             if (mUsesFragCoord || mUsesFrontFacing)
    297             {
    298                 out << "uniform float3 dx_DepthFront : register(c2);\n";
    299             }
    300         }
    301 
    302         out << "\n";
    303 
    304         if (mUsesDepthRange)
    305         {
    306             out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
    307                    "\n";
    308         }
    309 
    310         out <<  uniforms;
    311         out << "\n";
    312 
    313         if (mUsesTexture2D)
    314         {
    315             if (mOutputType == SH_HLSL9_OUTPUT)
    316             {
    317                 out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
    318                        "{\n"
    319                        "    return tex2D(s, t);\n"
    320                        "}\n"
    321                        "\n";
    322             }
    323             else if (mOutputType == SH_HLSL11_OUTPUT)
    324             {
    325                 out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
    326                        "{\n"
    327                        "    return t.Sample(s, uv);\n"
    328                        "}\n"
    329                        "\n";
    330             }
    331             else UNREACHABLE();
    332         }
    333 
    334         if (mUsesTexture2D_bias)
    335         {
    336             if (mOutputType == SH_HLSL9_OUTPUT)
    337             {
    338                 out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
    339                        "{\n"
    340                        "    return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
    341                        "}\n"
    342                        "\n";
    343             }
    344             else if (mOutputType == SH_HLSL11_OUTPUT)
    345             {
    346                 out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n"
    347                        "{\n"
    348                        "    return t.SampleBias(s, uv, bias);\n"
    349                        "}\n"
    350                        "\n";
    351             }
    352             else UNREACHABLE();
    353         }
    354 
    355         if (mUsesTexture2DProj)
    356         {
    357             if (mOutputType == SH_HLSL9_OUTPUT)
    358             {
    359                 out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
    360                        "{\n"
    361                        "    return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
    362                        "}\n"
    363                        "\n"
    364                        "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
    365                        "{\n"
    366                        "    return tex2Dproj(s, t);\n"
    367                        "}\n"
    368                        "\n";
    369             }
    370             else if (mOutputType == SH_HLSL11_OUTPUT)
    371             {
    372                 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
    373                        "{\n"
    374                        "    return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n"
    375                        "}\n"
    376                        "\n"
    377                        "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
    378                        "{\n"
    379                        "    return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n"
    380                        "}\n"
    381                        "\n";
    382             }
    383             else UNREACHABLE();
    384         }
    385 
    386         if (mUsesTexture2DProj_bias)
    387         {
    388             if (mOutputType == SH_HLSL9_OUTPUT)
    389             {
    390                 out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
    391                        "{\n"
    392                        "    return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
    393                        "}\n"
    394                        "\n"
    395                        "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
    396                        "{\n"
    397                        "    return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
    398                        "}\n"
    399                        "\n";
    400             }
    401             else if (mOutputType == SH_HLSL11_OUTPUT)
    402             {
    403                 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
    404                        "{\n"
    405                        "    return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n"
    406                        "}\n"
    407                        "\n"
    408                        "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
    409                        "{\n"
    410                        "    return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n"
    411                        "}\n"
    412                        "\n";
    413             }
    414             else UNREACHABLE();
    415         }
    416 
    417         if (mUsesTextureCube)
    418         {
    419             if (mOutputType == SH_HLSL9_OUTPUT)
    420             {
    421                 out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
    422                        "{\n"
    423                        "    return texCUBE(s, t);\n"
    424                        "}\n"
    425                        "\n";
    426             }
    427             else if (mOutputType == SH_HLSL11_OUTPUT)
    428             {
    429                 out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
    430                        "{\n"
    431                        "    return t.Sample(s, uvw);\n"
    432                        "}\n"
    433                        "\n";
    434             }
    435             else UNREACHABLE();
    436         }
    437 
    438         if (mUsesTextureCube_bias)
    439         {
    440             if (mOutputType == SH_HLSL9_OUTPUT)
    441             {
    442                 out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
    443                        "{\n"
    444                        "    return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
    445                        "}\n"
    446                        "\n";
    447             }
    448             else if (mOutputType == SH_HLSL11_OUTPUT)
    449             {
    450                 out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
    451                        "{\n"
    452                        "    return t.SampleBias(s, uvw, bias);\n"
    453                        "}\n"
    454                        "\n";
    455             }
    456             else UNREACHABLE();
    457         }
    458 
    459         // These *Lod0 intrinsics are not available in GL fragment shaders.
    460         // They are used to sample using discontinuous texture coordinates.
    461         if (mUsesTexture2DLod0)
    462         {
    463             if (mOutputType == SH_HLSL9_OUTPUT)
    464             {
    465                 out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n"
    466                        "{\n"
    467                        "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
    468                        "}\n"
    469                        "\n";
    470             }
    471             else if (mOutputType == SH_HLSL11_OUTPUT)
    472             {
    473                 out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n"
    474                        "{\n"
    475                        "    return t.SampleLevel(s, uv, 0);\n"
    476                        "}\n"
    477                        "\n";
    478             }
    479             else UNREACHABLE();
    480         }
    481 
    482         if (mUsesTexture2DLod0_bias)
    483         {
    484             if (mOutputType == SH_HLSL9_OUTPUT)
    485             {
    486                 out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n"
    487                        "{\n"
    488                        "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
    489                        "}\n"
    490                        "\n";
    491             }
    492             else if (mOutputType == SH_HLSL11_OUTPUT)
    493             {
    494                 out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n"
    495                        "{\n"
    496                        "    return t.SampleLevel(s, uv, 0);\n"
    497                        "}\n"
    498                        "\n";
    499             }
    500             else UNREACHABLE();
    501         }
    502 
    503         if (mUsesTexture2DProjLod0)
    504         {
    505             if (mOutputType == SH_HLSL9_OUTPUT)
    506             {
    507                 out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n"
    508                        "{\n"
    509                        "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
    510                        "}\n"
    511                        "\n"
    512                        "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n"
    513                        "{\n"
    514                        "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
    515                        "}\n"
    516                        "\n";
    517             }
    518             else if (mOutputType == SH_HLSL11_OUTPUT)
    519             {
    520                 out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n"
    521                        "{\n"
    522                        "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
    523                        "}\n"
    524                        "\n"
    525                        "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n"
    526                        "{\n"
    527                        "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
    528                        "}\n"
    529                        "\n";
    530             }
    531             else UNREACHABLE();
    532         }
    533 
    534         if (mUsesTexture2DProjLod0_bias)
    535         {
    536             if (mOutputType == SH_HLSL9_OUTPUT)
    537             {
    538                 out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n"
    539                        "{\n"
    540                        "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
    541                        "}\n"
    542                        "\n"
    543                        "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n"
    544                        "{\n"
    545                        "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
    546                        "}\n"
    547                        "\n";
    548             }
    549             else if (mOutputType == SH_HLSL11_OUTPUT)
    550             {
    551                 out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
    552                        "{\n"
    553                        "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
    554                        "}\n"
    555                        "\n"
    556                        "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
    557                        "{\n"
    558                        "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
    559                        "}\n"
    560                        "\n";
    561             }
    562             else UNREACHABLE();
    563         }
    564 
    565         if (mUsesTextureCubeLod0)
    566         {
    567             if (mOutputType == SH_HLSL9_OUTPUT)
    568             {
    569                 out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n"
    570                        "{\n"
    571                        "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
    572                        "}\n"
    573                        "\n";
    574             }
    575             else if (mOutputType == SH_HLSL11_OUTPUT)
    576             {
    577                 out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n"
    578                        "{\n"
    579                        "    return t.SampleLevel(s, uvw, 0);\n"
    580                        "}\n"
    581                        "\n";
    582             }
    583             else UNREACHABLE();
    584         }
    585 
    586         if (mUsesTextureCubeLod0_bias)
    587         {
    588             if (mOutputType == SH_HLSL9_OUTPUT)
    589             {
    590                 out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n"
    591                        "{\n"
    592                        "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
    593                        "}\n"
    594                        "\n";
    595             }
    596             else if (mOutputType == SH_HLSL11_OUTPUT)
    597             {
    598                 out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
    599                        "{\n"
    600                        "    return t.SampleLevel(s, uvw, 0);\n"
    601                        "}\n"
    602                        "\n";
    603             }
    604             else UNREACHABLE();
    605         }
    606 
    607         if (usingMRTExtension && mNumRenderTargets > 1)
    608         {
    609             out << "#define GL_USES_MRT\n";
    610         }
    611 
    612         if (mUsesFragColor)
    613         {
    614             out << "#define GL_USES_FRAG_COLOR\n";
    615         }
    616 
    617         if (mUsesFragData)
    618         {
    619             out << "#define GL_USES_FRAG_DATA\n";
    620         }
    621     }
    622     else   // Vertex shader
    623     {
    624         out << "// Attributes\n";
    625         out <<  attributes;
    626         out << "\n"
    627                "static float4 gl_Position = float4(0, 0, 0, 0);\n";
    628 
    629         if (mUsesPointSize)
    630         {
    631             out << "static float gl_PointSize = float(1);\n";
    632         }
    633 
    634         out << "\n"
    635                "// Varyings\n";
    636         out <<  varyings;
    637         out << "\n";
    638 
    639         if (mUsesDepthRange)
    640         {
    641             out << "struct gl_DepthRangeParameters\n"
    642                    "{\n"
    643                    "    float near;\n"
    644                    "    float far;\n"
    645                    "    float diff;\n"
    646                    "};\n"
    647                    "\n";
    648         }
    649 
    650         if (mOutputType == SH_HLSL11_OUTPUT)
    651         {
    652             if (mUsesDepthRange)
    653             {
    654                 out << "cbuffer DriverConstants : register(b1)\n"
    655                        "{\n"
    656                        "    float3 dx_DepthRange : packoffset(c0);\n"
    657                        "};\n"
    658                        "\n";
    659             }
    660         }
    661         else
    662         {
    663             if (mUsesDepthRange)
    664             {
    665                 out << "uniform float3 dx_DepthRange : register(c0);\n";
    666             }
    667 
    668             out << "uniform float4 dx_ViewAdjust : register(c1);\n"
    669                    "\n";
    670         }
    671 
    672         if (mUsesDepthRange)
    673         {
    674             out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
    675                    "\n";
    676         }
    677 
    678         out << uniforms;
    679         out << "\n";
    680 
    681         if (mUsesTexture2D)
    682         {
    683             if (mOutputType == SH_HLSL9_OUTPUT)
    684             {
    685                 out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
    686                        "{\n"
    687                        "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
    688                        "}\n"
    689                        "\n";
    690             }
    691             else if (mOutputType == SH_HLSL11_OUTPUT)
    692             {
    693                 out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
    694                        "{\n"
    695                        "    return t.SampleLevel(s, uv, 0);\n"
    696                        "}\n"
    697                        "\n";
    698             }
    699             else UNREACHABLE();
    700         }
    701 
    702         if (mUsesTexture2DLod)
    703         {
    704             if (mOutputType == SH_HLSL9_OUTPUT)
    705             {
    706                 out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n"
    707                        "{\n"
    708                        "    return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n"
    709                        "}\n"
    710                        "\n";
    711             }
    712             else if (mOutputType == SH_HLSL11_OUTPUT)
    713             {
    714                 out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n"
    715                        "{\n"
    716                        "    return t.SampleLevel(s, uv, lod);\n"
    717                        "}\n"
    718                        "\n";
    719             }
    720             else UNREACHABLE();
    721         }
    722 
    723         if (mUsesTexture2DProj)
    724         {
    725             if (mOutputType == SH_HLSL9_OUTPUT)
    726             {
    727                 out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
    728                        "{\n"
    729                        "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
    730                        "}\n"
    731                        "\n"
    732                        "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
    733                        "{\n"
    734                        "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
    735                        "}\n"
    736                        "\n";
    737             }
    738             else if (mOutputType == SH_HLSL11_OUTPUT)
    739             {
    740                 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
    741                        "{\n"
    742                        "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
    743                        "}\n"
    744                        "\n"
    745                        "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
    746                        "{\n"
    747                        "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
    748                        "}\n"
    749                        "\n";
    750             }
    751             else UNREACHABLE();
    752         }
    753 
    754         if (mUsesTexture2DProjLod)
    755         {
    756             if (mOutputType == SH_HLSL9_OUTPUT)
    757             {
    758                 out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n"
    759                        "{\n"
    760                        "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n"
    761                        "}\n"
    762                        "\n"
    763                        "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n"
    764                        "{\n"
    765                        "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n"
    766                        "}\n"
    767                        "\n";
    768             }
    769             else if (mOutputType == SH_HLSL11_OUTPUT)
    770             {
    771                 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float lod)\n"
    772                        "{\n"
    773                        "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n"
    774                        "}\n"
    775                        "\n"
    776                        "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
    777                        "{\n"
    778                        "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n"
    779                        "}\n"
    780                        "\n";
    781             }
    782             else UNREACHABLE();
    783         }
    784 
    785         if (mUsesTextureCube)
    786         {
    787             if (mOutputType == SH_HLSL9_OUTPUT)
    788             {
    789                 out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
    790                        "{\n"
    791                        "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
    792                        "}\n"
    793                        "\n";
    794             }
    795             else if (mOutputType == SH_HLSL11_OUTPUT)
    796             {
    797                 out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
    798                        "{\n"
    799                        "    return t.SampleLevel(s, uvw, 0);\n"
    800                        "}\n"
    801                        "\n";
    802             }
    803             else UNREACHABLE();
    804         }
    805 
    806         if (mUsesTextureCubeLod)
    807         {
    808             if (mOutputType == SH_HLSL9_OUTPUT)
    809             {
    810                 out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n"
    811                        "{\n"
    812                        "    return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n"
    813                        "}\n"
    814                        "\n";
    815             }
    816             else if (mOutputType == SH_HLSL11_OUTPUT)
    817             {
    818                 out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n"
    819                        "{\n"
    820                        "    return t.SampleLevel(s, uvw, lod);\n"
    821                        "}\n"
    822                        "\n";
    823             }
    824             else UNREACHABLE();
    825         }
    826     }
    827 
    828     if (mUsesFragCoord)
    829     {
    830         out << "#define GL_USES_FRAG_COORD\n";
    831     }
    832 
    833     if (mUsesPointCoord)
    834     {
    835         out << "#define GL_USES_POINT_COORD\n";
    836     }
    837 
    838     if (mUsesFrontFacing)
    839     {
    840         out << "#define GL_USES_FRONT_FACING\n";
    841     }
    842 
    843     if (mUsesPointSize)
    844     {
    845         out << "#define GL_USES_POINT_SIZE\n";
    846     }
    847 
    848     if (mUsesFragDepth)
    849     {
    850         out << "#define GL_USES_FRAG_DEPTH\n";
    851     }
    852 
    853     if (mUsesDepthRange)
    854     {
    855         out << "#define GL_USES_DEPTH_RANGE\n";
    856     }
    857 
    858     if (mUsesXor)
    859     {
    860         out << "bool xor(bool p, bool q)\n"
    861                "{\n"
    862                "    return (p || q) && !(p && q);\n"
    863                "}\n"
    864                "\n";
    865     }
    866 
    867     if (mUsesMod1)
    868     {
    869         out << "float mod(float x, float y)\n"
    870                "{\n"
    871                "    return x - y * floor(x / y);\n"
    872                "}\n"
    873                "\n";
    874     }
    875 
    876     if (mUsesMod2v)
    877     {
    878         out << "float2 mod(float2 x, float2 y)\n"
    879                "{\n"
    880                "    return x - y * floor(x / y);\n"
    881                "}\n"
    882                "\n";
    883     }
    884 
    885     if (mUsesMod2f)
    886     {
    887         out << "float2 mod(float2 x, float y)\n"
    888                "{\n"
    889                "    return x - y * floor(x / y);\n"
    890                "}\n"
    891                "\n";
    892     }
    893 
    894     if (mUsesMod3v)
    895     {
    896         out << "float3 mod(float3 x, float3 y)\n"
    897                "{\n"
    898                "    return x - y * floor(x / y);\n"
    899                "}\n"
    900                "\n";
    901     }
    902 
    903     if (mUsesMod3f)
    904     {
    905         out << "float3 mod(float3 x, float y)\n"
    906                "{\n"
    907                "    return x - y * floor(x / y);\n"
    908                "}\n"
    909                "\n";
    910     }
    911 
    912     if (mUsesMod4v)
    913     {
    914         out << "float4 mod(float4 x, float4 y)\n"
    915                "{\n"
    916                "    return x - y * floor(x / y);\n"
    917                "}\n"
    918                "\n";
    919     }
    920 
    921     if (mUsesMod4f)
    922     {
    923         out << "float4 mod(float4 x, float y)\n"
    924                "{\n"
    925                "    return x - y * floor(x / y);\n"
    926                "}\n"
    927                "\n";
    928     }
    929 
    930     if (mUsesFaceforward1)
    931     {
    932         out << "float faceforward(float N, float I, float Nref)\n"
    933                "{\n"
    934                "    if(dot(Nref, I) >= 0)\n"
    935                "    {\n"
    936                "        return -N;\n"
    937                "    }\n"
    938                "    else\n"
    939                "    {\n"
    940                "        return N;\n"
    941                "    }\n"
    942                "}\n"
    943                "\n";
    944     }
    945 
    946     if (mUsesFaceforward2)
    947     {
    948         out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
    949                "{\n"
    950                "    if(dot(Nref, I) >= 0)\n"
    951                "    {\n"
    952                "        return -N;\n"
    953                "    }\n"
    954                "    else\n"
    955                "    {\n"
    956                "        return N;\n"
    957                "    }\n"
    958                "}\n"
    959                "\n";
    960     }
    961 
    962     if (mUsesFaceforward3)
    963     {
    964         out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
    965                "{\n"
    966                "    if(dot(Nref, I) >= 0)\n"
    967                "    {\n"
    968                "        return -N;\n"
    969                "    }\n"
    970                "    else\n"
    971                "    {\n"
    972                "        return N;\n"
    973                "    }\n"
    974                "}\n"
    975                "\n";
    976     }
    977 
    978     if (mUsesFaceforward4)
    979     {
    980         out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
    981                "{\n"
    982                "    if(dot(Nref, I) >= 0)\n"
    983                "    {\n"
    984                "        return -N;\n"
    985                "    }\n"
    986                "    else\n"
    987                "    {\n"
    988                "        return N;\n"
    989                "    }\n"
    990                "}\n"
    991                "\n";
    992     }
    993 
    994     if (mUsesAtan2_1)
    995     {
    996         out << "float atanyx(float y, float x)\n"
    997                "{\n"
    998                "    if(x == 0 && y == 0) x = 1;\n"   // Avoid producing a NaN
    999                "    return atan2(y, x);\n"
   1000                "}\n";
   1001     }
   1002 
   1003     if (mUsesAtan2_2)
   1004     {
   1005         out << "float2 atanyx(float2 y, float2 x)\n"
   1006                "{\n"
   1007                "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
   1008                "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
   1009                "    return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
   1010                "}\n";
   1011     }
   1012 
   1013     if (mUsesAtan2_3)
   1014     {
   1015         out << "float3 atanyx(float3 y, float3 x)\n"
   1016                "{\n"
   1017                "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
   1018                "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
   1019                "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
   1020                "    return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
   1021                "}\n";
   1022     }
   1023 
   1024     if (mUsesAtan2_4)
   1025     {
   1026         out << "float4 atanyx(float4 y, float4 x)\n"
   1027                "{\n"
   1028                "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
   1029                "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
   1030                "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
   1031                "    if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
   1032                "    return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
   1033                "}\n";
   1034     }
   1035 }
   1036 
   1037 void OutputHLSL::visitSymbol(TIntermSymbol *node)
   1038 {
   1039     TInfoSinkBase &out = mBody;
   1040 
   1041     TString name = node->getSymbol();
   1042 
   1043     if (name == "gl_FragColor")
   1044     {
   1045         out << "gl_Color[0]";
   1046         mUsesFragColor = true;
   1047     }
   1048     else if (name == "gl_FragData")
   1049     {
   1050         out << "gl_Color";
   1051         mUsesFragData = true;
   1052     }
   1053     else if (name == "gl_DepthRange")
   1054     {
   1055         mUsesDepthRange = true;
   1056         out << name;
   1057     }
   1058     else if (name == "gl_FragCoord")
   1059     {
   1060         mUsesFragCoord = true;
   1061         out << name;
   1062     }
   1063     else if (name == "gl_PointCoord")
   1064     {
   1065         mUsesPointCoord = true;
   1066         out << name;
   1067     }
   1068     else if (name == "gl_FrontFacing")
   1069     {
   1070         mUsesFrontFacing = true;
   1071         out << name;
   1072     }
   1073     else if (name == "gl_PointSize")
   1074     {
   1075         mUsesPointSize = true;
   1076         out << name;
   1077     }
   1078     else if (name == "gl_FragDepthEXT")
   1079     {
   1080         mUsesFragDepth = true;
   1081         out << "gl_Depth";
   1082     }
   1083     else
   1084     {
   1085         TQualifier qualifier = node->getQualifier();
   1086 
   1087         if (qualifier == EvqUniform)
   1088         {
   1089             mReferencedUniforms[name] = node;
   1090             out << decorateUniform(name, node->getType());
   1091         }
   1092         else if (qualifier == EvqAttribute)
   1093         {
   1094             mReferencedAttributes[name] = node;
   1095             out << decorate(name);
   1096         }
   1097         else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
   1098         {
   1099             mReferencedVaryings[name] = node;
   1100             out << decorate(name);
   1101         }
   1102         else
   1103         {
   1104             out << decorate(name);
   1105         }
   1106     }
   1107 }
   1108 
   1109 bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
   1110 {
   1111     TInfoSinkBase &out = mBody;
   1112 
   1113     switch (node->getOp())
   1114     {
   1115       case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");           break;
   1116       case EOpInitialize:
   1117         if (visit == PreVisit)
   1118         {
   1119             // GLSL allows to write things like "float x = x;" where a new variable x is defined
   1120             // and the value of an existing variable x is assigned. HLSL uses C semantics (the
   1121             // new variable is created before the assignment is evaluated), so we need to convert
   1122             // this to "float t = x, x = t;".
   1123 
   1124             TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
   1125             TIntermTyped *expression = node->getRight();
   1126 
   1127             sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
   1128             expression->traverse(&searchSymbol);
   1129             bool sameSymbol = searchSymbol.foundMatch();
   1130 
   1131             if (sameSymbol)
   1132             {
   1133                 // Type already printed
   1134                 out << "t" + str(mUniqueIndex) + " = ";
   1135                 expression->traverse(this);
   1136                 out << ", ";
   1137                 symbolNode->traverse(this);
   1138                 out << " = t" + str(mUniqueIndex);
   1139 
   1140                 mUniqueIndex++;
   1141                 return false;
   1142             }
   1143         }
   1144         else if (visit == InVisit)
   1145         {
   1146             out << " = ";
   1147         }
   1148         break;
   1149       case EOpAddAssign:               outputTriplet(visit, "(", " += ", ")");          break;
   1150       case EOpSubAssign:               outputTriplet(visit, "(", " -= ", ")");          break;
   1151       case EOpMulAssign:               outputTriplet(visit, "(", " *= ", ")");          break;
   1152       case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
   1153       case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
   1154       case EOpVectorTimesMatrixAssign:
   1155         if (visit == PreVisit)
   1156         {
   1157             out << "(";
   1158         }
   1159         else if (visit == InVisit)
   1160         {
   1161             out << " = mul(";
   1162             node->getLeft()->traverse(this);
   1163             out << ", transpose(";
   1164         }
   1165         else
   1166         {
   1167             out << ")))";
   1168         }
   1169         break;
   1170       case EOpMatrixTimesMatrixAssign:
   1171         if (visit == PreVisit)
   1172         {
   1173             out << "(";
   1174         }
   1175         else if (visit == InVisit)
   1176         {
   1177             out << " = mul(";
   1178             node->getLeft()->traverse(this);
   1179             out << ", ";
   1180         }
   1181         else
   1182         {
   1183             out << "))";
   1184         }
   1185         break;
   1186       case EOpDivAssign:               outputTriplet(visit, "(", " /= ", ")");          break;
   1187       case EOpIndexDirect:             outputTriplet(visit, "", "[", "]");              break;
   1188       case EOpIndexIndirect:           outputTriplet(visit, "", "[", "]");              break;
   1189       case EOpIndexDirectStruct:
   1190         if (visit == InVisit)
   1191         {
   1192             const TStructure* structure = node->getLeft()->getType().getStruct();
   1193             const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
   1194             const TField* field = structure->fields()[index->getIConst(0)];
   1195             out << "." + decorateField(field->name(), node->getLeft()->getType());
   1196 
   1197             return false;
   1198         }
   1199         break;
   1200       case EOpVectorSwizzle:
   1201         if (visit == InVisit)
   1202         {
   1203             out << ".";
   1204 
   1205             TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
   1206 
   1207             if (swizzle)
   1208             {
   1209                 TIntermSequence &sequence = swizzle->getSequence();
   1210 
   1211                 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
   1212                 {
   1213                     TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
   1214 
   1215                     if (element)
   1216                     {
   1217                         int i = element->getIConst(0);
   1218 
   1219                         switch (i)
   1220                         {
   1221                         case 0: out << "x"; break;
   1222                         case 1: out << "y"; break;
   1223                         case 2: out << "z"; break;
   1224                         case 3: out << "w"; break;
   1225                         default: UNREACHABLE();
   1226                         }
   1227                     }
   1228                     else UNREACHABLE();
   1229                 }
   1230             }
   1231             else UNREACHABLE();
   1232 
   1233             return false;   // Fully processed
   1234         }
   1235         break;
   1236       case EOpAdd:               outputTriplet(visit, "(", " + ", ")"); break;
   1237       case EOpSub:               outputTriplet(visit, "(", " - ", ")"); break;
   1238       case EOpMul:               outputTriplet(visit, "(", " * ", ")"); break;
   1239       case EOpDiv:               outputTriplet(visit, "(", " / ", ")"); break;
   1240       case EOpEqual:
   1241       case EOpNotEqual:
   1242         if (node->getLeft()->isScalar())
   1243         {
   1244             if (node->getOp() == EOpEqual)
   1245             {
   1246                 outputTriplet(visit, "(", " == ", ")");
   1247             }
   1248             else
   1249             {
   1250                 outputTriplet(visit, "(", " != ", ")");
   1251             }
   1252         }
   1253         else if (node->getLeft()->getBasicType() == EbtStruct)
   1254         {
   1255             if (node->getOp() == EOpEqual)
   1256             {
   1257                 out << "(";
   1258             }
   1259             else
   1260             {
   1261                 out << "!(";
   1262             }
   1263 
   1264             const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
   1265 
   1266             for (size_t i = 0; i < fields.size(); i++)
   1267             {
   1268                 const TField *field = fields[i];
   1269 
   1270                 node->getLeft()->traverse(this);
   1271                 out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
   1272                 node->getRight()->traverse(this);
   1273                 out << "." + decorateField(field->name(), node->getLeft()->getType());
   1274 
   1275                 if (i < fields.size() - 1)
   1276                 {
   1277                     out << " && ";
   1278                 }
   1279             }
   1280 
   1281             out << ")";
   1282 
   1283             return false;
   1284         }
   1285         else
   1286         {
   1287             ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
   1288 
   1289             if (node->getOp() == EOpEqual)
   1290             {
   1291                 outputTriplet(visit, "all(", " == ", ")");
   1292             }
   1293             else
   1294             {
   1295                 outputTriplet(visit, "!all(", " == ", ")");
   1296             }
   1297         }
   1298         break;
   1299       case EOpLessThan:          outputTriplet(visit, "(", " < ", ")");   break;
   1300       case EOpGreaterThan:       outputTriplet(visit, "(", " > ", ")");   break;
   1301       case EOpLessThanEqual:     outputTriplet(visit, "(", " <= ", ")");  break;
   1302       case EOpGreaterThanEqual:  outputTriplet(visit, "(", " >= ", ")");  break;
   1303       case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
   1304       case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
   1305       case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
   1306       case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
   1307       case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
   1308       case EOpLogicalOr:
   1309         if (node->getRight()->hasSideEffects())
   1310         {
   1311             out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
   1312             return false;
   1313         }
   1314         else
   1315         {
   1316            outputTriplet(visit, "(", " || ", ")");
   1317            return true;
   1318         }
   1319       case EOpLogicalXor:
   1320         mUsesXor = true;
   1321         outputTriplet(visit, "xor(", ", ", ")");
   1322         break;
   1323       case EOpLogicalAnd:
   1324         if (node->getRight()->hasSideEffects())
   1325         {
   1326             out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
   1327             return false;
   1328         }
   1329         else
   1330         {
   1331            outputTriplet(visit, "(", " && ", ")");
   1332            return true;
   1333         }
   1334       default: UNREACHABLE();
   1335     }
   1336 
   1337     return true;
   1338 }
   1339 
   1340 bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
   1341 {
   1342     switch (node->getOp())
   1343     {
   1344       case EOpNegative:         outputTriplet(visit, "(-", "", ")");  break;
   1345       case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");  break;
   1346       case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");  break;
   1347       case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)"); break;
   1348       case EOpPostDecrement:    outputTriplet(visit, "(", "", "--)"); break;
   1349       case EOpPreIncrement:     outputTriplet(visit, "(++", "", ")"); break;
   1350       case EOpPreDecrement:     outputTriplet(visit, "(--", "", ")"); break;
   1351       case EOpConvIntToBool:
   1352       case EOpConvFloatToBool:
   1353         switch (node->getOperand()->getType().getNominalSize())
   1354         {
   1355           case 1:    outputTriplet(visit, "bool(", "", ")");  break;
   1356           case 2:    outputTriplet(visit, "bool2(", "", ")"); break;
   1357           case 3:    outputTriplet(visit, "bool3(", "", ")"); break;
   1358           case 4:    outputTriplet(visit, "bool4(", "", ")"); break;
   1359           default: UNREACHABLE();
   1360         }
   1361         break;
   1362       case EOpConvBoolToFloat:
   1363       case EOpConvIntToFloat:
   1364         switch (node->getOperand()->getType().getNominalSize())
   1365         {
   1366           case 1:    outputTriplet(visit, "float(", "", ")");  break;
   1367           case 2:    outputTriplet(visit, "float2(", "", ")"); break;
   1368           case 3:    outputTriplet(visit, "float3(", "", ")"); break;
   1369           case 4:    outputTriplet(visit, "float4(", "", ")"); break;
   1370           default: UNREACHABLE();
   1371         }
   1372         break;
   1373       case EOpConvFloatToInt:
   1374       case EOpConvBoolToInt:
   1375         switch (node->getOperand()->getType().getNominalSize())
   1376         {
   1377           case 1:    outputTriplet(visit, "int(", "", ")");  break;
   1378           case 2:    outputTriplet(visit, "int2(", "", ")"); break;
   1379           case 3:    outputTriplet(visit, "int3(", "", ")"); break;
   1380           case 4:    outputTriplet(visit, "int4(", "", ")"); break;
   1381           default: UNREACHABLE();
   1382         }
   1383         break;
   1384       case EOpRadians:          outputTriplet(visit, "radians(", "", ")");   break;
   1385       case EOpDegrees:          outputTriplet(visit, "degrees(", "", ")");   break;
   1386       case EOpSin:              outputTriplet(visit, "sin(", "", ")");       break;
   1387       case EOpCos:              outputTriplet(visit, "cos(", "", ")");       break;
   1388       case EOpTan:              outputTriplet(visit, "tan(", "", ")");       break;
   1389       case EOpAsin:             outputTriplet(visit, "asin(", "", ")");      break;
   1390       case EOpAcos:             outputTriplet(visit, "acos(", "", ")");      break;
   1391       case EOpAtan:             outputTriplet(visit, "atan(", "", ")");      break;
   1392       case EOpExp:              outputTriplet(visit, "exp(", "", ")");       break;
   1393       case EOpLog:              outputTriplet(visit, "log(", "", ")");       break;
   1394       case EOpExp2:             outputTriplet(visit, "exp2(", "", ")");      break;
   1395       case EOpLog2:             outputTriplet(visit, "log2(", "", ")");      break;
   1396       case EOpSqrt:             outputTriplet(visit, "sqrt(", "", ")");      break;
   1397       case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", "", ")");     break;
   1398       case EOpAbs:              outputTriplet(visit, "abs(", "", ")");       break;
   1399       case EOpSign:             outputTriplet(visit, "sign(", "", ")");      break;
   1400       case EOpFloor:            outputTriplet(visit, "floor(", "", ")");     break;
   1401       case EOpCeil:             outputTriplet(visit, "ceil(", "", ")");      break;
   1402       case EOpFract:            outputTriplet(visit, "frac(", "", ")");      break;
   1403       case EOpLength:           outputTriplet(visit, "length(", "", ")");    break;
   1404       case EOpNormalize:        outputTriplet(visit, "normalize(", "", ")"); break;
   1405       case EOpDFdx:
   1406         if(mInsideDiscontinuousLoop || mOutputLod0Function)
   1407         {
   1408             outputTriplet(visit, "(", "", ", 0.0)");
   1409         }
   1410         else
   1411         {
   1412             outputTriplet(visit, "ddx(", "", ")");
   1413         }
   1414         break;
   1415       case EOpDFdy:
   1416         if(mInsideDiscontinuousLoop || mOutputLod0Function)
   1417         {
   1418             outputTriplet(visit, "(", "", ", 0.0)");
   1419         }
   1420         else
   1421         {
   1422            outputTriplet(visit, "ddy(", "", ")");
   1423         }
   1424         break;
   1425       case EOpFwidth:
   1426         if(mInsideDiscontinuousLoop || mOutputLod0Function)
   1427         {
   1428             outputTriplet(visit, "(", "", ", 0.0)");
   1429         }
   1430         else
   1431         {
   1432             outputTriplet(visit, "fwidth(", "", ")");
   1433         }
   1434         break;
   1435       case EOpAny:              outputTriplet(visit, "any(", "", ")");       break;
   1436       case EOpAll:              outputTriplet(visit, "all(", "", ")");       break;
   1437       default: UNREACHABLE();
   1438     }
   1439 
   1440     return true;
   1441 }
   1442 
   1443 bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
   1444 {
   1445     TInfoSinkBase &out = mBody;
   1446 
   1447     switch (node->getOp())
   1448     {
   1449       case EOpSequence:
   1450         {
   1451             if (mInsideFunction)
   1452             {
   1453                 outputLineDirective(node->getLine().first_line);
   1454                 out << "{\n";
   1455 
   1456                 mScopeDepth++;
   1457 
   1458                 if (mScopeBracket.size() < mScopeDepth)
   1459                 {
   1460                     mScopeBracket.push_back(0);   // New scope level
   1461                 }
   1462                 else
   1463                 {
   1464                     mScopeBracket[mScopeDepth - 1]++;   // New scope at existing level
   1465                 }
   1466             }
   1467 
   1468             for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
   1469             {
   1470                 outputLineDirective((*sit)->getLine().first_line);
   1471 
   1472                 traverseStatements(*sit);
   1473 
   1474                 out << ";\n";
   1475             }
   1476 
   1477             if (mInsideFunction)
   1478             {
   1479                 outputLineDirective(node->getLine().last_line);
   1480                 out << "}\n";
   1481 
   1482                 mScopeDepth--;
   1483             }
   1484 
   1485             return false;
   1486         }
   1487       case EOpDeclaration:
   1488         if (visit == PreVisit)
   1489         {
   1490             TIntermSequence &sequence = node->getSequence();
   1491             TIntermTyped *variable = sequence[0]->getAsTyped();
   1492 
   1493             if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
   1494             {
   1495                 if (variable->getType().getStruct())
   1496                 {
   1497                     addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
   1498                 }
   1499 
   1500                 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "")   // Variable declaration
   1501                 {
   1502                     if (!mInsideFunction)
   1503                     {
   1504                         out << "static ";
   1505                     }
   1506 
   1507                     out << typeString(variable->getType()) + " ";
   1508 
   1509                     for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
   1510                     {
   1511                         TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
   1512 
   1513                         if (symbol)
   1514                         {
   1515                             symbol->traverse(this);
   1516                             out << arrayString(symbol->getType());
   1517                             out << " = " + initializer(variable->getType());
   1518                         }
   1519                         else
   1520                         {
   1521                             (*sit)->traverse(this);
   1522                         }
   1523 
   1524                         if (*sit != sequence.back())
   1525                         {
   1526                             out << ", ";
   1527                         }
   1528                     }
   1529                 }
   1530                 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "")   // Type (struct) declaration
   1531                 {
   1532                     // Already added to constructor map
   1533                 }
   1534                 else UNREACHABLE();
   1535             }
   1536             else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut))
   1537             {
   1538                 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
   1539                 {
   1540                     TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
   1541 
   1542                     if (symbol)
   1543                     {
   1544                         // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
   1545                         mReferencedVaryings[symbol->getSymbol()] = symbol;
   1546                     }
   1547                     else
   1548                     {
   1549                         (*sit)->traverse(this);
   1550                     }
   1551                 }
   1552             }
   1553 
   1554             return false;
   1555         }
   1556         else if (visit == InVisit)
   1557         {
   1558             out << ", ";
   1559         }
   1560         break;
   1561       case EOpPrototype:
   1562         if (visit == PreVisit)
   1563         {
   1564             out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
   1565 
   1566             TIntermSequence &arguments = node->getSequence();
   1567 
   1568             for (unsigned int i = 0; i < arguments.size(); i++)
   1569             {
   1570                 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
   1571 
   1572                 if (symbol)
   1573                 {
   1574                     out << argumentString(symbol);
   1575 
   1576                     if (i < arguments.size() - 1)
   1577                     {
   1578                         out << ", ";
   1579                     }
   1580                 }
   1581                 else UNREACHABLE();
   1582             }
   1583 
   1584             out << ");\n";
   1585 
   1586             // Also prototype the Lod0 variant if needed
   1587             if (mContainsLoopDiscontinuity && !mOutputLod0Function)
   1588             {
   1589                 mOutputLod0Function = true;
   1590                 node->traverse(this);
   1591                 mOutputLod0Function = false;
   1592             }
   1593 
   1594             return false;
   1595         }
   1596         break;
   1597       case EOpComma:            outputTriplet(visit, "(", ", ", ")");                break;
   1598       case EOpFunction:
   1599         {
   1600             TString name = TFunction::unmangleName(node->getName());
   1601 
   1602             out << typeString(node->getType()) << " ";
   1603 
   1604             if (name == "main")
   1605             {
   1606                 out << "gl_main(";
   1607             }
   1608             else
   1609             {
   1610                 out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
   1611             }
   1612 
   1613             TIntermSequence &sequence = node->getSequence();
   1614             TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
   1615 
   1616             for (unsigned int i = 0; i < arguments.size(); i++)
   1617             {
   1618                 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
   1619 
   1620                 if (symbol)
   1621                 {
   1622                     if (symbol->getType().getStruct())
   1623                     {
   1624                         addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
   1625                     }
   1626 
   1627                     out << argumentString(symbol);
   1628 
   1629                     if (i < arguments.size() - 1)
   1630                     {
   1631                         out << ", ";
   1632                     }
   1633                 }
   1634                 else UNREACHABLE();
   1635             }
   1636 
   1637             out << ")\n"
   1638                 "{\n";
   1639 
   1640             if (sequence.size() > 1)
   1641             {
   1642                 mInsideFunction = true;
   1643                 sequence[1]->traverse(this);
   1644                 mInsideFunction = false;
   1645             }
   1646 
   1647             out << "}\n";
   1648 
   1649             if (mContainsLoopDiscontinuity && !mOutputLod0Function)
   1650             {
   1651                 if (name != "main")
   1652                 {
   1653                     mOutputLod0Function = true;
   1654                     node->traverse(this);
   1655                     mOutputLod0Function = false;
   1656                 }
   1657             }
   1658 
   1659             return false;
   1660         }
   1661         break;
   1662       case EOpFunctionCall:
   1663         {
   1664             TString name = TFunction::unmangleName(node->getName());
   1665             bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
   1666 
   1667             if (node->isUserDefined())
   1668             {
   1669                 out << decorate(name) << (lod0 ? "Lod0(" : "(");
   1670             }
   1671             else
   1672             {
   1673                 if (name == "texture2D")
   1674                 {
   1675                     if (!lod0)
   1676                     {
   1677                         if (node->getSequence().size() == 2)
   1678                         {
   1679                             mUsesTexture2D = true;
   1680                         }
   1681                         else if (node->getSequence().size() == 3)
   1682                         {
   1683                             mUsesTexture2D_bias = true;
   1684                         }
   1685                         else UNREACHABLE();
   1686 
   1687                         out << "gl_texture2D(";
   1688                     }
   1689                     else
   1690                     {
   1691                         if (node->getSequence().size() == 2)
   1692                         {
   1693                             mUsesTexture2DLod0 = true;
   1694                         }
   1695                         else if (node->getSequence().size() == 3)
   1696                         {
   1697                             mUsesTexture2DLod0_bias = true;
   1698                         }
   1699                         else UNREACHABLE();
   1700 
   1701                         out << "gl_texture2DLod0(";
   1702                     }
   1703                 }
   1704                 else if (name == "texture2DProj")
   1705                 {
   1706                     if (!lod0)
   1707                     {
   1708                         if (node->getSequence().size() == 2)
   1709                         {
   1710                             mUsesTexture2DProj = true;
   1711                         }
   1712                         else if (node->getSequence().size() == 3)
   1713                         {
   1714                             mUsesTexture2DProj_bias = true;
   1715                         }
   1716                         else UNREACHABLE();
   1717 
   1718                         out << "gl_texture2DProj(";
   1719                     }
   1720                     else
   1721                     {
   1722                         if (node->getSequence().size() == 2)
   1723                         {
   1724                             mUsesTexture2DProjLod0 = true;
   1725                         }
   1726                         else if (node->getSequence().size() == 3)
   1727                         {
   1728                             mUsesTexture2DProjLod0_bias = true;
   1729                         }
   1730                         else UNREACHABLE();
   1731 
   1732                         out << "gl_texture2DProjLod0(";
   1733                     }
   1734                 }
   1735                 else if (name == "textureCube")
   1736                 {
   1737                     if (!lod0)
   1738                     {
   1739                         if (node->getSequence().size() == 2)
   1740                         {
   1741                             mUsesTextureCube = true;
   1742                         }
   1743                         else if (node->getSequence().size() == 3)
   1744                         {
   1745                             mUsesTextureCube_bias = true;
   1746                         }
   1747                         else UNREACHABLE();
   1748 
   1749                         out << "gl_textureCube(";
   1750                     }
   1751                     else
   1752                     {
   1753                         if (node->getSequence().size() == 2)
   1754                         {
   1755                             mUsesTextureCubeLod0 = true;
   1756                         }
   1757                         else if (node->getSequence().size() == 3)
   1758                         {
   1759                             mUsesTextureCubeLod0_bias = true;
   1760                         }
   1761                         else UNREACHABLE();
   1762 
   1763                         out << "gl_textureCubeLod0(";
   1764                     }
   1765                 }
   1766                 else if (name == "texture2DLod")
   1767                 {
   1768                     if (node->getSequence().size() == 3)
   1769                     {
   1770                         mUsesTexture2DLod = true;
   1771                     }
   1772                     else UNREACHABLE();
   1773 
   1774                     out << "gl_texture2DLod(";
   1775                 }
   1776                 else if (name == "texture2DProjLod")
   1777                 {
   1778                     if (node->getSequence().size() == 3)
   1779                     {
   1780                         mUsesTexture2DProjLod = true;
   1781                     }
   1782                     else UNREACHABLE();
   1783 
   1784                     out << "gl_texture2DProjLod(";
   1785                 }
   1786                 else if (name == "textureCubeLod")
   1787                 {
   1788                     if (node->getSequence().size() == 3)
   1789                     {
   1790                         mUsesTextureCubeLod = true;
   1791                     }
   1792                     else UNREACHABLE();
   1793 
   1794                     out << "gl_textureCubeLod(";
   1795                 }
   1796                 else UNREACHABLE();
   1797             }
   1798 
   1799             TIntermSequence &arguments = node->getSequence();
   1800 
   1801             for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++)
   1802             {
   1803                 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
   1804                 {
   1805                     out << "texture_";
   1806                     (*arg)->traverse(this);
   1807                     out << ", sampler_";
   1808                 }
   1809 
   1810                 (*arg)->traverse(this);
   1811 
   1812                 if (arg < arguments.end() - 1)
   1813                 {
   1814                     out << ", ";
   1815                 }
   1816             }
   1817 
   1818             out << ")";
   1819 
   1820             return false;
   1821         }
   1822         break;
   1823       case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");             break;
   1824       case EOpConstructFloat:
   1825         addConstructor(node->getType(), "vec1", &node->getSequence());
   1826         outputTriplet(visit, "vec1(", "", ")");
   1827         break;
   1828       case EOpConstructVec2:
   1829         addConstructor(node->getType(), "vec2", &node->getSequence());
   1830         outputTriplet(visit, "vec2(", ", ", ")");
   1831         break;
   1832       case EOpConstructVec3:
   1833         addConstructor(node->getType(), "vec3", &node->getSequence());
   1834         outputTriplet(visit, "vec3(", ", ", ")");
   1835         break;
   1836       case EOpConstructVec4:
   1837         addConstructor(node->getType(), "vec4", &node->getSequence());
   1838         outputTriplet(visit, "vec4(", ", ", ")");
   1839         break;
   1840       case EOpConstructBool:
   1841         addConstructor(node->getType(), "bvec1", &node->getSequence());
   1842         outputTriplet(visit, "bvec1(", "", ")");
   1843         break;
   1844       case EOpConstructBVec2:
   1845         addConstructor(node->getType(), "bvec2", &node->getSequence());
   1846         outputTriplet(visit, "bvec2(", ", ", ")");
   1847         break;
   1848       case EOpConstructBVec3:
   1849         addConstructor(node->getType(), "bvec3", &node->getSequence());
   1850         outputTriplet(visit, "bvec3(", ", ", ")");
   1851         break;
   1852       case EOpConstructBVec4:
   1853         addConstructor(node->getType(), "bvec4", &node->getSequence());
   1854         outputTriplet(visit, "bvec4(", ", ", ")");
   1855         break;
   1856       case EOpConstructInt:
   1857         addConstructor(node->getType(), "ivec1", &node->getSequence());
   1858         outputTriplet(visit, "ivec1(", "", ")");
   1859         break;
   1860       case EOpConstructIVec2:
   1861         addConstructor(node->getType(), "ivec2", &node->getSequence());
   1862         outputTriplet(visit, "ivec2(", ", ", ")");
   1863         break;
   1864       case EOpConstructIVec3:
   1865         addConstructor(node->getType(), "ivec3", &node->getSequence());
   1866         outputTriplet(visit, "ivec3(", ", ", ")");
   1867         break;
   1868       case EOpConstructIVec4:
   1869         addConstructor(node->getType(), "ivec4", &node->getSequence());
   1870         outputTriplet(visit, "ivec4(", ", ", ")");
   1871         break;
   1872       case EOpConstructMat2:
   1873         addConstructor(node->getType(), "mat2", &node->getSequence());
   1874         outputTriplet(visit, "mat2(", ", ", ")");
   1875         break;
   1876       case EOpConstructMat3:
   1877         addConstructor(node->getType(), "mat3", &node->getSequence());
   1878         outputTriplet(visit, "mat3(", ", ", ")");
   1879         break;
   1880       case EOpConstructMat4:
   1881         addConstructor(node->getType(), "mat4", &node->getSequence());
   1882         outputTriplet(visit, "mat4(", ", ", ")");
   1883         break;
   1884       case EOpConstructStruct:
   1885         addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
   1886         outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
   1887         break;
   1888       case EOpLessThan:         outputTriplet(visit, "(", " < ", ")");                 break;
   1889       case EOpGreaterThan:      outputTriplet(visit, "(", " > ", ")");                 break;
   1890       case EOpLessThanEqual:    outputTriplet(visit, "(", " <= ", ")");                break;
   1891       case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")");                break;
   1892       case EOpVectorEqual:      outputTriplet(visit, "(", " == ", ")");                break;
   1893       case EOpVectorNotEqual:   outputTriplet(visit, "(", " != ", ")");                break;
   1894       case EOpMod:
   1895         {
   1896             // We need to look at the number of components in both arguments
   1897             switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
   1898                      + node->getSequence()[1]->getAsTyped()->getNominalSize())
   1899             {
   1900               case 11: mUsesMod1 = true; break;
   1901               case 22: mUsesMod2v = true; break;
   1902               case 21: mUsesMod2f = true; break;
   1903               case 33: mUsesMod3v = true; break;
   1904               case 31: mUsesMod3f = true; break;
   1905               case 44: mUsesMod4v = true; break;
   1906               case 41: mUsesMod4f = true; break;
   1907               default: UNREACHABLE();
   1908             }
   1909 
   1910             outputTriplet(visit, "mod(", ", ", ")");
   1911         }
   1912         break;
   1913       case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");               break;
   1914       case EOpAtan:
   1915         ASSERT(node->getSequence().size() == 2);   // atan(x) is a unary operator
   1916         switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
   1917         {
   1918           case 1: mUsesAtan2_1 = true; break;
   1919           case 2: mUsesAtan2_2 = true; break;
   1920           case 3: mUsesAtan2_3 = true; break;
   1921           case 4: mUsesAtan2_4 = true; break;
   1922           default: UNREACHABLE();
   1923         }
   1924         outputTriplet(visit, "atanyx(", ", ", ")");
   1925         break;
   1926       case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
   1927       case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
   1928       case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
   1929       case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
   1930       case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
   1931       case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
   1932       case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;
   1933       case EOpDot:           outputTriplet(visit, "dot(", ", ", ")");           break;
   1934       case EOpCross:         outputTriplet(visit, "cross(", ", ", ")");         break;
   1935       case EOpFaceForward:
   1936         {
   1937             switch (node->getSequence()[0]->getAsTyped()->getNominalSize())   // Number of components in the first argument
   1938             {
   1939             case 1: mUsesFaceforward1 = true; break;
   1940             case 2: mUsesFaceforward2 = true; break;
   1941             case 3: mUsesFaceforward3 = true; break;
   1942             case 4: mUsesFaceforward4 = true; break;
   1943             default: UNREACHABLE();
   1944             }
   1945 
   1946             outputTriplet(visit, "faceforward(", ", ", ")");
   1947         }
   1948         break;
   1949       case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
   1950       case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
   1951       case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
   1952       default: UNREACHABLE();
   1953     }
   1954 
   1955     return true;
   1956 }
   1957 
   1958 bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
   1959 {
   1960     TInfoSinkBase &out = mBody;
   1961 
   1962     if (node->usesTernaryOperator())
   1963     {
   1964         out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
   1965     }
   1966     else  // if/else statement
   1967     {
   1968         mUnfoldShortCircuit->traverse(node->getCondition());
   1969 
   1970         out << "if (";
   1971 
   1972         node->getCondition()->traverse(this);
   1973 
   1974         out << ")\n";
   1975 
   1976         outputLineDirective(node->getLine().first_line);
   1977         out << "{\n";
   1978 
   1979         bool discard = false;
   1980 
   1981         if (node->getTrueBlock())
   1982         {
   1983             traverseStatements(node->getTrueBlock());
   1984 
   1985             // Detect true discard
   1986             discard = (discard || FindDiscard::search(node->getTrueBlock()));
   1987         }
   1988 
   1989         outputLineDirective(node->getLine().first_line);
   1990         out << ";\n}\n";
   1991 
   1992         if (node->getFalseBlock())
   1993         {
   1994             out << "else\n";
   1995 
   1996             outputLineDirective(node->getFalseBlock()->getLine().first_line);
   1997             out << "{\n";
   1998 
   1999             outputLineDirective(node->getFalseBlock()->getLine().first_line);
   2000             traverseStatements(node->getFalseBlock());
   2001 
   2002             outputLineDirective(node->getFalseBlock()->getLine().first_line);
   2003             out << ";\n}\n";
   2004 
   2005             // Detect false discard
   2006             discard = (discard || FindDiscard::search(node->getFalseBlock()));
   2007         }
   2008 
   2009         // ANGLE issue 486: Detect problematic conditional discard
   2010         if (discard && FindSideEffectRewriting::search(node))
   2011         {
   2012             mUsesDiscardRewriting = true;
   2013         }
   2014     }
   2015 
   2016     return false;
   2017 }
   2018 
   2019 void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
   2020 {
   2021     writeConstantUnion(node->getType(), node->getUnionArrayPointer());
   2022 }
   2023 
   2024 bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
   2025 {
   2026     bool wasDiscontinuous = mInsideDiscontinuousLoop;
   2027 
   2028     if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop)
   2029     {
   2030         mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
   2031     }
   2032 
   2033     if (mOutputType == SH_HLSL9_OUTPUT)
   2034     {
   2035         if (handleExcessiveLoop(node))
   2036         {
   2037             return false;
   2038         }
   2039     }
   2040 
   2041     TInfoSinkBase &out = mBody;
   2042 
   2043     if (node->getType() == ELoopDoWhile)
   2044     {
   2045         out << "{do\n";
   2046 
   2047         outputLineDirective(node->getLine().first_line);
   2048         out << "{\n";
   2049     }
   2050     else
   2051     {
   2052         out << "{for(";
   2053 
   2054         if (node->getInit())
   2055         {
   2056             node->getInit()->traverse(this);
   2057         }
   2058 
   2059         out << "; ";
   2060 
   2061         if (node->getCondition())
   2062         {
   2063             node->getCondition()->traverse(this);
   2064         }
   2065 
   2066         out << "; ";
   2067 
   2068         if (node->getExpression())
   2069         {
   2070             node->getExpression()->traverse(this);
   2071         }
   2072 
   2073         out << ")\n";
   2074 
   2075         outputLineDirective(node->getLine().first_line);
   2076         out << "{\n";
   2077     }
   2078 
   2079     if (node->getBody())
   2080     {
   2081         traverseStatements(node->getBody());
   2082     }
   2083 
   2084     outputLineDirective(node->getLine().first_line);
   2085     out << ";}\n";
   2086 
   2087     if (node->getType() == ELoopDoWhile)
   2088     {
   2089         outputLineDirective(node->getCondition()->getLine().first_line);
   2090         out << "while(\n";
   2091 
   2092         node->getCondition()->traverse(this);
   2093 
   2094         out << ");";
   2095     }
   2096 
   2097     out << "}\n";
   2098 
   2099     mInsideDiscontinuousLoop = wasDiscontinuous;
   2100 
   2101     return false;
   2102 }
   2103 
   2104 bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
   2105 {
   2106     TInfoSinkBase &out = mBody;
   2107 
   2108     switch (node->getFlowOp())
   2109     {
   2110       case EOpKill:
   2111         outputTriplet(visit, "discard;\n", "", "");
   2112         break;
   2113       case EOpBreak:
   2114         if (visit == PreVisit)
   2115         {
   2116             if (mExcessiveLoopIndex)
   2117             {
   2118                 out << "{Break";
   2119                 mExcessiveLoopIndex->traverse(this);
   2120                 out << " = true; break;}\n";
   2121             }
   2122             else
   2123             {
   2124                 out << "break;\n";
   2125             }
   2126         }
   2127         break;
   2128       case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
   2129       case EOpReturn:
   2130         if (visit == PreVisit)
   2131         {
   2132             if (node->getExpression())
   2133             {
   2134                 out << "return ";
   2135             }
   2136             else
   2137             {
   2138                 out << "return;\n";
   2139             }
   2140         }
   2141         else if (visit == PostVisit)
   2142         {
   2143             if (node->getExpression())
   2144             {
   2145                 out << ";\n";
   2146             }
   2147         }
   2148         break;
   2149       default: UNREACHABLE();
   2150     }
   2151 
   2152     return true;
   2153 }
   2154 
   2155 void OutputHLSL::traverseStatements(TIntermNode *node)
   2156 {
   2157     if (isSingleStatement(node))
   2158     {
   2159         mUnfoldShortCircuit->traverse(node);
   2160     }
   2161 
   2162     node->traverse(this);
   2163 }
   2164 
   2165 bool OutputHLSL::isSingleStatement(TIntermNode *node)
   2166 {
   2167     TIntermAggregate *aggregate = node->getAsAggregate();
   2168 
   2169     if (aggregate)
   2170     {
   2171         if (aggregate->getOp() == EOpSequence)
   2172         {
   2173             return false;
   2174         }
   2175         else
   2176         {
   2177             for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
   2178             {
   2179                 if (!isSingleStatement(*sit))
   2180                 {
   2181                     return false;
   2182                 }
   2183             }
   2184 
   2185             return true;
   2186         }
   2187     }
   2188 
   2189     return true;
   2190 }
   2191 
   2192 // Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
   2193 // (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
   2194 bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
   2195 {
   2196     const int MAX_LOOP_ITERATIONS = 254;
   2197     TInfoSinkBase &out = mBody;
   2198 
   2199     // Parse loops of the form:
   2200     // for(int index = initial; index [comparator] limit; index += increment)
   2201     TIntermSymbol *index = NULL;
   2202     TOperator comparator = EOpNull;
   2203     int initial = 0;
   2204     int limit = 0;
   2205     int increment = 0;
   2206 
   2207     // Parse index name and intial value
   2208     if (node->getInit())
   2209     {
   2210         TIntermAggregate *init = node->getInit()->getAsAggregate();
   2211 
   2212         if (init)
   2213         {
   2214             TIntermSequence &sequence = init->getSequence();
   2215             TIntermTyped *variable = sequence[0]->getAsTyped();
   2216 
   2217             if (variable && variable->getQualifier() == EvqTemporary)
   2218             {
   2219                 TIntermBinary *assign = variable->getAsBinaryNode();
   2220 
   2221                 if (assign->getOp() == EOpInitialize)
   2222                 {
   2223                     TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
   2224                     TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
   2225 
   2226                     if (symbol && constant)
   2227                     {
   2228                         if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
   2229                         {
   2230                             index = symbol;
   2231                             initial = constant->getIConst(0);
   2232                         }
   2233                     }
   2234                 }
   2235             }
   2236         }
   2237     }
   2238 
   2239     // Parse comparator and limit value
   2240     if (index != NULL && node->getCondition())
   2241     {
   2242         TIntermBinary *test = node->getCondition()->getAsBinaryNode();
   2243 
   2244         if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
   2245         {
   2246             TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
   2247 
   2248             if (constant)
   2249             {
   2250                 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
   2251                 {
   2252                     comparator = test->getOp();
   2253                     limit = constant->getIConst(0);
   2254                 }
   2255             }
   2256         }
   2257     }
   2258 
   2259     // Parse increment
   2260     if (index != NULL && comparator != EOpNull && node->getExpression())
   2261     {
   2262         TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
   2263         TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
   2264 
   2265         if (binaryTerminal)
   2266         {
   2267             TOperator op = binaryTerminal->getOp();
   2268             TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
   2269 
   2270             if (constant)
   2271             {
   2272                 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
   2273                 {
   2274                     int value = constant->getIConst(0);
   2275 
   2276                     switch (op)
   2277                     {
   2278                       case EOpAddAssign: increment = value;  break;
   2279                       case EOpSubAssign: increment = -value; break;
   2280                       default: UNIMPLEMENTED();
   2281                     }
   2282                 }
   2283             }
   2284         }
   2285         else if (unaryTerminal)
   2286         {
   2287             TOperator op = unaryTerminal->getOp();
   2288 
   2289             switch (op)
   2290             {
   2291               case EOpPostIncrement: increment = 1;  break;
   2292               case EOpPostDecrement: increment = -1; break;
   2293               case EOpPreIncrement:  increment = 1;  break;
   2294               case EOpPreDecrement:  increment = -1; break;
   2295               default: UNIMPLEMENTED();
   2296             }
   2297         }
   2298     }
   2299 
   2300     if (index != NULL && comparator != EOpNull && increment != 0)
   2301     {
   2302         if (comparator == EOpLessThanEqual)
   2303         {
   2304             comparator = EOpLessThan;
   2305             limit += 1;
   2306         }
   2307 
   2308         if (comparator == EOpLessThan)
   2309         {
   2310             int iterations = (limit - initial) / increment;
   2311 
   2312             if (iterations <= MAX_LOOP_ITERATIONS)
   2313             {
   2314                 return false;   // Not an excessive loop
   2315             }
   2316 
   2317             TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
   2318             mExcessiveLoopIndex = index;
   2319 
   2320             out << "{int ";
   2321             index->traverse(this);
   2322             out << ";\n"
   2323                    "bool Break";
   2324             index->traverse(this);
   2325             out << " = false;\n";
   2326 
   2327             bool firstLoopFragment = true;
   2328 
   2329             while (iterations > 0)
   2330             {
   2331                 int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
   2332 
   2333                 if (!firstLoopFragment)
   2334                 {
   2335                     out << "if (!Break";
   2336                     index->traverse(this);
   2337                     out << ") {\n";
   2338                 }
   2339 
   2340                 if (iterations <= MAX_LOOP_ITERATIONS)   // Last loop fragment
   2341                 {
   2342                     mExcessiveLoopIndex = NULL;   // Stops setting the Break flag
   2343                 }
   2344 
   2345                 // for(int index = initial; index < clampedLimit; index += increment)
   2346 
   2347                 out << "for(";
   2348                 index->traverse(this);
   2349                 out << " = ";
   2350                 out << initial;
   2351 
   2352                 out << "; ";
   2353                 index->traverse(this);
   2354                 out << " < ";
   2355                 out << clampedLimit;
   2356 
   2357                 out << "; ";
   2358                 index->traverse(this);
   2359                 out << " += ";
   2360                 out << increment;
   2361                 out << ")\n";
   2362 
   2363                 outputLineDirective(node->getLine().first_line);
   2364                 out << "{\n";
   2365 
   2366                 if (node->getBody())
   2367                 {
   2368                     node->getBody()->traverse(this);
   2369                 }
   2370 
   2371                 outputLineDirective(node->getLine().first_line);
   2372                 out << ";}\n";
   2373 
   2374                 if (!firstLoopFragment)
   2375                 {
   2376                     out << "}\n";
   2377                 }
   2378 
   2379                 firstLoopFragment = false;
   2380 
   2381                 initial += MAX_LOOP_ITERATIONS * increment;
   2382                 iterations -= MAX_LOOP_ITERATIONS;
   2383             }
   2384 
   2385             out << "}";
   2386 
   2387             mExcessiveLoopIndex = restoreIndex;
   2388 
   2389             return true;
   2390         }
   2391         else UNIMPLEMENTED();
   2392     }
   2393 
   2394     return false;   // Not handled as an excessive loop
   2395 }
   2396 
   2397 void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
   2398 {
   2399     TInfoSinkBase &out = mBody;
   2400 
   2401     if (visit == PreVisit)
   2402     {
   2403         out << preString;
   2404     }
   2405     else if (visit == InVisit)
   2406     {
   2407         out << inString;
   2408     }
   2409     else if (visit == PostVisit)
   2410     {
   2411         out << postString;
   2412     }
   2413 }
   2414 
   2415 void OutputHLSL::outputLineDirective(int line)
   2416 {
   2417     if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
   2418     {
   2419         mBody << "\n";
   2420         mBody << "#line " << line;
   2421 
   2422         if (mContext.sourcePath)
   2423         {
   2424             mBody << " \"" << mContext.sourcePath << "\"";
   2425         }
   2426 
   2427         mBody << "\n";
   2428     }
   2429 }
   2430 
   2431 TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
   2432 {
   2433     TQualifier qualifier = symbol->getQualifier();
   2434     const TType &type = symbol->getType();
   2435     TString name = symbol->getSymbol();
   2436 
   2437     if (name.empty())   // HLSL demands named arguments, also for prototypes
   2438     {
   2439         name = "x" + str(mUniqueIndex++);
   2440     }
   2441     else
   2442     {
   2443         name = decorate(name);
   2444     }
   2445 
   2446     if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
   2447     {
   2448        return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
   2449               qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type);
   2450     }
   2451 
   2452     return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
   2453 }
   2454 
   2455 TString OutputHLSL::qualifierString(TQualifier qualifier)
   2456 {
   2457     switch(qualifier)
   2458     {
   2459       case EvqIn:            return "in";
   2460       case EvqOut:           return "out";
   2461       case EvqInOut:         return "inout";
   2462       case EvqConstReadOnly: return "const";
   2463       default: UNREACHABLE();
   2464     }
   2465 
   2466     return "";
   2467 }
   2468 
   2469 TString OutputHLSL::typeString(const TType &type)
   2470 {
   2471     if (type.getBasicType() == EbtStruct)
   2472     {
   2473         const TString& typeName = type.getStruct()->name();
   2474         if (typeName != "")
   2475         {
   2476             return structLookup(typeName);
   2477         }
   2478         else   // Nameless structure, define in place
   2479         {
   2480             const TFieldList &fields = type.getStruct()->fields();
   2481 
   2482             TString string = "struct\n"
   2483                              "{\n";
   2484 
   2485             for (unsigned int i = 0; i < fields.size(); i++)
   2486             {
   2487                 const TField *field = fields[i];
   2488 
   2489                 string += "    " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
   2490             }
   2491 
   2492             string += "} ";
   2493 
   2494             return string;
   2495         }
   2496     }
   2497     else if (type.isMatrix())
   2498     {
   2499         switch (type.getNominalSize())
   2500         {
   2501           case 2: return "float2x2";
   2502           case 3: return "float3x3";
   2503           case 4: return "float4x4";
   2504         }
   2505     }
   2506     else
   2507     {
   2508         switch (type.getBasicType())
   2509         {
   2510           case EbtFloat:
   2511             switch (type.getNominalSize())
   2512             {
   2513               case 1: return "float";
   2514               case 2: return "float2";
   2515               case 3: return "float3";
   2516               case 4: return "float4";
   2517             }
   2518           case EbtInt:
   2519             switch (type.getNominalSize())
   2520             {
   2521               case 1: return "int";
   2522               case 2: return "int2";
   2523               case 3: return "int3";
   2524               case 4: return "int4";
   2525             }
   2526           case EbtBool:
   2527             switch (type.getNominalSize())
   2528             {
   2529               case 1: return "bool";
   2530               case 2: return "bool2";
   2531               case 3: return "bool3";
   2532               case 4: return "bool4";
   2533             }
   2534           case EbtVoid:
   2535             return "void";
   2536           case EbtSampler2D:
   2537             return "sampler2D";
   2538           case EbtSamplerCube:
   2539             return "samplerCUBE";
   2540           case EbtSamplerExternalOES:
   2541             return "sampler2D";
   2542           default:
   2543             break;
   2544         }
   2545     }
   2546 
   2547     UNREACHABLE();
   2548     return "<unknown type>";
   2549 }
   2550 
   2551 TString OutputHLSL::textureString(const TType &type)
   2552 {
   2553     switch (type.getBasicType())
   2554     {
   2555       case EbtSampler2D:
   2556         return "Texture2D";
   2557       case EbtSamplerCube:
   2558         return "TextureCube";
   2559       case EbtSamplerExternalOES:
   2560         return "Texture2D";
   2561       default:
   2562         break;
   2563     }
   2564 
   2565     UNREACHABLE();
   2566     return "<unknown texture type>";
   2567 }
   2568 
   2569 TString OutputHLSL::arrayString(const TType &type)
   2570 {
   2571     if (!type.isArray())
   2572     {
   2573         return "";
   2574     }
   2575 
   2576     return "[" + str(type.getArraySize()) + "]";
   2577 }
   2578 
   2579 TString OutputHLSL::initializer(const TType &type)
   2580 {
   2581     TString string;
   2582 
   2583     size_t size = type.getObjectSize();
   2584     for (size_t component = 0; component < size; component++)
   2585     {
   2586         string += "0";
   2587 
   2588         if (component + 1 < size)
   2589         {
   2590             string += ", ";
   2591         }
   2592     }
   2593 
   2594     return "{" + string + "}";
   2595 }
   2596 
   2597 void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
   2598 {
   2599     if (name == "")
   2600     {
   2601         return;   // Nameless structures don't have constructors
   2602     }
   2603 
   2604     if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end())
   2605     {
   2606         return;   // Already added
   2607     }
   2608 
   2609     TType ctorType = type;
   2610     ctorType.clearArrayness();
   2611     ctorType.setPrecision(EbpHigh);
   2612     ctorType.setQualifier(EvqTemporary);
   2613 
   2614     TString ctorName = type.getStruct() ? decorate(name) : name;
   2615 
   2616     typedef std::vector<TType> ParameterArray;
   2617     ParameterArray ctorParameters;
   2618 
   2619     if (type.getStruct())
   2620     {
   2621         mStructNames.insert(decorate(name));
   2622 
   2623         TString structure;
   2624         structure += "struct " + decorate(name) + "\n"
   2625                      "{\n";
   2626 
   2627         const TFieldList &fields = type.getStruct()->fields();
   2628 
   2629         for (unsigned int i = 0; i < fields.size(); i++)
   2630         {
   2631             const TField *field = fields[i];
   2632 
   2633             structure += "    " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
   2634         }
   2635 
   2636         structure += "};\n";
   2637 
   2638         if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
   2639         {
   2640             mStructDeclarations.push_back(structure);
   2641         }
   2642 
   2643         for (unsigned int i = 0; i < fields.size(); i++)
   2644         {
   2645             ctorParameters.push_back(*fields[i]->type());
   2646         }
   2647     }
   2648     else if (parameters)
   2649     {
   2650         for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
   2651         {
   2652             ctorParameters.push_back((*parameter)->getAsTyped()->getType());
   2653         }
   2654     }
   2655     else UNREACHABLE();
   2656 
   2657     TString constructor;
   2658 
   2659     if (ctorType.getStruct())
   2660     {
   2661         constructor += ctorName + " " + ctorName + "_ctor(";
   2662     }
   2663     else   // Built-in type
   2664     {
   2665         constructor += typeString(ctorType) + " " + ctorName + "(";
   2666     }
   2667 
   2668     for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
   2669     {
   2670         const TType &type = ctorParameters[parameter];
   2671 
   2672         constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
   2673 
   2674         if (parameter < ctorParameters.size() - 1)
   2675         {
   2676             constructor += ", ";
   2677         }
   2678     }
   2679 
   2680     constructor += ")\n"
   2681                    "{\n";
   2682 
   2683     if (ctorType.getStruct())
   2684     {
   2685         constructor += "    " + ctorName + " structure = {";
   2686     }
   2687     else
   2688     {
   2689         constructor += "    return " + typeString(ctorType) + "(";
   2690     }
   2691 
   2692     if (ctorType.isMatrix() && ctorParameters.size() == 1)
   2693     {
   2694         int dim = ctorType.getNominalSize();
   2695         const TType &parameter = ctorParameters[0];
   2696 
   2697         if (parameter.isScalar())
   2698         {
   2699             for (int row = 0; row < dim; row++)
   2700             {
   2701                 for (int col = 0; col < dim; col++)
   2702                 {
   2703                     constructor += TString((row == col) ? "x0" : "0.0");
   2704 
   2705                     if (row < dim - 1 || col < dim - 1)
   2706                     {
   2707                         constructor += ", ";
   2708                     }
   2709                 }
   2710             }
   2711         }
   2712         else if (parameter.isMatrix())
   2713         {
   2714             for (int row = 0; row < dim; row++)
   2715             {
   2716                 for (int col = 0; col < dim; col++)
   2717                 {
   2718                     if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
   2719                     {
   2720                         constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
   2721                     }
   2722                     else
   2723                     {
   2724                         constructor += TString((row == col) ? "1.0" : "0.0");
   2725                     }
   2726 
   2727                     if (row < dim - 1 || col < dim - 1)
   2728                     {
   2729                         constructor += ", ";
   2730                     }
   2731                 }
   2732             }
   2733         }
   2734         else UNREACHABLE();
   2735     }
   2736     else
   2737     {
   2738         size_t remainingComponents = ctorType.getObjectSize();
   2739         size_t parameterIndex = 0;
   2740 
   2741         while (remainingComponents > 0)
   2742         {
   2743             const TType &parameter = ctorParameters[parameterIndex];
   2744             const size_t parameterSize = parameter.getObjectSize();
   2745             bool moreParameters = parameterIndex + 1 < ctorParameters.size();
   2746 
   2747             constructor += "x" + str(parameterIndex);
   2748 
   2749             if (parameter.isScalar())
   2750             {
   2751                 ASSERT(parameterSize <= remainingComponents);
   2752                 remainingComponents -= parameterSize;
   2753             }
   2754             else if (parameter.isVector())
   2755             {
   2756                 if (remainingComponents == parameterSize || moreParameters)
   2757                 {
   2758                     ASSERT(parameterSize <= remainingComponents);
   2759                     remainingComponents -= parameterSize;
   2760                 }
   2761                 else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
   2762                 {
   2763                     switch (remainingComponents)
   2764                     {
   2765                       case 1: constructor += ".x";    break;
   2766                       case 2: constructor += ".xy";   break;
   2767                       case 3: constructor += ".xyz";  break;
   2768                       case 4: constructor += ".xyzw"; break;
   2769                       default: UNREACHABLE();
   2770                     }
   2771 
   2772                     remainingComponents = 0;
   2773                 }
   2774                 else UNREACHABLE();
   2775             }
   2776             else if (parameter.isMatrix() || parameter.getStruct())
   2777             {
   2778                 ASSERT(remainingComponents == parameterSize || moreParameters);
   2779                 ASSERT(parameterSize <= remainingComponents);
   2780 
   2781                 remainingComponents -= parameterSize;
   2782             }
   2783             else UNREACHABLE();
   2784 
   2785             if (moreParameters)
   2786             {
   2787                 parameterIndex++;
   2788             }
   2789 
   2790             if (remainingComponents)
   2791             {
   2792                 constructor += ", ";
   2793             }
   2794         }
   2795     }
   2796 
   2797     if (ctorType.getStruct())
   2798     {
   2799         constructor += "};\n"
   2800                        "    return structure;\n"
   2801                        "}\n";
   2802     }
   2803     else
   2804     {
   2805         constructor += ");\n"
   2806                        "}\n";
   2807     }
   2808 
   2809     mConstructors.insert(constructor);
   2810 }
   2811 
   2812 const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
   2813 {
   2814     TInfoSinkBase &out = mBody;
   2815 
   2816     if (type.getBasicType() == EbtStruct)
   2817     {
   2818         out << structLookup(type.getStruct()->name()) + "_ctor(";
   2819 
   2820         const TFieldList &fields = type.getStruct()->fields();
   2821 
   2822         for (size_t i = 0; i < fields.size(); i++)
   2823         {
   2824             const TType *fieldType = fields[i]->type();
   2825 
   2826             constUnion = writeConstantUnion(*fieldType, constUnion);
   2827 
   2828             if (i != fields.size() - 1)
   2829             {
   2830                 out << ", ";
   2831             }
   2832         }
   2833 
   2834         out << ")";
   2835     }
   2836     else
   2837     {
   2838         size_t size = type.getObjectSize();
   2839         bool writeType = size > 1;
   2840 
   2841         if (writeType)
   2842         {
   2843             out << typeString(type) << "(";
   2844         }
   2845 
   2846         for (size_t i = 0; i < size; i++, constUnion++)
   2847         {
   2848             switch (constUnion->getType())
   2849             {
   2850               case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break;
   2851               case EbtInt:   out << constUnion->getIConst(); break;
   2852               case EbtBool:  out << constUnion->getBConst(); break;
   2853               default: UNREACHABLE();
   2854             }
   2855 
   2856             if (i != size - 1)
   2857             {
   2858                 out << ", ";
   2859             }
   2860         }
   2861 
   2862         if (writeType)
   2863         {
   2864             out << ")";
   2865         }
   2866     }
   2867 
   2868     return constUnion;
   2869 }
   2870 
   2871 TString OutputHLSL::scopeString(unsigned int depthLimit)
   2872 {
   2873     TString string;
   2874 
   2875     for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
   2876     {
   2877         string += "_" + str(i);
   2878     }
   2879 
   2880     return string;
   2881 }
   2882 
   2883 TString OutputHLSL::scopedStruct(const TString &typeName)
   2884 {
   2885     if (typeName == "")
   2886     {
   2887         return typeName;
   2888     }
   2889 
   2890     return typeName + scopeString(mScopeDepth);
   2891 }
   2892 
   2893 TString OutputHLSL::structLookup(const TString &typeName)
   2894 {
   2895     for (int depth = mScopeDepth; depth >= 0; depth--)
   2896     {
   2897         TString scopedName = decorate(typeName + scopeString(depth));
   2898 
   2899         for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
   2900         {
   2901             if (*structName == scopedName)
   2902             {
   2903                 return scopedName;
   2904             }
   2905         }
   2906     }
   2907 
   2908     UNREACHABLE();   // Should have found a matching constructor
   2909 
   2910     return typeName;
   2911 }
   2912 
   2913 TString OutputHLSL::decorate(const TString &string)
   2914 {
   2915     if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
   2916     {
   2917         return "_" + string;
   2918     }
   2919 
   2920     return string;
   2921 }
   2922 
   2923 TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
   2924 {
   2925     if (type.getBasicType() == EbtSamplerExternalOES)
   2926     {
   2927         return "ex_" + string;
   2928     }
   2929 
   2930     return decorate(string);
   2931 }
   2932 
   2933 TString OutputHLSL::decorateField(const TString &string, const TType &structure)
   2934 {
   2935     if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
   2936     {
   2937         return decorate(string);
   2938     }
   2939 
   2940     return string;
   2941 }
   2942 
   2943 TString OutputHLSL::registerString(TIntermSymbol *operand)
   2944 {
   2945     ASSERT(operand->getQualifier() == EvqUniform);
   2946 
   2947     if (IsSampler(operand->getBasicType()))
   2948     {
   2949         return "s" + str(samplerRegister(operand));
   2950     }
   2951 
   2952     return "c" + str(uniformRegister(operand));
   2953 }
   2954 
   2955 int OutputHLSL::samplerRegister(TIntermSymbol *sampler)
   2956 {
   2957     const TType &type = sampler->getType();
   2958     ASSERT(IsSampler(type.getBasicType()));
   2959 
   2960     int index = mSamplerRegister;
   2961     mSamplerRegister += sampler->totalRegisterCount();
   2962 
   2963     declareUniform(type, sampler->getSymbol(), index);
   2964 
   2965     return index;
   2966 }
   2967 
   2968 int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
   2969 {
   2970     const TType &type = uniform->getType();
   2971     ASSERT(!IsSampler(type.getBasicType()));
   2972 
   2973     int index = mUniformRegister;
   2974     mUniformRegister += uniform->totalRegisterCount();
   2975 
   2976     declareUniform(type, uniform->getSymbol(), index);
   2977 
   2978     return index;
   2979 }
   2980 
   2981 void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
   2982 {
   2983     TStructure *structure = type.getStruct();
   2984 
   2985     if (!structure)
   2986     {
   2987         mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index));
   2988     }
   2989     else
   2990     {
   2991         const TFieldList &fields = structure->fields();
   2992 
   2993         if (type.isArray())
   2994         {
   2995             int elementIndex = index;
   2996 
   2997             for (int i = 0; i < type.getArraySize(); i++)
   2998             {
   2999                 for (size_t j = 0; j < fields.size(); j++)
   3000                 {
   3001                     const TType &fieldType = *fields[j]->type();
   3002                     const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name();
   3003                     declareUniform(fieldType, uniformName, elementIndex);
   3004                     elementIndex += fieldType.totalRegisterCount();
   3005                 }
   3006             }
   3007         }
   3008         else
   3009         {
   3010             int fieldIndex = index;
   3011 
   3012             for (size_t i = 0; i < fields.size(); i++)
   3013             {
   3014                 const TType &fieldType = *fields[i]->type();
   3015                 const TString uniformName = name + "." + fields[i]->name();
   3016                 declareUniform(fieldType, uniformName, fieldIndex);
   3017                 fieldIndex += fieldType.totalRegisterCount();
   3018             }
   3019         }
   3020     }
   3021 }
   3022 
   3023 GLenum OutputHLSL::glVariableType(const TType &type)
   3024 {
   3025     if (type.getBasicType() == EbtFloat)
   3026     {
   3027         if (type.isScalar())
   3028         {
   3029             return GL_FLOAT;
   3030         }
   3031         else if (type.isVector())
   3032         {
   3033             switch(type.getNominalSize())
   3034             {
   3035               case 2: return GL_FLOAT_VEC2;
   3036               case 3: return GL_FLOAT_VEC3;
   3037               case 4: return GL_FLOAT_VEC4;
   3038               default: UNREACHABLE();
   3039             }
   3040         }
   3041         else if (type.isMatrix())
   3042         {
   3043             switch(type.getNominalSize())
   3044             {
   3045               case 2: return GL_FLOAT_MAT2;
   3046               case 3: return GL_FLOAT_MAT3;
   3047               case 4: return GL_FLOAT_MAT4;
   3048               default: UNREACHABLE();
   3049             }
   3050         }
   3051         else UNREACHABLE();
   3052     }
   3053     else if (type.getBasicType() == EbtInt)
   3054     {
   3055         if (type.isScalar())
   3056         {
   3057             return GL_INT;
   3058         }
   3059         else if (type.isVector())
   3060         {
   3061             switch(type.getNominalSize())
   3062             {
   3063               case 2: return GL_INT_VEC2;
   3064               case 3: return GL_INT_VEC3;
   3065               case 4: return GL_INT_VEC4;
   3066               default: UNREACHABLE();
   3067             }
   3068         }
   3069         else UNREACHABLE();
   3070     }
   3071     else if (type.getBasicType() == EbtBool)
   3072     {
   3073         if (type.isScalar())
   3074         {
   3075             return GL_BOOL;
   3076         }
   3077         else if (type.isVector())
   3078         {
   3079             switch(type.getNominalSize())
   3080             {
   3081               case 2: return GL_BOOL_VEC2;
   3082               case 3: return GL_BOOL_VEC3;
   3083               case 4: return GL_BOOL_VEC4;
   3084               default: UNREACHABLE();
   3085             }
   3086         }
   3087         else UNREACHABLE();
   3088     }
   3089     else if (type.getBasicType() == EbtSampler2D)
   3090     {
   3091         return GL_SAMPLER_2D;
   3092     }
   3093     else if (type.getBasicType() == EbtSamplerCube)
   3094     {
   3095         return GL_SAMPLER_CUBE;
   3096     }
   3097     else UNREACHABLE();
   3098 
   3099     return GL_NONE;
   3100 }
   3101 
   3102 GLenum OutputHLSL::glVariablePrecision(const TType &type)
   3103 {
   3104     if (type.getBasicType() == EbtFloat)
   3105     {
   3106         switch (type.getPrecision())
   3107         {
   3108           case EbpHigh:   return GL_HIGH_FLOAT;
   3109           case EbpMedium: return GL_MEDIUM_FLOAT;
   3110           case EbpLow:    return GL_LOW_FLOAT;
   3111           case EbpUndefined:
   3112             // Should be defined as the default precision by the parser
   3113           default: UNREACHABLE();
   3114         }
   3115     }
   3116     else if (type.getBasicType() == EbtInt)
   3117     {
   3118         switch (type.getPrecision())
   3119         {
   3120           case EbpHigh:   return GL_HIGH_INT;
   3121           case EbpMedium: return GL_MEDIUM_INT;
   3122           case EbpLow:    return GL_LOW_INT;
   3123           case EbpUndefined:
   3124             // Should be defined as the default precision by the parser
   3125           default: UNREACHABLE();
   3126         }
   3127     }
   3128 
   3129     // Other types (boolean, sampler) don't have a precision
   3130     return GL_NONE;
   3131 }
   3132 
   3133 }
   3134