5520c861b4dd16332df91e44da8fce95985ff4f9
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / OutputHLSL.cpp
1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "compiler/translator/OutputHLSL.h"
8
9 #include "common/angleutils.h"
10 #include "common/utilities.h"
11 #include "common/blocklayout.h"
12 #include "compiler/translator/compilerdebug.h"
13 #include "compiler/translator/InfoSink.h"
14 #include "compiler/translator/DetectDiscontinuity.h"
15 #include "compiler/translator/SearchSymbol.h"
16 #include "compiler/translator/UnfoldShortCircuit.h"
17 #include "compiler/translator/FlagStd140Structs.h"
18 #include "compiler/translator/NodeSearch.h"
19 #include "compiler/translator/RewriteElseBlocks.h"
20
21 #include <algorithm>
22 #include <cfloat>
23 #include <stdio.h>
24
25 namespace sh
26 {
27
28 TString OutputHLSL::TextureFunction::name() const
29 {
30     TString name = "gl_texture";
31
32     if (IsSampler2D(sampler))
33     {
34         name += "2D";
35     }
36     else if (IsSampler3D(sampler))
37     {
38         name += "3D";
39     }
40     else if (IsSamplerCube(sampler))
41     {
42         name += "Cube";
43     }
44     else UNREACHABLE();
45
46     if (proj)
47     {
48         name += "Proj";
49     }
50
51     if (offset)
52     {
53         name += "Offset";
54     }
55
56     switch(method)
57     {
58       case IMPLICIT:                  break;
59       case BIAS:                      break;   // Extra parameter makes the signature unique
60       case LOD:      name += "Lod";   break;
61       case LOD0:     name += "Lod0";  break;
62       case LOD0BIAS: name += "Lod0";  break;   // Extra parameter makes the signature unique
63       case SIZE:     name += "Size";  break;
64       case FETCH:    name += "Fetch"; break;
65       case GRAD:     name += "Grad";  break;
66       default: UNREACHABLE();
67     }
68
69     return name + "(";
70 }
71
72 const char *RegisterPrefix(const TType &type)
73 {
74     if (IsSampler(type.getBasicType()))
75     {
76         return "s";
77     }
78     else
79     {
80         return "c";
81     }
82 }
83
84 bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
85 {
86     if (sampler < rhs.sampler) return true;
87     if (sampler > rhs.sampler) return false;
88
89     if (coords < rhs.coords)   return true;
90     if (coords > rhs.coords)   return false;
91
92     if (!proj && rhs.proj)     return true;
93     if (proj && !rhs.proj)     return false;
94
95     if (!offset && rhs.offset) return true;
96     if (offset && !rhs.offset) return false;
97
98     if (method < rhs.method)   return true;
99     if (method > rhs.method)   return false;
100
101     return false;
102 }
103
104 OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
105     : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
106 {
107     mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
108     mInsideFunction = false;
109
110     mUsesFragColor = false;
111     mUsesFragData = false;
112     mUsesDepthRange = false;
113     mUsesFragCoord = false;
114     mUsesPointCoord = false;
115     mUsesFrontFacing = false;
116     mUsesPointSize = false;
117     mUsesFragDepth = false;
118     mUsesXor = false;
119     mUsesMod1 = false;
120     mUsesMod2v = false;
121     mUsesMod2f = false;
122     mUsesMod3v = false;
123     mUsesMod3f = false;
124     mUsesMod4v = false;
125     mUsesMod4f = false;
126     mUsesFaceforward1 = false;
127     mUsesFaceforward2 = false;
128     mUsesFaceforward3 = false;
129     mUsesFaceforward4 = false;
130     mUsesAtan2_1 = false;
131     mUsesAtan2_2 = false;
132     mUsesAtan2_3 = false;
133     mUsesAtan2_4 = false;
134     mUsesDiscardRewriting = false;
135     mUsesNestedBreak = false;
136
137     mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
138
139     mUniqueIndex = 0;
140
141     mContainsLoopDiscontinuity = false;
142     mOutputLod0Function = false;
143     mInsideDiscontinuousLoop = false;
144     mNestedLoopDepth = 0;
145
146     mExcessiveLoopIndex = NULL;
147
148     if (mOutputType == SH_HLSL9_OUTPUT)
149     {
150         if (mContext.shaderType == SH_FRAGMENT_SHADER)
151         {
152             mUniformRegister = 3;   // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
153         }
154         else
155         {
156             mUniformRegister = 2;   // Reserve registers for dx_DepthRange and dx_ViewAdjust
157         }
158     }
159     else
160     {
161         mUniformRegister = 0;
162     }
163
164     mSamplerRegister = 0;
165     mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
166     mPaddingCounter = 0;
167 }
168
169 OutputHLSL::~OutputHLSL()
170 {
171     delete mUnfoldShortCircuit;
172 }
173
174 void OutputHLSL::output()
175 {
176     mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
177     const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
178     makeFlaggedStructMaps(flaggedStructs);
179
180     // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
181     // use a vertex attribute as a condition, and some related computation in the else block.
182     if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER)
183     {
184         RewriteElseBlocks(mContext.treeRoot);
185     }
186
187     mContext.treeRoot->traverse(this);   // Output the body first to determine what has to go in the header
188     header();
189
190     mContext.infoSink().obj << mHeader.c_str();
191     mContext.infoSink().obj << mBody.c_str();
192 }
193
194 void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs)
195 {
196     for (unsigned int structIndex = 0; structIndex < flaggedStructs.size(); structIndex++)
197     {
198         TIntermTyped *flaggedNode = flaggedStructs[structIndex];
199
200         // This will mark the necessary block elements as referenced
201         flaggedNode->traverse(this);
202         TString structName(mBody.c_str());
203         mBody.erase();
204
205         mFlaggedStructOriginalNames[flaggedNode] = structName;
206
207         for (size_t pos = structName.find('.'); pos != std::string::npos; pos = structName.find('.'))
208         {
209             structName.erase(pos, 1);
210         }
211
212         mFlaggedStructMappedNames[flaggedNode] = "map" + structName;
213     }
214 }
215
216 TInfoSinkBase &OutputHLSL::getBodyStream()
217 {
218     return mBody;
219 }
220
221 const std::vector<gl::Uniform> &OutputHLSL::getUniforms()
222 {
223     return mActiveUniforms;
224 }
225
226 const std::vector<gl::InterfaceBlock> &OutputHLSL::getInterfaceBlocks() const
227 {
228     return mActiveInterfaceBlocks;
229 }
230
231 const std::vector<gl::Attribute> &OutputHLSL::getOutputVariables() const
232 {
233     return mActiveOutputVariables;
234 }
235
236 const std::vector<gl::Attribute> &OutputHLSL::getAttributes() const
237 {
238     return mActiveAttributes;
239 }
240
241 const std::vector<gl::Varying> &OutputHLSL::getVaryings() const
242 {
243     return mActiveVaryings;
244 }
245
246 int OutputHLSL::vectorSize(const TType &type) const
247 {
248     int elementSize = type.isMatrix() ? type.getCols() : 1;
249     int arraySize = type.isArray() ? type.getArraySize() : 1;
250
251     return elementSize * arraySize;
252 }
253
254 TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field)
255 {
256     if (interfaceBlock.hasInstanceName())
257     {
258         return interfaceBlock.name() + "." + field.name();
259     }
260     else
261     {
262         return field.name();
263     }
264 }
265
266 TString OutputHLSL::decoratePrivate(const TString &privateText)
267 {
268     return "dx_" + privateText;
269 }
270
271 TString OutputHLSL::interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlock)
272 {
273     return decoratePrivate(interfaceBlock.name()) + "_type";
274 }
275
276 TString OutputHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
277 {
278     if (!interfaceBlock.hasInstanceName())
279     {
280         return "";
281     }
282     else if (interfaceBlock.isArray())
283     {
284         return decoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
285     }
286     else
287     {
288         return decorate(interfaceBlock.instanceName());
289     }
290 }
291
292 TString OutputHLSL::interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
293 {
294     const TType &fieldType = *field.type();
295     const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
296     ASSERT(matrixPacking != EmpUnspecified);
297
298     if (fieldType.isMatrix())
299     {
300         // Use HLSL row-major packing for GLSL column-major matrices
301         const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
302         return matrixPackString + " " + typeString(fieldType);
303     }
304     else if (fieldType.getStruct())
305     {
306         // Use HLSL row-major packing for GLSL column-major matrices
307         return structureTypeName(*fieldType.getStruct(), matrixPacking == EmpColumnMajor, blockStorage == EbsStd140);
308     }
309     else
310     {
311         return typeString(fieldType);
312     }
313 }
314
315 TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
316 {
317     TString hlsl;
318
319     int elementIndex = 0;
320
321     for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
322     {
323         const TField &field = *interfaceBlock.fields()[typeIndex];
324         const TType &fieldType = *field.type();
325
326         if (blockStorage == EbsStd140)
327         {
328             // 2 and 3 component vector types in some cases need pre-padding
329             hlsl += std140PrePaddingString(fieldType, &elementIndex);
330         }
331
332         hlsl += "    " + interfaceBlockFieldTypeString(field, blockStorage) +
333                 " " + decorate(field.name()) + arrayString(fieldType) + ";\n";
334
335         // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
336         if (blockStorage == EbsStd140)
337         {
338             const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
339             hlsl += std140PostPaddingString(fieldType, useHLSLRowMajorPacking);
340         }
341     }
342
343     return hlsl;
344 }
345
346 TString OutputHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
347 {
348     const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
349
350     return "struct " + interfaceBlockStructNameString(interfaceBlock) + "\n"
351            "{\n" +
352            interfaceBlockFieldString(interfaceBlock, blockStorage) +
353            "};\n\n";
354 }
355
356 TString OutputHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
357 {
358     const TString &arrayIndexString =  (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : "");
359     const TString &blockName = interfaceBlock.name() + arrayIndexString;
360     TString hlsl;
361
362     hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
363             "{\n";
364
365     if (interfaceBlock.hasInstanceName())
366     {
367         hlsl += "    " + interfaceBlockStructNameString(interfaceBlock) + " " + interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
368     }
369     else
370     {
371         const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
372         hlsl += interfaceBlockFieldString(interfaceBlock, blockStorage);
373     }
374
375     hlsl += "};\n\n";
376
377     return hlsl;
378 }
379
380 TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex)
381 {
382     if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
383     {
384         // no padding needed, HLSL will align the field to a new register
385         *elementIndex = 0;
386         return "";
387     }
388
389     const GLenum glType = glVariableType(type);
390     const int numComponents = gl::UniformComponentCount(glType);
391
392     if (numComponents >= 4)
393     {
394         // no padding needed, HLSL will align the field to a new register
395         *elementIndex = 0;
396         return "";
397     }
398
399     if (*elementIndex + numComponents > 4)
400     {
401         // no padding needed, HLSL will align the field to a new register
402         *elementIndex = numComponents;
403         return "";
404     }
405
406     TString padding;
407
408     const int alignment = numComponents == 3 ? 4 : numComponents;
409     const int paddingOffset = (*elementIndex % alignment);
410
411     if (paddingOffset != 0)
412     {
413         // padding is neccessary
414         for (int paddingIndex = paddingOffset; paddingIndex < alignment; paddingIndex++)
415         {
416             padding += "    float pad_" + str(mPaddingCounter++) + ";\n";
417         }
418
419         *elementIndex += (alignment - paddingOffset);
420     }
421
422     *elementIndex += numComponents;
423     *elementIndex %= 4;
424
425     return padding;
426 }
427
428 TString OutputHLSL::std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking)
429 {
430     if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
431     {
432         return "";
433     }
434
435     int numComponents = 0;
436
437     if (type.isMatrix())
438     {
439         // This method can also be called from structureString, which does not use layout qualifiers.
440         // Thus, use the method parameter for determining the matrix packing.
441         //
442         // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
443         // wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
444         //
445         const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
446         const GLenum glType = glVariableType(type);
447         numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
448     }
449     else if (type.getStruct())
450     {
451         const TString &structName = structureTypeName(*type.getStruct(), useHLSLRowMajorPacking, true);
452         numComponents = mStd140StructElementIndexes[structName];
453
454         if (numComponents == 0)
455         {
456             return "";
457         }
458     }
459     else
460     {
461         const GLenum glType = glVariableType(type);
462         numComponents = gl::UniformComponentCount(glType);
463     }
464
465     TString padding;
466     for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
467     {
468         padding += "    float pad_" + str(mPaddingCounter++) + ";\n";
469     }
470     return padding;
471 }
472
473 // Use the same layout for packed and shared
474 void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout)
475 {
476     interfaceBlock->layout = newLayout;
477     interfaceBlock->blockInfo.clear();
478
479     switch (newLayout)
480     {
481       case gl::BLOCKLAYOUT_SHARED:
482       case gl::BLOCKLAYOUT_PACKED:
483         {
484             gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo, gl::HLSLBlockEncoder::ENCODE_PACKED);
485             hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
486             interfaceBlock->dataSize = hlslEncoder.getBlockSize();
487         }
488         break;
489
490       case gl::BLOCKLAYOUT_STANDARD:
491         {
492             gl::Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo);
493             stdEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
494             interfaceBlock->dataSize = stdEncoder.getBlockSize();
495         }
496         break;
497
498       default:
499         UNREACHABLE();
500         break;
501     }
502 }
503
504 gl::BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage)
505 {
506     switch (blockStorage)
507     {
508       case EbsPacked: return gl::BLOCKLAYOUT_PACKED;
509       case EbsShared: return gl::BLOCKLAYOUT_SHARED;
510       case EbsStd140: return gl::BLOCKLAYOUT_STANDARD;
511       default: UNREACHABLE(); return gl::BLOCKLAYOUT_SHARED;
512     }
513 }
514
515 TString OutputHLSL::structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName)
516 {
517     TString init;
518
519     TString preIndentString;
520     TString fullIndentString;
521
522     for (int spaces = 0; spaces < (indent * 4); spaces++)
523     {
524         preIndentString += ' ';
525     }
526
527     for (int spaces = 0; spaces < ((indent+1) * 4); spaces++)
528     {
529         fullIndentString += ' ';
530     }
531
532     init += preIndentString + "{\n";
533
534     const TFieldList &fields = structure.fields();
535     for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
536     {
537         const TField &field = *fields[fieldIndex];
538         const TString &fieldName = rhsStructName + "." + decorate(field.name());
539         const TType &fieldType = *field.type();
540
541         if (fieldType.getStruct())
542         {
543             init += structInitializerString(indent + 1, *fieldType.getStruct(), fieldName);
544         }
545         else
546         {
547             init += fullIndentString + fieldName + ",\n";
548         }
549     }
550
551     init += preIndentString + "}" + (indent == 0 ? ";" : ",") + "\n";
552
553     return init;
554 }
555
556 void OutputHLSL::header()
557 {
558     TInfoSinkBase &out = mHeader;
559
560     TString uniforms;
561     TString interfaceBlocks;
562     TString varyings;
563     TString attributes;
564     TString flaggedStructs;
565
566     for (ReferencedSymbols::const_iterator uniformIt = mReferencedUniforms.begin(); uniformIt != mReferencedUniforms.end(); uniformIt++)
567     {
568         const TIntermSymbol &uniform = *uniformIt->second;
569         const TType &type = uniform.getType();
570         const TString &name = uniform.getSymbol();
571
572         int registerIndex = declareUniformAndAssignRegister(type, name);
573
574         if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
575         {
576             uniforms += "uniform " + samplerString(type) + " sampler_" + decorateUniform(name, type) + arrayString(type) + 
577                         " : register(s" + str(registerIndex) + ");\n";
578
579             uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
580                         " : register(t" + str(registerIndex) + ");\n";
581         }
582         else
583         {
584             const TStructure *structure = type.getStruct();
585             const TString &typeName = (structure ? structureTypeName(*structure, false, false) : typeString(type));
586
587             const TString &registerString = TString("register(") + RegisterPrefix(type) + str(registerIndex) + ")";
588
589             uniforms += "uniform " + typeName + " " + decorateUniform(name, type) + arrayString(type) + " : " + registerString + ";\n";
590         }
591     }
592
593     for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
594     {
595         const TType &nodeType = interfaceBlockIt->second->getType();
596         const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
597         const TFieldList &fieldList = interfaceBlock.fields();
598
599         unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
600         gl::InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize, mInterfaceBlockRegister);
601         for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
602         {
603             const TField &field = *fieldList[typeIndex];
604             const TString &fullUniformName = interfaceBlockFieldString(interfaceBlock, field);
605             declareInterfaceBlockField(*field.type(), fullUniformName, activeBlock.fields);
606         }
607
608         mInterfaceBlockRegister += std::max(1u, arraySize);
609
610         gl::BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlock.blockStorage());
611         setBlockLayout(&activeBlock, blockLayoutType);
612
613         if (interfaceBlock.matrixPacking() == EmpRowMajor)
614         {
615             activeBlock.isRowMajorLayout = true;
616         }
617
618         mActiveInterfaceBlocks.push_back(activeBlock);
619
620         if (interfaceBlock.hasInstanceName())
621         {
622             interfaceBlocks += interfaceBlockStructString(interfaceBlock);
623         }
624
625         if (arraySize > 0)
626         {
627             for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
628             {
629                 interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex + arrayIndex, arrayIndex);
630             }
631         }
632         else
633         {
634             interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex, GL_INVALID_INDEX);
635         }
636     }
637
638     for (std::map<TIntermTyped*, TString>::const_iterator flaggedStructIt = mFlaggedStructMappedNames.begin(); flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++)
639     {
640         TIntermTyped *structNode = flaggedStructIt->first;
641         const TString &mappedName = flaggedStructIt->second;
642         const TStructure &structure = *structNode->getType().getStruct();
643         const TString &originalName = mFlaggedStructOriginalNames[structNode];
644
645         flaggedStructs += "static " + decorate(structure.name()) + " " + mappedName + " =\n";
646         flaggedStructs += structInitializerString(0, structure, originalName);
647         flaggedStructs += "\n";
648     }
649
650     for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
651     {
652         const TType &type = varying->second->getType();
653         const TString &name = varying->second->getSymbol();
654
655         // Program linking depends on this exact format
656         varyings += "static " + interpolationString(type.getQualifier()) + " " + typeString(type) + " " +
657                     decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
658
659         declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings);
660     }
661
662     for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
663     {
664         const TType &type = attribute->second->getType();
665         const TString &name = attribute->second->getSymbol();
666
667         attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
668
669         gl::Attribute attributeVar(glVariableType(type), glVariablePrecision(type), name.c_str(),
670                                (unsigned int)type.getArraySize(), type.getLayoutQualifier().location);
671         mActiveAttributes.push_back(attributeVar);
672     }
673
674     for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
675     {
676         out << *structDeclaration;
677     }
678
679     for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
680     {
681         out << *constructor;
682     }
683
684     if (mUsesDiscardRewriting)
685     {
686         out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
687     }
688
689     if (mUsesNestedBreak)
690     {
691         out << "#define ANGLE_USES_NESTED_BREAK" << "\n";
692     }
693
694     if (mContext.shaderType == SH_FRAGMENT_SHADER)
695     {
696         TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
697         const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
698
699         out << "// Varyings\n";
700         out <<  varyings;
701         out << "\n";
702
703         if (mContext.getShaderVersion() >= 300)
704         {
705             for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
706             {
707                 const TString &variableName = outputVariableIt->first;
708                 const TType &variableType = outputVariableIt->second->getType();
709                 const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier();
710
711                 out << "static " + typeString(variableType) + " out_" + variableName + arrayString(variableType) +
712                        " = " + initializer(variableType) + ";\n";
713
714                 gl::Attribute outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(),
715                                     (unsigned int)variableType.getArraySize(), layoutQualifier.location);
716                 mActiveOutputVariables.push_back(outputVar);
717             }
718         }
719         else
720         {
721             const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
722
723             out << "static float4 gl_Color[" << numColorValues << "] =\n"
724                    "{\n";
725             for (unsigned int i = 0; i < numColorValues; i++)
726             {
727                 out << "    float4(0, 0, 0, 0)";
728                 if (i + 1 != numColorValues)
729                 {
730                     out << ",";
731                 }
732                 out << "\n";
733             }
734
735             out << "};\n";
736         }
737
738         if (mUsesFragDepth)
739         {
740             out << "static float gl_Depth = 0.0;\n";
741         }
742
743         if (mUsesFragCoord)
744         {
745             out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
746         }
747
748         if (mUsesPointCoord)
749         {
750             out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
751         }
752
753         if (mUsesFrontFacing)
754         {
755             out << "static bool gl_FrontFacing = false;\n";
756         }
757
758         out << "\n";
759
760         if (mUsesDepthRange)
761         {
762             out << "struct gl_DepthRangeParameters\n"
763                    "{\n"
764                    "    float near;\n"
765                    "    float far;\n"
766                    "    float diff;\n"
767                    "};\n"
768                    "\n";
769         }
770
771         if (mOutputType == SH_HLSL11_OUTPUT)
772         {
773             out << "cbuffer DriverConstants : register(b1)\n"
774                    "{\n";
775
776             if (mUsesDepthRange)
777             {
778                 out << "    float3 dx_DepthRange : packoffset(c0);\n";
779             }
780
781             if (mUsesFragCoord)
782             {
783                 out << "    float4 dx_ViewCoords : packoffset(c1);\n";
784             }
785
786             if (mUsesFragCoord || mUsesFrontFacing)
787             {
788                 out << "    float3 dx_DepthFront : packoffset(c2);\n";
789             }
790
791             out << "};\n";
792         }
793         else
794         {
795             if (mUsesDepthRange)
796             {
797                 out << "uniform float3 dx_DepthRange : register(c0);";
798             }
799
800             if (mUsesFragCoord)
801             {
802                 out << "uniform float4 dx_ViewCoords : register(c1);\n";
803             }
804
805             if (mUsesFragCoord || mUsesFrontFacing)
806             {
807                 out << "uniform float3 dx_DepthFront : register(c2);\n";
808             }
809         }
810
811         out << "\n";
812
813         if (mUsesDepthRange)
814         {
815             out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
816                    "\n";
817         }
818         
819         out <<  uniforms;
820         out << "\n";
821
822         if (!interfaceBlocks.empty())
823         {
824             out << interfaceBlocks;
825             out << "\n";
826
827             if (!flaggedStructs.empty())
828             {
829                 out << "// Std140 Structures accessed by value\n";
830                 out << "\n";
831                 out << flaggedStructs;
832                 out << "\n";
833             }
834         }
835
836         if (usingMRTExtension && mNumRenderTargets > 1)
837         {
838             out << "#define GL_USES_MRT\n";
839         }
840
841         if (mUsesFragColor)
842         {
843             out << "#define GL_USES_FRAG_COLOR\n";
844         }
845
846         if (mUsesFragData)
847         {
848             out << "#define GL_USES_FRAG_DATA\n";
849         }
850     }
851     else   // Vertex shader
852     {
853         out << "// Attributes\n";
854         out <<  attributes;
855         out << "\n"
856                "static float4 gl_Position = float4(0, 0, 0, 0);\n";
857         
858         if (mUsesPointSize)
859         {
860             out << "static float gl_PointSize = float(1);\n";
861         }
862
863         out << "\n"
864                "// Varyings\n";
865         out <<  varyings;
866         out << "\n";
867
868         if (mUsesDepthRange)
869         {
870             out << "struct gl_DepthRangeParameters\n"
871                    "{\n"
872                    "    float near;\n"
873                    "    float far;\n"
874                    "    float diff;\n"
875                    "};\n"
876                    "\n";
877         }
878
879         if (mOutputType == SH_HLSL11_OUTPUT)
880         {
881             if (mUsesDepthRange)
882             {
883                 out << "cbuffer DriverConstants : register(b1)\n"
884                        "{\n"
885                        "    float3 dx_DepthRange : packoffset(c0);\n"
886                        "};\n"
887                        "\n";
888             }
889         }
890         else
891         {
892             if (mUsesDepthRange)
893             {
894                 out << "uniform float3 dx_DepthRange : register(c0);\n";
895             }
896
897             out << "uniform float4 dx_ViewAdjust : register(c1);\n"
898                    "\n";
899         }
900
901         if (mUsesDepthRange)
902         {
903             out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
904                    "\n";
905         }
906
907         out << uniforms;
908         out << "\n";
909         
910         if (!interfaceBlocks.empty())
911         {
912             out << interfaceBlocks;
913             out << "\n";
914
915             if (!flaggedStructs.empty())
916             {
917                 out << "// Std140 Structures accessed by value\n";
918                 out << "\n";
919                 out << flaggedStructs;
920                 out << "\n";
921             }
922         }
923     }
924
925     for (TextureFunctionSet::const_iterator textureFunction = mUsesTexture.begin(); textureFunction != mUsesTexture.end(); textureFunction++)
926     {
927         // Return type
928         if (textureFunction->method == TextureFunction::SIZE)
929         {
930             switch(textureFunction->sampler)
931             {
932               case EbtSampler2D:            out << "int2 "; break;
933               case EbtSampler3D:            out << "int3 "; break;
934               case EbtSamplerCube:          out << "int2 "; break;
935               case EbtSampler2DArray:       out << "int3 "; break;
936               case EbtISampler2D:           out << "int2 "; break;
937               case EbtISampler3D:           out << "int3 "; break;
938               case EbtISamplerCube:         out << "int2 "; break;
939               case EbtISampler2DArray:      out << "int3 "; break;
940               case EbtUSampler2D:           out << "int2 "; break;
941               case EbtUSampler3D:           out << "int3 "; break;
942               case EbtUSamplerCube:         out << "int2 "; break;
943               case EbtUSampler2DArray:      out << "int3 "; break;
944               case EbtSampler2DShadow:      out << "int2 "; break;
945               case EbtSamplerCubeShadow:    out << "int2 "; break;
946               case EbtSampler2DArrayShadow: out << "int3 "; break;
947               default: UNREACHABLE();
948             }
949         }
950         else   // Sampling function
951         {
952             switch(textureFunction->sampler)
953             {
954               case EbtSampler2D:            out << "float4 "; break;
955               case EbtSampler3D:            out << "float4 "; break;
956               case EbtSamplerCube:          out << "float4 "; break;
957               case EbtSampler2DArray:       out << "float4 "; break;
958               case EbtISampler2D:           out << "int4 ";   break;
959               case EbtISampler3D:           out << "int4 ";   break;
960               case EbtISamplerCube:         out << "int4 ";   break;
961               case EbtISampler2DArray:      out << "int4 ";   break;
962               case EbtUSampler2D:           out << "uint4 ";  break;
963               case EbtUSampler3D:           out << "uint4 ";  break;
964               case EbtUSamplerCube:         out << "uint4 ";  break;
965               case EbtUSampler2DArray:      out << "uint4 ";  break;
966               case EbtSampler2DShadow:      out << "float ";  break;
967               case EbtSamplerCubeShadow:    out << "float ";  break;
968               case EbtSampler2DArrayShadow: out << "float ";  break;
969               default: UNREACHABLE();
970             }
971         }
972
973         // Function name
974         out << textureFunction->name();
975
976         // Argument list
977         int hlslCoords = 4;
978
979         if (mOutputType == SH_HLSL9_OUTPUT)
980         {
981             switch(textureFunction->sampler)
982             {
983               case EbtSampler2D:   out << "sampler2D s";   hlslCoords = 2; break;
984               case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break;
985               default: UNREACHABLE();
986             }
987
988             switch(textureFunction->method)
989             {
990               case TextureFunction::IMPLICIT:                 break;
991               case TextureFunction::BIAS:     hlslCoords = 4; break;
992               case TextureFunction::LOD:      hlslCoords = 4; break;
993               case TextureFunction::LOD0:     hlslCoords = 4; break;
994               case TextureFunction::LOD0BIAS: hlslCoords = 4; break;
995               default: UNREACHABLE();
996             }
997         }
998         else if (mOutputType == SH_HLSL11_OUTPUT)
999         {
1000             switch(textureFunction->sampler)
1001             {
1002               case EbtSampler2D:            out << "Texture2D x, SamplerState s";                hlslCoords = 2; break;
1003               case EbtSampler3D:            out << "Texture3D x, SamplerState s";                hlslCoords = 3; break;
1004               case EbtSamplerCube:          out << "TextureCube x, SamplerState s";              hlslCoords = 3; break;
1005               case EbtSampler2DArray:       out << "Texture2DArray x, SamplerState s";           hlslCoords = 3; break;
1006               case EbtISampler2D:           out << "Texture2D<int4> x, SamplerState s";          hlslCoords = 2; break;
1007               case EbtISampler3D:           out << "Texture3D<int4> x, SamplerState s";          hlslCoords = 3; break;
1008               case EbtISamplerCube:         out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
1009               case EbtISampler2DArray:      out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
1010               case EbtUSampler2D:           out << "Texture2D<uint4> x, SamplerState s";         hlslCoords = 2; break;
1011               case EbtUSampler3D:           out << "Texture3D<uint4> x, SamplerState s";         hlslCoords = 3; break;
1012               case EbtUSamplerCube:         out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
1013               case EbtUSampler2DArray:      out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
1014               case EbtSampler2DShadow:      out << "Texture2D x, SamplerComparisonState s";      hlslCoords = 2; break;
1015               case EbtSamplerCubeShadow:    out << "TextureCube x, SamplerComparisonState s";    hlslCoords = 3; break;
1016               case EbtSampler2DArrayShadow: out << "Texture2DArray x, SamplerComparisonState s"; hlslCoords = 3; break;
1017               default: UNREACHABLE();
1018             }
1019         }
1020         else UNREACHABLE();
1021
1022         if (textureFunction->method == TextureFunction::FETCH)   // Integer coordinates
1023         {
1024             switch(textureFunction->coords)
1025             {
1026               case 2: out << ", int2 t"; break;
1027               case 3: out << ", int3 t"; break;
1028               default: UNREACHABLE();
1029             }
1030         }
1031         else   // Floating-point coordinates (except textureSize)
1032         {
1033             switch(textureFunction->coords)
1034             {
1035               case 1: out << ", int lod";  break;   // textureSize()
1036               case 2: out << ", float2 t"; break;
1037               case 3: out << ", float3 t"; break;
1038               case 4: out << ", float4 t"; break;
1039               default: UNREACHABLE();
1040             }
1041         }
1042
1043         if (textureFunction->method == TextureFunction::GRAD)
1044         {
1045             switch(textureFunction->sampler)
1046             {
1047               case EbtSampler2D:
1048               case EbtISampler2D:
1049               case EbtUSampler2D:
1050               case EbtSampler2DArray:
1051               case EbtISampler2DArray:
1052               case EbtUSampler2DArray:
1053               case EbtSampler2DShadow:
1054               case EbtSampler2DArrayShadow:
1055                 out << ", float2 ddx, float2 ddy";
1056                 break;
1057               case EbtSampler3D:
1058               case EbtISampler3D:
1059               case EbtUSampler3D:
1060               case EbtSamplerCube:
1061               case EbtISamplerCube:
1062               case EbtUSamplerCube:
1063               case EbtSamplerCubeShadow:
1064                 out << ", float3 ddx, float3 ddy";
1065                 break;
1066               default: UNREACHABLE();
1067             }
1068         }
1069
1070         switch(textureFunction->method)
1071         {
1072           case TextureFunction::IMPLICIT:                        break;
1073           case TextureFunction::BIAS:                            break;   // Comes after the offset parameter
1074           case TextureFunction::LOD:      out << ", float lod";  break;
1075           case TextureFunction::LOD0:                            break;
1076           case TextureFunction::LOD0BIAS:                        break;   // Comes after the offset parameter
1077           case TextureFunction::SIZE:                            break;
1078           case TextureFunction::FETCH:    out << ", int mip";    break;
1079           case TextureFunction::GRAD:                            break;
1080           default: UNREACHABLE();
1081         }
1082
1083         if (textureFunction->offset)
1084         {
1085             switch(textureFunction->sampler)
1086             {
1087               case EbtSampler2D:            out << ", int2 offset"; break;
1088               case EbtSampler3D:            out << ", int3 offset"; break;
1089               case EbtSampler2DArray:       out << ", int2 offset"; break;
1090               case EbtISampler2D:           out << ", int2 offset"; break;
1091               case EbtISampler3D:           out << ", int3 offset"; break;
1092               case EbtISampler2DArray:      out << ", int2 offset"; break;
1093               case EbtUSampler2D:           out << ", int2 offset"; break;
1094               case EbtUSampler3D:           out << ", int3 offset"; break;
1095               case EbtUSampler2DArray:      out << ", int2 offset"; break;
1096               case EbtSampler2DShadow:      out << ", int2 offset"; break;
1097               case EbtSampler2DArrayShadow: out << ", int2 offset"; break;
1098               default: UNREACHABLE();
1099             }
1100         }
1101
1102         if (textureFunction->method == TextureFunction::BIAS ||
1103             textureFunction->method == TextureFunction::LOD0BIAS)
1104         {
1105             out << ", float bias";
1106         }
1107
1108         out << ")\n"
1109                "{\n";
1110
1111         if (textureFunction->method == TextureFunction::SIZE)
1112         {
1113             if (IsSampler2D(textureFunction->sampler) || IsSamplerCube(textureFunction->sampler))
1114             {
1115                 if (IsSamplerArray(textureFunction->sampler))
1116                 {
1117                     out << "    uint width; uint height; uint layers; uint numberOfLevels;\n"
1118                            "    x.GetDimensions(lod, width, height, layers, numberOfLevels);\n";
1119                 }
1120                 else
1121                 {
1122                     out << "    uint width; uint height; uint numberOfLevels;\n"
1123                            "    x.GetDimensions(lod, width, height, numberOfLevels);\n";
1124                 }
1125             }
1126             else if (IsSampler3D(textureFunction->sampler))
1127             {
1128                 out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
1129                        "    x.GetDimensions(lod, width, height, depth, numberOfLevels);\n";
1130             }
1131             else UNREACHABLE();
1132
1133             switch(textureFunction->sampler)
1134             {
1135               case EbtSampler2D:            out << "    return int2(width, height);";         break;
1136               case EbtSampler3D:            out << "    return int3(width, height, depth);";  break;
1137               case EbtSamplerCube:          out << "    return int2(width, height);";         break;
1138               case EbtSampler2DArray:       out << "    return int3(width, height, layers);"; break;
1139               case EbtISampler2D:           out << "    return int2(width, height);";         break;
1140               case EbtISampler3D:           out << "    return int3(width, height, depth);";  break;
1141               case EbtISamplerCube:         out << "    return int2(width, height);";         break;
1142               case EbtISampler2DArray:      out << "    return int3(width, height, layers);"; break;
1143               case EbtUSampler2D:           out << "    return int2(width, height);";         break;
1144               case EbtUSampler3D:           out << "    return int3(width, height, depth);";  break;
1145               case EbtUSamplerCube:         out << "    return int2(width, height);";         break;
1146               case EbtUSampler2DArray:      out << "    return int3(width, height, layers);"; break;
1147               case EbtSampler2DShadow:      out << "    return int2(width, height);";         break;
1148               case EbtSamplerCubeShadow:    out << "    return int2(width, height);";         break;
1149               case EbtSampler2DArrayShadow: out << "    return int3(width, height, layers);"; break;
1150               default: UNREACHABLE();
1151             }
1152         }
1153         else
1154         {
1155             if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
1156             {
1157                 out << "    float width; float height; float layers; float levels;\n";
1158
1159                 out << "    uint mip = 0;\n";
1160
1161                 out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
1162
1163                 out << "    bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
1164                 out << "    bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
1165                 out << "    bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
1166                 out << "    bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || (zMajor && t.z < 0.0f);\n";
1167
1168                 // FACE_POSITIVE_X = 000b
1169                 // FACE_NEGATIVE_X = 001b
1170                 // FACE_POSITIVE_Y = 010b
1171                 // FACE_NEGATIVE_Y = 011b
1172                 // FACE_POSITIVE_Z = 100b
1173                 // FACE_NEGATIVE_Z = 101b
1174                 out << "    int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n";
1175
1176                 out << "    float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n";
1177                 out << "    float v = yMajor ? t.z : (negative ? t.y : -t.y);\n";
1178                 out << "    float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n";
1179
1180                 out << "    t.x = (u * 0.5f / m) + 0.5f;\n";
1181                 out << "    t.y = (v * 0.5f / m) + 0.5f;\n";
1182             }
1183             else if (IsIntegerSampler(textureFunction->sampler) &&
1184                      textureFunction->method != TextureFunction::FETCH)
1185             {
1186                 if (IsSampler2D(textureFunction->sampler))
1187                 {
1188                     if (IsSamplerArray(textureFunction->sampler))
1189                     {
1190                         out << "    float width; float height; float layers; float levels;\n";
1191
1192                         if (textureFunction->method == TextureFunction::LOD0)
1193                         {
1194                             out << "    uint mip = 0;\n";
1195                         }
1196                         else if (textureFunction->method == TextureFunction::LOD0BIAS)
1197                         {
1198                             out << "    uint mip = bias;\n";
1199                         }
1200                         else
1201                         {
1202                             if (textureFunction->method == TextureFunction::IMPLICIT ||
1203                                 textureFunction->method == TextureFunction::BIAS)
1204                             {
1205                                 out << "    x.GetDimensions(0, width, height, layers, levels);\n"
1206                                        "    float2 tSized = float2(t.x * width, t.y * height);\n"
1207                                        "    float dx = length(ddx(tSized));\n"
1208                                        "    float dy = length(ddy(tSized));\n"
1209                                        "    float lod = log2(max(dx, dy));\n";
1210
1211                                 if (textureFunction->method == TextureFunction::BIAS)
1212                                 {
1213                                     out << "    lod += bias;\n";
1214                                 }
1215                             }
1216                             else if (textureFunction->method == TextureFunction::GRAD)
1217                             {
1218                                 out << "    x.GetDimensions(0, width, height, layers, levels);\n"
1219                                        "    float lod = log2(max(length(ddx), length(ddy)));\n";
1220                             }
1221
1222                             out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
1223                         }
1224
1225                         out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
1226                     }
1227                     else
1228                     {
1229                         out << "    float width; float height; float levels;\n";
1230
1231                         if (textureFunction->method == TextureFunction::LOD0)
1232                         {
1233                             out << "    uint mip = 0;\n";
1234                         }
1235                         else if (textureFunction->method == TextureFunction::LOD0BIAS)
1236                         {
1237                             out << "    uint mip = bias;\n";
1238                         }
1239                         else
1240                         {
1241                             if (textureFunction->method == TextureFunction::IMPLICIT ||
1242                                 textureFunction->method == TextureFunction::BIAS)
1243                             {
1244                                 out << "    x.GetDimensions(0, width, height, levels);\n"
1245                                        "    float2 tSized = float2(t.x * width, t.y * height);\n"
1246                                        "    float dx = length(ddx(tSized));\n"
1247                                        "    float dy = length(ddy(tSized));\n"
1248                                        "    float lod = log2(max(dx, dy));\n";
1249
1250                                 if (textureFunction->method == TextureFunction::BIAS)
1251                                 {
1252                                     out << "    lod += bias;\n";
1253                                 }
1254                             }
1255                             else if (textureFunction->method == TextureFunction::LOD)
1256                             {
1257                                 out << "    x.GetDimensions(0, width, height, levels);\n";
1258                             }
1259                             else if (textureFunction->method == TextureFunction::GRAD)
1260                             {
1261                                 out << "    x.GetDimensions(0, width, height, levels);\n"
1262                                        "    float lod = log2(max(length(ddx), length(ddy)));\n";
1263                             }
1264
1265                             out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
1266                         }
1267
1268                         out << "    x.GetDimensions(mip, width, height, levels);\n";
1269                     }
1270                 }
1271                 else if (IsSampler3D(textureFunction->sampler))
1272                 {
1273                     out << "    float width; float height; float depth; float levels;\n";
1274
1275                     if (textureFunction->method == TextureFunction::LOD0)
1276                     {
1277                         out << "    uint mip = 0;\n";
1278                     }
1279                     else if (textureFunction->method == TextureFunction::LOD0BIAS)
1280                     {
1281                         out << "    uint mip = bias;\n";
1282                     }
1283                     else
1284                     {
1285                         if (textureFunction->method == TextureFunction::IMPLICIT ||
1286                             textureFunction->method == TextureFunction::BIAS)
1287                         {
1288                             out << "    x.GetDimensions(0, width, height, depth, levels);\n"
1289                                    "    float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n"
1290                                    "    float dx = length(ddx(tSized));\n"
1291                                    "    float dy = length(ddy(tSized));\n"
1292                                    "    float lod = log2(max(dx, dy));\n";
1293
1294                             if (textureFunction->method == TextureFunction::BIAS)
1295                             {
1296                                 out << "    lod += bias;\n";
1297                             }
1298                         }
1299                         else if (textureFunction->method == TextureFunction::GRAD)
1300                         {
1301                             out << "    x.GetDimensions(0, width, height, depth, levels);\n"
1302                                    "    float lod = log2(max(length(ddx), length(ddy)));\n";
1303                         }
1304
1305                         out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
1306                     }
1307
1308                     out << "    x.GetDimensions(mip, width, height, depth, levels);\n";
1309                 }
1310                 else UNREACHABLE();
1311             }
1312
1313             out << "    return ";
1314
1315             // HLSL intrinsic
1316             if (mOutputType == SH_HLSL9_OUTPUT)
1317             {
1318                 switch(textureFunction->sampler)
1319                 {
1320                   case EbtSampler2D:   out << "tex2D";   break;
1321                   case EbtSamplerCube: out << "texCUBE"; break;
1322                   default: UNREACHABLE();
1323                 }
1324
1325                 switch(textureFunction->method)
1326                 {
1327                   case TextureFunction::IMPLICIT: out << "(s, ";     break;
1328                   case TextureFunction::BIAS:     out << "bias(s, "; break;
1329                   case TextureFunction::LOD:      out << "lod(s, ";  break;
1330                   case TextureFunction::LOD0:     out << "lod(s, ";  break;
1331                   case TextureFunction::LOD0BIAS: out << "lod(s, ";  break;
1332                   default: UNREACHABLE();
1333                 }
1334             }
1335             else if (mOutputType == SH_HLSL11_OUTPUT)
1336             {
1337                 if (textureFunction->method == TextureFunction::GRAD)
1338                 {
1339                     if (IsIntegerSampler(textureFunction->sampler))
1340                     {
1341                         out << "x.Load(";
1342                     }
1343                     else if (IsShadowSampler(textureFunction->sampler))
1344                     {
1345                         out << "x.SampleCmpLevelZero(s, ";
1346                     }
1347                     else
1348                     {
1349                         out << "x.SampleGrad(s, ";
1350                     }
1351                 }
1352                 else if (IsIntegerSampler(textureFunction->sampler) ||
1353                          textureFunction->method == TextureFunction::FETCH)
1354                 {
1355                     out << "x.Load(";
1356                 }
1357                 else if (IsShadowSampler(textureFunction->sampler))
1358                 {
1359                     out << "x.SampleCmp(s, ";
1360                 }
1361                 else
1362                 {
1363                     switch(textureFunction->method)
1364                     {
1365                       case TextureFunction::IMPLICIT: out << "x.Sample(s, ";      break;
1366                       case TextureFunction::BIAS:     out << "x.SampleBias(s, ";  break;
1367                       case TextureFunction::LOD:      out << "x.SampleLevel(s, "; break;
1368                       case TextureFunction::LOD0:     out << "x.SampleLevel(s, "; break;
1369                       case TextureFunction::LOD0BIAS: out << "x.SampleLevel(s, "; break;
1370                       default: UNREACHABLE();
1371                     }
1372                 }
1373             }
1374             else UNREACHABLE();
1375
1376             // Integer sampling requires integer addresses
1377             TString addressx = "";
1378             TString addressy = "";
1379             TString addressz = "";
1380             TString close = "";
1381
1382             if (IsIntegerSampler(textureFunction->sampler) ||
1383                 textureFunction->method == TextureFunction::FETCH)
1384             {
1385                 switch(hlslCoords)
1386                 {
1387                   case 2: out << "int3("; break;
1388                   case 3: out << "int4("; break;
1389                   default: UNREACHABLE();
1390                 }
1391             
1392                 // Convert from normalized floating-point to integer
1393                 if (textureFunction->method != TextureFunction::FETCH)
1394                 {
1395                     addressx = "int(floor(width * frac((";
1396                     addressy = "int(floor(height * frac((";
1397
1398                     if (IsSamplerArray(textureFunction->sampler))
1399                     {
1400                         addressz = "int(max(0, min(layers - 1, floor(0.5 + ";
1401                     }
1402                     else if (IsSamplerCube(textureFunction->sampler))
1403                     {
1404                         addressz = "((((";
1405                     }
1406                     else
1407                     {
1408                         addressz = "int(floor(depth * frac((";
1409                     }
1410
1411                     close = "))))";
1412                 }
1413             }
1414             else
1415             {
1416                 switch(hlslCoords)
1417                 {
1418                   case 2: out << "float2("; break;
1419                   case 3: out << "float3("; break;
1420                   case 4: out << "float4("; break;
1421                   default: UNREACHABLE();
1422                 }
1423             }
1424
1425             TString proj = "";   // Only used for projected textures
1426         
1427             if (textureFunction->proj)
1428             {
1429                 switch(textureFunction->coords)
1430                 {
1431                   case 3: proj = " / t.z"; break;
1432                   case 4: proj = " / t.w"; break;
1433                   default: UNREACHABLE();
1434                 }
1435             }
1436
1437             out << addressx + ("t.x" + proj) + close + ", " + addressy + ("t.y" + proj) + close;
1438
1439             if (mOutputType == SH_HLSL9_OUTPUT)
1440             {
1441                 if (hlslCoords >= 3)
1442                 {
1443                     if (textureFunction->coords < 3)
1444                     {
1445                         out << ", 0";
1446                     }
1447                     else
1448                     {
1449                         out << ", t.z" + proj;
1450                     }
1451                 }
1452
1453                 if (hlslCoords == 4)
1454                 {
1455                     switch(textureFunction->method)
1456                     {
1457                       case TextureFunction::BIAS:     out << ", bias"; break;
1458                       case TextureFunction::LOD:      out << ", lod";  break;
1459                       case TextureFunction::LOD0:     out << ", 0";    break;
1460                       case TextureFunction::LOD0BIAS: out << ", bias"; break;
1461                       default: UNREACHABLE();
1462                     }
1463                 }
1464
1465                 out << "));\n";
1466             }
1467             else if (mOutputType == SH_HLSL11_OUTPUT)
1468             {
1469                 if (hlslCoords >= 3)
1470                 {
1471                     if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
1472                     {
1473                         out << ", face";
1474                     }
1475                     else
1476                     {
1477                         out << ", " + addressz + ("t.z" + proj) + close;
1478                     }
1479                 }
1480
1481                 if (textureFunction->method == TextureFunction::GRAD)
1482                 {
1483                     if (IsIntegerSampler(textureFunction->sampler))
1484                     {
1485                         out << ", mip)";
1486                     }
1487                     else if (IsShadowSampler(textureFunction->sampler))
1488                     {
1489                         // Compare value
1490                         switch(textureFunction->coords)
1491                         {
1492                           case 3: out << "), t.z"; break;
1493                           case 4: out << "), t.w"; break;
1494                           default: UNREACHABLE();
1495                         }
1496                     }
1497                     else
1498                     {
1499                         out << "), ddx, ddy";
1500                     }
1501                 }
1502                 else if (IsIntegerSampler(textureFunction->sampler) ||
1503                          textureFunction->method == TextureFunction::FETCH)
1504                 {
1505                     out << ", mip)";
1506                 }
1507                 else if (IsShadowSampler(textureFunction->sampler))
1508                 {
1509                     // Compare value
1510                     switch(textureFunction->coords)
1511                     {
1512                       case 3: out << "), t.z"; break;
1513                       case 4: out << "), t.w"; break;
1514                       default: UNREACHABLE();
1515                     }
1516                 }
1517                 else
1518                 {
1519                     switch(textureFunction->method)
1520                     {
1521                       case TextureFunction::IMPLICIT: out << ")";       break;
1522                       case TextureFunction::BIAS:     out << "), bias"; break;
1523                       case TextureFunction::LOD:      out << "), lod";  break;
1524                       case TextureFunction::LOD0:     out << "), 0";    break;
1525                       case TextureFunction::LOD0BIAS: out << "), bias"; break;
1526                       default: UNREACHABLE();
1527                     }
1528                 }
1529
1530                 if (textureFunction->offset)
1531                 {
1532                     out << ", offset";
1533                 }
1534
1535                 out << ");";
1536             }
1537             else UNREACHABLE();
1538         }
1539
1540         out << "\n"
1541                "}\n"
1542                "\n";
1543     }
1544
1545     if (mUsesFragCoord)
1546     {
1547         out << "#define GL_USES_FRAG_COORD\n";
1548     }
1549
1550     if (mUsesPointCoord)
1551     {
1552         out << "#define GL_USES_POINT_COORD\n";
1553     }
1554
1555     if (mUsesFrontFacing)
1556     {
1557         out << "#define GL_USES_FRONT_FACING\n";
1558     }
1559
1560     if (mUsesPointSize)
1561     {
1562         out << "#define GL_USES_POINT_SIZE\n";
1563     }
1564
1565     if (mUsesFragDepth)
1566     {
1567         out << "#define GL_USES_FRAG_DEPTH\n";
1568     }
1569
1570     if (mUsesDepthRange)
1571     {
1572         out << "#define GL_USES_DEPTH_RANGE\n";
1573     }
1574
1575     if (mUsesXor)
1576     {
1577         out << "bool xor(bool p, bool q)\n"
1578                "{\n"
1579                "    return (p || q) && !(p && q);\n"
1580                "}\n"
1581                "\n";
1582     }
1583
1584     if (mUsesMod1)
1585     {
1586         out << "float mod(float x, float y)\n"
1587                "{\n"
1588                "    return x - y * floor(x / y);\n"
1589                "}\n"
1590                "\n";
1591     }
1592
1593     if (mUsesMod2v)
1594     {
1595         out << "float2 mod(float2 x, float2 y)\n"
1596                "{\n"
1597                "    return x - y * floor(x / y);\n"
1598                "}\n"
1599                "\n";
1600     }
1601
1602     if (mUsesMod2f)
1603     {
1604         out << "float2 mod(float2 x, float y)\n"
1605                "{\n"
1606                "    return x - y * floor(x / y);\n"
1607                "}\n"
1608                "\n";
1609     }
1610     
1611     if (mUsesMod3v)
1612     {
1613         out << "float3 mod(float3 x, float3 y)\n"
1614                "{\n"
1615                "    return x - y * floor(x / y);\n"
1616                "}\n"
1617                "\n";
1618     }
1619
1620     if (mUsesMod3f)
1621     {
1622         out << "float3 mod(float3 x, float y)\n"
1623                "{\n"
1624                "    return x - y * floor(x / y);\n"
1625                "}\n"
1626                "\n";
1627     }
1628
1629     if (mUsesMod4v)
1630     {
1631         out << "float4 mod(float4 x, float4 y)\n"
1632                "{\n"
1633                "    return x - y * floor(x / y);\n"
1634                "}\n"
1635                "\n";
1636     }
1637
1638     if (mUsesMod4f)
1639     {
1640         out << "float4 mod(float4 x, float y)\n"
1641                "{\n"
1642                "    return x - y * floor(x / y);\n"
1643                "}\n"
1644                "\n";
1645     }
1646
1647     if (mUsesFaceforward1)
1648     {
1649         out << "float faceforward(float N, float I, float Nref)\n"
1650                "{\n"
1651                "    if(dot(Nref, I) >= 0)\n"
1652                "    {\n"
1653                "        return -N;\n"
1654                "    }\n"
1655                "    else\n"
1656                "    {\n"
1657                "        return N;\n"
1658                "    }\n"
1659                "}\n"
1660                "\n";
1661     }
1662
1663     if (mUsesFaceforward2)
1664     {
1665         out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
1666                "{\n"
1667                "    if(dot(Nref, I) >= 0)\n"
1668                "    {\n"
1669                "        return -N;\n"
1670                "    }\n"
1671                "    else\n"
1672                "    {\n"
1673                "        return N;\n"
1674                "    }\n"
1675                "}\n"
1676                "\n";
1677     }
1678
1679     if (mUsesFaceforward3)
1680     {
1681         out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
1682                "{\n"
1683                "    if(dot(Nref, I) >= 0)\n"
1684                "    {\n"
1685                "        return -N;\n"
1686                "    }\n"
1687                "    else\n"
1688                "    {\n"
1689                "        return N;\n"
1690                "    }\n"
1691                "}\n"
1692                "\n";
1693     }
1694
1695     if (mUsesFaceforward4)
1696     {
1697         out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
1698                "{\n"
1699                "    if(dot(Nref, I) >= 0)\n"
1700                "    {\n"
1701                "        return -N;\n"
1702                "    }\n"
1703                "    else\n"
1704                "    {\n"
1705                "        return N;\n"
1706                "    }\n"
1707                "}\n"
1708                "\n";
1709     }
1710
1711     if (mUsesAtan2_1)
1712     {
1713         out << "float atanyx(float y, float x)\n"
1714                "{\n"
1715                "    if(x == 0 && y == 0) x = 1;\n"   // Avoid producing a NaN
1716                "    return atan2(y, x);\n"
1717                "}\n";
1718     }
1719
1720     if (mUsesAtan2_2)
1721     {
1722         out << "float2 atanyx(float2 y, float2 x)\n"
1723                "{\n"
1724                "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1725                "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1726                "    return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
1727                "}\n";
1728     }
1729
1730     if (mUsesAtan2_3)
1731     {
1732         out << "float3 atanyx(float3 y, float3 x)\n"
1733                "{\n"
1734                "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1735                "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1736                "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
1737                "    return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
1738                "}\n";
1739     }
1740
1741     if (mUsesAtan2_4)
1742     {
1743         out << "float4 atanyx(float4 y, float4 x)\n"
1744                "{\n"
1745                "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1746                "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1747                "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
1748                "    if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
1749                "    return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
1750                "}\n";
1751     }
1752 }
1753
1754 void OutputHLSL::visitSymbol(TIntermSymbol *node)
1755 {
1756     TInfoSinkBase &out = mBody;
1757
1758     // Handle accessing std140 structs by value
1759     if (mFlaggedStructMappedNames.count(node) > 0)
1760     {
1761         out << mFlaggedStructMappedNames[node];
1762         return;
1763     }
1764
1765     TString name = node->getSymbol();
1766
1767     if (name == "gl_DepthRange")
1768     {
1769         mUsesDepthRange = true;
1770         out << name;
1771     }
1772     else
1773     {
1774         TQualifier qualifier = node->getQualifier();
1775
1776         if (qualifier == EvqUniform)
1777         {
1778             const TType& nodeType = node->getType();
1779             const TInterfaceBlock* interfaceBlock = nodeType.getInterfaceBlock();
1780
1781             if (interfaceBlock)
1782             {
1783                 mReferencedInterfaceBlocks[interfaceBlock->name()] = node;
1784             }
1785             else
1786             {
1787                 mReferencedUniforms[name] = node;
1788             }
1789
1790             out << decorateUniform(name, nodeType);
1791         }
1792         else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
1793         {
1794             mReferencedAttributes[name] = node;
1795             out << decorate(name);
1796         }
1797         else if (isVarying(qualifier))
1798         {
1799             mReferencedVaryings[name] = node;
1800             out << decorate(name);
1801         }
1802         else if (qualifier == EvqFragmentOut)
1803         {
1804             mReferencedOutputVariables[name] = node;
1805             out << "out_" << name;
1806         }
1807         else if (qualifier == EvqFragColor)
1808         {
1809             out << "gl_Color[0]";
1810             mUsesFragColor = true;
1811         }
1812         else if (qualifier == EvqFragData)
1813         {
1814             out << "gl_Color";
1815             mUsesFragData = true;
1816         }
1817         else if (qualifier == EvqFragCoord)
1818         {
1819             mUsesFragCoord = true;
1820             out << name;
1821         }
1822         else if (qualifier == EvqPointCoord)
1823         {
1824             mUsesPointCoord = true;
1825             out << name;
1826         }
1827         else if (qualifier == EvqFrontFacing)
1828         {
1829             mUsesFrontFacing = true;
1830             out << name;
1831         }
1832         else if (qualifier == EvqPointSize)
1833         {
1834             mUsesPointSize = true;
1835             out << name;
1836         }
1837         else if (name == "gl_FragDepthEXT")
1838         {
1839             mUsesFragDepth = true;
1840             out << "gl_Depth";
1841         }
1842         else if (qualifier == EvqInternal)
1843         {
1844             out << name;
1845         }
1846         else
1847         {
1848             out << decorate(name);
1849         }
1850     }
1851 }
1852
1853 void OutputHLSL::visitRaw(TIntermRaw *node)
1854 {
1855     mBody << node->getRawText();
1856 }
1857
1858 bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
1859 {
1860     TInfoSinkBase &out = mBody;
1861
1862     // Handle accessing std140 structs by value
1863     if (mFlaggedStructMappedNames.count(node) > 0)
1864     {
1865         out << mFlaggedStructMappedNames[node];
1866         return false;
1867     }
1868
1869     switch (node->getOp())
1870     {
1871       case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");           break;
1872       case EOpInitialize:
1873         if (visit == PreVisit)
1874         {
1875             // GLSL allows to write things like "float x = x;" where a new variable x is defined
1876             // and the value of an existing variable x is assigned. HLSL uses C semantics (the
1877             // new variable is created before the assignment is evaluated), so we need to convert
1878             // this to "float t = x, x = t;".
1879
1880             TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
1881             TIntermTyped *expression = node->getRight();
1882
1883             sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
1884             expression->traverse(&searchSymbol);
1885             bool sameSymbol = searchSymbol.foundMatch();
1886
1887             if (sameSymbol)
1888             {
1889                 // Type already printed
1890                 out << "t" + str(mUniqueIndex) + " = ";
1891                 expression->traverse(this);
1892                 out << ", ";
1893                 symbolNode->traverse(this);
1894                 out << " = t" + str(mUniqueIndex);
1895
1896                 mUniqueIndex++;
1897                 return false;
1898             }
1899         }
1900         else if (visit == InVisit)
1901         {
1902             out << " = ";
1903         }
1904         break;
1905       case EOpAddAssign:               outputTriplet(visit, "(", " += ", ")");          break;
1906       case EOpSubAssign:               outputTriplet(visit, "(", " -= ", ")");          break;
1907       case EOpMulAssign:               outputTriplet(visit, "(", " *= ", ")");          break;
1908       case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
1909       case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
1910       case EOpVectorTimesMatrixAssign:
1911         if (visit == PreVisit)
1912         {
1913             out << "(";
1914         }
1915         else if (visit == InVisit)
1916         {
1917             out << " = mul(";
1918             node->getLeft()->traverse(this);
1919             out << ", transpose(";   
1920         }
1921         else
1922         {
1923             out << ")))";
1924         }
1925         break;
1926       case EOpMatrixTimesMatrixAssign:
1927         if (visit == PreVisit)
1928         {
1929             out << "(";
1930         }
1931         else if (visit == InVisit)
1932         {
1933             out << " = mul(";
1934             node->getLeft()->traverse(this);
1935             out << ", ";   
1936         }
1937         else
1938         {
1939             out << "))";
1940         }
1941         break;
1942       case EOpDivAssign:               outputTriplet(visit, "(", " /= ", ")");          break;
1943       case EOpIndexDirect:
1944         {
1945             const TType& leftType = node->getLeft()->getType();
1946             if (leftType.isInterfaceBlock())
1947             {
1948                 if (visit == PreVisit)
1949                 {
1950                     TInterfaceBlock* interfaceBlock = leftType.getInterfaceBlock();
1951                     const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
1952
1953                     mReferencedInterfaceBlocks[interfaceBlock->instanceName()] = node->getLeft()->getAsSymbolNode();
1954                     out << interfaceBlockInstanceString(*interfaceBlock, arrayIndex);
1955
1956                     return false;
1957                 }
1958             }
1959             else
1960             {
1961                 outputTriplet(visit, "", "[", "]");
1962             }
1963         }
1964         break;
1965       case EOpIndexIndirect:
1966         // We do not currently support indirect references to interface blocks
1967         ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
1968         outputTriplet(visit, "", "[", "]");
1969         break;
1970       case EOpIndexDirectStruct:
1971         if (visit == InVisit)
1972         {
1973             const TStructure* structure = node->getLeft()->getType().getStruct();
1974             const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
1975             const TField* field = structure->fields()[index->getIConst(0)];
1976             out << "." + decorateField(field->name(), *structure);
1977
1978             return false;
1979         }
1980         break;
1981       case EOpIndexDirectInterfaceBlock:
1982         if (visit == InVisit)
1983         {
1984             const TInterfaceBlock* interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
1985             const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
1986             const TField* field = interfaceBlock->fields()[index->getIConst(0)];
1987             out << "." + decorate(field->name());
1988
1989             return false;
1990         }
1991         break;
1992       case EOpVectorSwizzle:
1993         if (visit == InVisit)
1994         {
1995             out << ".";
1996
1997             TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
1998
1999             if (swizzle)
2000             {
2001                 TIntermSequence &sequence = swizzle->getSequence();
2002
2003                 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
2004                 {
2005                     TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
2006
2007                     if (element)
2008                     {
2009                         int i = element->getIConst(0);
2010
2011                         switch (i)
2012                         {
2013                         case 0: out << "x"; break;
2014                         case 1: out << "y"; break;
2015                         case 2: out << "z"; break;
2016                         case 3: out << "w"; break;
2017                         default: UNREACHABLE();
2018                         }
2019                     }
2020                     else UNREACHABLE();
2021                 }
2022             }
2023             else UNREACHABLE();
2024
2025             return false;   // Fully processed
2026         }
2027         break;
2028       case EOpAdd:               outputTriplet(visit, "(", " + ", ")"); break;
2029       case EOpSub:               outputTriplet(visit, "(", " - ", ")"); break;
2030       case EOpMul:               outputTriplet(visit, "(", " * ", ")"); break;
2031       case EOpDiv:               outputTriplet(visit, "(", " / ", ")"); break;
2032       case EOpEqual:
2033       case EOpNotEqual:
2034         if (node->getLeft()->isScalar())
2035         {
2036             if (node->getOp() == EOpEqual)
2037             {
2038                 outputTriplet(visit, "(", " == ", ")");
2039             }
2040             else
2041             {
2042                 outputTriplet(visit, "(", " != ", ")");
2043             }
2044         }
2045         else if (node->getLeft()->getBasicType() == EbtStruct)
2046         {
2047             if (node->getOp() == EOpEqual)
2048             {
2049                 out << "(";
2050             }
2051             else
2052             {
2053                 out << "!(";
2054             }
2055
2056             const TStructure &structure = *node->getLeft()->getType().getStruct();
2057             const TFieldList &fields = structure.fields();
2058
2059             for (size_t i = 0; i < fields.size(); i++)
2060             {
2061                 const TField *field = fields[i];
2062
2063                 node->getLeft()->traverse(this);
2064                 out << "." + decorateField(field->name(), structure) + " == ";
2065                 node->getRight()->traverse(this);
2066                 out << "." + decorateField(field->name(), structure);
2067
2068                 if (i < fields.size() - 1)
2069                 {
2070                     out << " && ";
2071                 }
2072             }
2073
2074             out << ")";
2075
2076             return false;
2077         }
2078         else
2079         {
2080             ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
2081
2082             if (node->getOp() == EOpEqual)
2083             {
2084                 outputTriplet(visit, "all(", " == ", ")");
2085             }
2086             else
2087             {
2088                 outputTriplet(visit, "!all(", " == ", ")");
2089             }
2090         }
2091         break;
2092       case EOpLessThan:          outputTriplet(visit, "(", " < ", ")");   break;
2093       case EOpGreaterThan:       outputTriplet(visit, "(", " > ", ")");   break;
2094       case EOpLessThanEqual:     outputTriplet(visit, "(", " <= ", ")");  break;
2095       case EOpGreaterThanEqual:  outputTriplet(visit, "(", " >= ", ")");  break;
2096       case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
2097       case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
2098       case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
2099       case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
2100       case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
2101       case EOpLogicalOr:
2102         if (node->getRight()->hasSideEffects())
2103         {
2104             out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
2105             return false;
2106         }
2107         else
2108         {
2109            outputTriplet(visit, "(", " || ", ")");
2110            return true;
2111         }
2112       case EOpLogicalXor:
2113         mUsesXor = true;
2114         outputTriplet(visit, "xor(", ", ", ")");
2115         break;
2116       case EOpLogicalAnd:
2117         if (node->getRight()->hasSideEffects())
2118         {
2119             out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
2120             return false;
2121         }
2122         else
2123         {
2124            outputTriplet(visit, "(", " && ", ")");
2125            return true;
2126         }
2127       default: UNREACHABLE();
2128     }
2129
2130     return true;
2131 }
2132
2133 bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
2134 {
2135     switch (node->getOp())
2136     {
2137       case EOpNegative:         outputTriplet(visit, "(-", "", ")");  break;
2138       case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");  break;
2139       case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");  break;
2140       case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)"); break;
2141       case EOpPostDecrement:    outputTriplet(visit, "(", "", "--)"); break;
2142       case EOpPreIncrement:     outputTriplet(visit, "(++", "", ")"); break;
2143       case EOpPreDecrement:     outputTriplet(visit, "(--", "", ")"); break;
2144       case EOpConvIntToBool:
2145       case EOpConvUIntToBool:
2146       case EOpConvFloatToBool:
2147         switch (node->getOperand()->getType().getNominalSize())
2148         {
2149           case 1:    outputTriplet(visit, "bool(", "", ")");  break;
2150           case 2:    outputTriplet(visit, "bool2(", "", ")"); break;
2151           case 3:    outputTriplet(visit, "bool3(", "", ")"); break;
2152           case 4:    outputTriplet(visit, "bool4(", "", ")"); break;
2153           default: UNREACHABLE();
2154         }
2155         break;
2156       case EOpConvBoolToFloat:
2157       case EOpConvIntToFloat:
2158       case EOpConvUIntToFloat:
2159         switch (node->getOperand()->getType().getNominalSize())
2160         {
2161           case 1:    outputTriplet(visit, "float(", "", ")");  break;
2162           case 2:    outputTriplet(visit, "float2(", "", ")"); break;
2163           case 3:    outputTriplet(visit, "float3(", "", ")"); break;
2164           case 4:    outputTriplet(visit, "float4(", "", ")"); break;
2165           default: UNREACHABLE();
2166         }
2167         break;
2168       case EOpConvFloatToInt:
2169       case EOpConvBoolToInt:
2170       case EOpConvUIntToInt:
2171         switch (node->getOperand()->getType().getNominalSize())
2172         {
2173           case 1:    outputTriplet(visit, "int(", "", ")");  break;
2174           case 2:    outputTriplet(visit, "int2(", "", ")"); break;
2175           case 3:    outputTriplet(visit, "int3(", "", ")"); break;
2176           case 4:    outputTriplet(visit, "int4(", "", ")"); break;
2177           default: UNREACHABLE();
2178         }
2179         break;
2180       case EOpConvFloatToUInt:
2181       case EOpConvBoolToUInt:
2182       case EOpConvIntToUInt:
2183         switch (node->getOperand()->getType().getNominalSize())
2184         {
2185           case 1:    outputTriplet(visit, "uint(", "", ")");  break;
2186           case 2:    outputTriplet(visit, "uint2(", "", ")");  break;
2187           case 3:    outputTriplet(visit, "uint3(", "", ")");  break;
2188           case 4:    outputTriplet(visit, "uint4(", "", ")");  break;
2189           default: UNREACHABLE();
2190         }
2191         break;
2192       case EOpRadians:          outputTriplet(visit, "radians(", "", ")");   break;
2193       case EOpDegrees:          outputTriplet(visit, "degrees(", "", ")");   break;
2194       case EOpSin:              outputTriplet(visit, "sin(", "", ")");       break;
2195       case EOpCos:              outputTriplet(visit, "cos(", "", ")");       break;
2196       case EOpTan:              outputTriplet(visit, "tan(", "", ")");       break;
2197       case EOpAsin:             outputTriplet(visit, "asin(", "", ")");      break;
2198       case EOpAcos:             outputTriplet(visit, "acos(", "", ")");      break;
2199       case EOpAtan:             outputTriplet(visit, "atan(", "", ")");      break;
2200       case EOpExp:              outputTriplet(visit, "exp(", "", ")");       break;
2201       case EOpLog:              outputTriplet(visit, "log(", "", ")");       break;
2202       case EOpExp2:             outputTriplet(visit, "exp2(", "", ")");      break;
2203       case EOpLog2:             outputTriplet(visit, "log2(", "", ")");      break;
2204       case EOpSqrt:             outputTriplet(visit, "sqrt(", "", ")");      break;
2205       case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", "", ")");     break;
2206       case EOpAbs:              outputTriplet(visit, "abs(", "", ")");       break;
2207       case EOpSign:             outputTriplet(visit, "sign(", "", ")");      break;
2208       case EOpFloor:            outputTriplet(visit, "floor(", "", ")");     break;
2209       case EOpCeil:             outputTriplet(visit, "ceil(", "", ")");      break;
2210       case EOpFract:            outputTriplet(visit, "frac(", "", ")");      break;
2211       case EOpLength:           outputTriplet(visit, "length(", "", ")");    break;
2212       case EOpNormalize:        outputTriplet(visit, "normalize(", "", ")"); break;
2213       case EOpDFdx:
2214         if(mInsideDiscontinuousLoop || mOutputLod0Function)
2215         {
2216             outputTriplet(visit, "(", "", ", 0.0)");
2217         }
2218         else
2219         {
2220             outputTriplet(visit, "ddx(", "", ")");
2221         }
2222         break;
2223       case EOpDFdy:
2224         if(mInsideDiscontinuousLoop || mOutputLod0Function)
2225         {
2226             outputTriplet(visit, "(", "", ", 0.0)");
2227         }
2228         else
2229         {
2230            outputTriplet(visit, "ddy(", "", ")");
2231         }
2232         break;
2233       case EOpFwidth:
2234         if(mInsideDiscontinuousLoop || mOutputLod0Function)
2235         {
2236             outputTriplet(visit, "(", "", ", 0.0)");
2237         }
2238         else
2239         {
2240             outputTriplet(visit, "fwidth(", "", ")");
2241         }
2242         break;
2243       case EOpAny:              outputTriplet(visit, "any(", "", ")");       break;
2244       case EOpAll:              outputTriplet(visit, "all(", "", ")");       break;
2245       default: UNREACHABLE();
2246     }
2247
2248     return true;
2249 }
2250
2251 bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
2252 {
2253     TInfoSinkBase &out = mBody;
2254
2255     switch (node->getOp())
2256     {
2257       case EOpSequence:
2258         {
2259             if (mInsideFunction)
2260             {
2261                 outputLineDirective(node->getLine().first_line);
2262                 out << "{\n";
2263             }
2264
2265             for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
2266             {
2267                 outputLineDirective((*sit)->getLine().first_line);
2268
2269                 traverseStatements(*sit);
2270
2271                 out << ";\n";
2272             }
2273
2274             if (mInsideFunction)
2275             {
2276                 outputLineDirective(node->getLine().last_line);
2277                 out << "}\n";
2278             }
2279
2280             return false;
2281         }
2282       case EOpDeclaration:
2283         if (visit == PreVisit)
2284         {
2285             TIntermSequence &sequence = node->getSequence();
2286             TIntermTyped *variable = sequence[0]->getAsTyped();
2287
2288             if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
2289             {
2290                 if (variable->getType().getStruct())
2291                 {
2292                     addConstructor(variable->getType(), structNameString(*variable->getType().getStruct()), NULL);
2293                 }
2294
2295                 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "")   // Variable declaration
2296                 {
2297                     if (!mInsideFunction)
2298                     {
2299                         out << "static ";
2300                     }
2301
2302                     out << typeString(variable->getType()) + " ";
2303
2304                     for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
2305                     {
2306                         TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
2307
2308                         if (symbol)
2309                         {
2310                             symbol->traverse(this);
2311                             out << arrayString(symbol->getType());
2312                             out << " = " + initializer(symbol->getType());
2313                         }
2314                         else
2315                         {
2316                             (*sit)->traverse(this);
2317                         }
2318
2319                         if (*sit != sequence.back())
2320                         {
2321                             out << ", ";
2322                         }
2323                     }
2324                 }
2325                 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "")   // Type (struct) declaration
2326                 {
2327                     // Already added to constructor map
2328                 }
2329                 else UNREACHABLE();
2330             }
2331             else if (variable && isVaryingOut(variable->getQualifier()))
2332             {
2333                 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
2334                 {
2335                     TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
2336
2337                     if (symbol)
2338                     {
2339                         // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
2340                         mReferencedVaryings[symbol->getSymbol()] = symbol;
2341                     }
2342                     else
2343                     {
2344                         (*sit)->traverse(this);
2345                     }
2346                 }
2347             }
2348
2349             return false;
2350         }
2351         else if (visit == InVisit)
2352         {
2353             out << ", ";
2354         }
2355         break;
2356       case EOpPrototype:
2357         if (visit == PreVisit)
2358         {
2359             out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
2360
2361             TIntermSequence &arguments = node->getSequence();
2362
2363             for (unsigned int i = 0; i < arguments.size(); i++)
2364             {
2365                 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
2366
2367                 if (symbol)
2368                 {
2369                     out << argumentString(symbol);
2370
2371                     if (i < arguments.size() - 1)
2372                     {
2373                         out << ", ";
2374                     }
2375                 }
2376                 else UNREACHABLE();
2377             }
2378
2379             out << ");\n";
2380
2381             // Also prototype the Lod0 variant if needed
2382             if (mContainsLoopDiscontinuity && !mOutputLod0Function)
2383             {
2384                 mOutputLod0Function = true;
2385                 node->traverse(this);
2386                 mOutputLod0Function = false;
2387             }
2388
2389             return false;
2390         }
2391         break;
2392       case EOpComma:            outputTriplet(visit, "(", ", ", ")");                break;
2393       case EOpFunction:
2394         {
2395             TString name = TFunction::unmangleName(node->getName());
2396
2397             out << typeString(node->getType()) << " ";
2398
2399             if (name == "main")
2400             {
2401                 out << "gl_main(";
2402             }
2403             else
2404             {
2405                 out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
2406             }
2407
2408             TIntermSequence &sequence = node->getSequence();
2409             TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
2410
2411             for (unsigned int i = 0; i < arguments.size(); i++)
2412             {
2413                 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
2414
2415                 if (symbol)
2416                 {
2417                     if (symbol->getType().getStruct())
2418                     {
2419                         addConstructor(symbol->getType(), structNameString(*symbol->getType().getStruct()), NULL);
2420                     }
2421
2422                     out << argumentString(symbol);
2423
2424                     if (i < arguments.size() - 1)
2425                     {
2426                         out << ", ";
2427                     }
2428                 }
2429                 else UNREACHABLE();
2430             }
2431
2432             out << ")\n"
2433                 "{\n";
2434             
2435             if (sequence.size() > 1)
2436             {
2437                 mInsideFunction = true;
2438                 sequence[1]->traverse(this);
2439                 mInsideFunction = false;
2440             }
2441             
2442             out << "}\n";
2443
2444             if (mContainsLoopDiscontinuity && !mOutputLod0Function)
2445             {
2446                 if (name != "main")
2447                 {
2448                     mOutputLod0Function = true;
2449                     node->traverse(this);
2450                     mOutputLod0Function = false;
2451                 }
2452             }
2453
2454             return false;
2455         }
2456         break;
2457       case EOpFunctionCall:
2458         {
2459             TString name = TFunction::unmangleName(node->getName());
2460             bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
2461             TIntermSequence &arguments = node->getSequence();
2462
2463             if (node->isUserDefined())
2464             {
2465                 out << decorate(name) << (lod0 ? "Lod0(" : "(");
2466             }
2467             else
2468             {
2469                 TBasicType samplerType = arguments[0]->getAsTyped()->getType().getBasicType();
2470
2471                 TextureFunction textureFunction;
2472                 textureFunction.sampler = samplerType;
2473                 textureFunction.coords = arguments[1]->getAsTyped()->getNominalSize();
2474                 textureFunction.method = TextureFunction::IMPLICIT;
2475                 textureFunction.proj = false;
2476                 textureFunction.offset = false;
2477
2478                 if (name == "texture2D" || name == "textureCube" || name == "texture")
2479                 {
2480                     textureFunction.method = TextureFunction::IMPLICIT;
2481                 }
2482                 else if (name == "texture2DProj" || name == "textureProj")
2483                 {
2484                     textureFunction.method = TextureFunction::IMPLICIT;
2485                     textureFunction.proj = true;
2486                 }
2487                 else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" ||
2488                          name == "texture2DLodEXT" || name == "textureCubeLodEXT")
2489                 {
2490                     textureFunction.method = TextureFunction::LOD;
2491                 }
2492                 else if (name == "texture2DProjLod" || name == "textureProjLod" || name == "texture2DProjLodEXT")
2493                 {
2494                     textureFunction.method = TextureFunction::LOD;
2495                     textureFunction.proj = true;
2496                 }
2497                 else if (name == "textureSize")
2498                 {
2499                     textureFunction.method = TextureFunction::SIZE;
2500                 }
2501                 else if (name == "textureOffset")
2502                 {
2503                     textureFunction.method = TextureFunction::IMPLICIT;
2504                     textureFunction.offset = true;
2505                 }
2506                 else if (name == "textureProjOffset")
2507                 {
2508                     textureFunction.method = TextureFunction::IMPLICIT;
2509                     textureFunction.offset = true;
2510                     textureFunction.proj = true;
2511                 }
2512                 else if (name == "textureLodOffset")
2513                 {
2514                     textureFunction.method = TextureFunction::LOD;
2515                     textureFunction.offset = true;
2516                 }
2517                 else if (name == "textureProjLodOffset")
2518                 {
2519                     textureFunction.method = TextureFunction::LOD;
2520                     textureFunction.proj = true;
2521                     textureFunction.offset = true;
2522                 }
2523                 else if (name == "texelFetch")
2524                 {
2525                     textureFunction.method = TextureFunction::FETCH;
2526                 }
2527                 else if (name == "texelFetchOffset")
2528                 {
2529                     textureFunction.method = TextureFunction::FETCH;
2530                     textureFunction.offset = true;
2531                 }
2532                 else if (name == "textureGrad" || name == "texture2DGradEXT")
2533                 {
2534                     textureFunction.method = TextureFunction::GRAD;
2535                 }
2536                 else if (name == "textureGradOffset")
2537                 {
2538                     textureFunction.method = TextureFunction::GRAD;
2539                     textureFunction.offset = true;
2540                 }
2541                 else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" || name == "textureCubeGradEXT")
2542                 {
2543                     textureFunction.method = TextureFunction::GRAD;
2544                     textureFunction.proj = true;
2545                 }
2546                 else if (name == "textureProjGradOffset")
2547                 {
2548                     textureFunction.method = TextureFunction::GRAD;
2549                     textureFunction.proj = true;
2550                     textureFunction.offset = true;
2551                 }
2552                 else UNREACHABLE();
2553
2554                 if (textureFunction.method == TextureFunction::IMPLICIT)   // Could require lod 0 or have a bias argument
2555                 {
2556                     unsigned int mandatoryArgumentCount = 2;   // All functions have sampler and coordinate arguments
2557
2558                     if (textureFunction.offset)
2559                     {
2560                         mandatoryArgumentCount++;
2561                     }
2562
2563                     bool bias = (arguments.size() > mandatoryArgumentCount);   // Bias argument is optional
2564
2565                     if (lod0 || mContext.shaderType == SH_VERTEX_SHADER)
2566                     {
2567                         if (bias)
2568                         {
2569                             textureFunction.method = TextureFunction::LOD0BIAS;
2570                         }
2571                         else
2572                         {
2573                             textureFunction.method = TextureFunction::LOD0;
2574                         }
2575                     }
2576                     else if (bias)
2577                     {
2578                         textureFunction.method = TextureFunction::BIAS;
2579                     }
2580                 }
2581
2582                 mUsesTexture.insert(textureFunction);
2583
2584                 out << textureFunction.name();
2585             }
2586
2587             for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++)
2588             {
2589                 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
2590                 {
2591                     out << "texture_";
2592                     (*arg)->traverse(this);
2593                     out << ", sampler_";
2594                 }
2595
2596                 (*arg)->traverse(this);
2597
2598                 if (arg < arguments.end() - 1)
2599                 {
2600                     out << ", ";
2601                 }
2602             }
2603
2604             out << ")";
2605
2606             return false;
2607         }
2608         break;
2609       case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");             break;
2610       case EOpConstructFloat:
2611         addConstructor(node->getType(), "vec1", &node->getSequence());
2612         outputTriplet(visit, "vec1(", "", ")");
2613         break;
2614       case EOpConstructVec2:
2615         addConstructor(node->getType(), "vec2", &node->getSequence());
2616         outputTriplet(visit, "vec2(", ", ", ")");
2617         break;
2618       case EOpConstructVec3:
2619         addConstructor(node->getType(), "vec3", &node->getSequence());
2620         outputTriplet(visit, "vec3(", ", ", ")");
2621         break;
2622       case EOpConstructVec4:
2623         addConstructor(node->getType(), "vec4", &node->getSequence());
2624         outputTriplet(visit, "vec4(", ", ", ")");
2625         break;
2626       case EOpConstructBool:
2627         addConstructor(node->getType(), "bvec1", &node->getSequence());
2628         outputTriplet(visit, "bvec1(", "", ")");
2629         break;
2630       case EOpConstructBVec2:
2631         addConstructor(node->getType(), "bvec2", &node->getSequence());
2632         outputTriplet(visit, "bvec2(", ", ", ")");
2633         break;
2634       case EOpConstructBVec3:
2635         addConstructor(node->getType(), "bvec3", &node->getSequence());
2636         outputTriplet(visit, "bvec3(", ", ", ")");
2637         break;
2638       case EOpConstructBVec4:
2639         addConstructor(node->getType(), "bvec4", &node->getSequence());
2640         outputTriplet(visit, "bvec4(", ", ", ")");
2641         break;
2642       case EOpConstructInt:
2643         addConstructor(node->getType(), "ivec1", &node->getSequence());
2644         outputTriplet(visit, "ivec1(", "", ")");
2645         break;
2646       case EOpConstructIVec2:
2647         addConstructor(node->getType(), "ivec2", &node->getSequence());
2648         outputTriplet(visit, "ivec2(", ", ", ")");
2649         break;
2650       case EOpConstructIVec3:
2651         addConstructor(node->getType(), "ivec3", &node->getSequence());
2652         outputTriplet(visit, "ivec3(", ", ", ")");
2653         break;
2654       case EOpConstructIVec4:
2655         addConstructor(node->getType(), "ivec4", &node->getSequence());
2656         outputTriplet(visit, "ivec4(", ", ", ")");
2657         break;
2658       case EOpConstructUInt:
2659         addConstructor(node->getType(), "uvec1", &node->getSequence());
2660         outputTriplet(visit, "uvec1(", "", ")");
2661         break;
2662       case EOpConstructUVec2:
2663         addConstructor(node->getType(), "uvec2", &node->getSequence());
2664         outputTriplet(visit, "uvec2(", ", ", ")");
2665         break;
2666       case EOpConstructUVec3:
2667         addConstructor(node->getType(), "uvec3", &node->getSequence());
2668         outputTriplet(visit, "uvec3(", ", ", ")");
2669         break;
2670       case EOpConstructUVec4:
2671         addConstructor(node->getType(), "uvec4", &node->getSequence());
2672         outputTriplet(visit, "uvec4(", ", ", ")");
2673         break;
2674       case EOpConstructMat2:
2675         addConstructor(node->getType(), "mat2", &node->getSequence());
2676         outputTriplet(visit, "mat2(", ", ", ")");
2677         break;
2678       case EOpConstructMat3:
2679         addConstructor(node->getType(), "mat3", &node->getSequence());
2680         outputTriplet(visit, "mat3(", ", ", ")");
2681         break;
2682       case EOpConstructMat4: 
2683         addConstructor(node->getType(), "mat4", &node->getSequence());
2684         outputTriplet(visit, "mat4(", ", ", ")");
2685         break;
2686       case EOpConstructStruct:
2687         {
2688             const TString &structName = structNameString(*node->getType().getStruct());
2689             addConstructor(node->getType(), structName, &node->getSequence());
2690             outputTriplet(visit, structName + "_ctor(", ", ", ")");
2691         }
2692         break;
2693       case EOpLessThan:         outputTriplet(visit, "(", " < ", ")");                 break;
2694       case EOpGreaterThan:      outputTriplet(visit, "(", " > ", ")");                 break;
2695       case EOpLessThanEqual:    outputTriplet(visit, "(", " <= ", ")");                break;
2696       case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")");                break;
2697       case EOpVectorEqual:      outputTriplet(visit, "(", " == ", ")");                break;
2698       case EOpVectorNotEqual:   outputTriplet(visit, "(", " != ", ")");                break;
2699       case EOpMod:
2700         {
2701             // We need to look at the number of components in both arguments
2702             const int modValue = node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
2703                                + node->getSequence()[1]->getAsTyped()->getNominalSize();
2704             switch (modValue)
2705             {
2706               case 11: mUsesMod1 = true; break;
2707               case 22: mUsesMod2v = true; break;
2708               case 21: mUsesMod2f = true; break;
2709               case 33: mUsesMod3v = true; break;
2710               case 31: mUsesMod3f = true; break;
2711               case 44: mUsesMod4v = true; break;
2712               case 41: mUsesMod4f = true; break;
2713               default: UNREACHABLE();
2714             }
2715
2716             outputTriplet(visit, "mod(", ", ", ")");
2717         }
2718         break;
2719       case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");               break;
2720       case EOpAtan:
2721         ASSERT(node->getSequence().size() == 2);   // atan(x) is a unary operator
2722         switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
2723         {
2724           case 1: mUsesAtan2_1 = true; break;
2725           case 2: mUsesAtan2_2 = true; break;
2726           case 3: mUsesAtan2_3 = true; break;
2727           case 4: mUsesAtan2_4 = true; break;
2728           default: UNREACHABLE();
2729         }
2730         outputTriplet(visit, "atanyx(", ", ", ")");
2731         break;
2732       case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
2733       case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
2734       case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
2735       case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
2736       case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
2737       case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
2738       case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;
2739       case EOpDot:           outputTriplet(visit, "dot(", ", ", ")");           break;
2740       case EOpCross:         outputTriplet(visit, "cross(", ", ", ")");         break;
2741       case EOpFaceForward:
2742         {
2743             switch (node->getSequence()[0]->getAsTyped()->getNominalSize())   // Number of components in the first argument
2744             {
2745             case 1: mUsesFaceforward1 = true; break;
2746             case 2: mUsesFaceforward2 = true; break;
2747             case 3: mUsesFaceforward3 = true; break;
2748             case 4: mUsesFaceforward4 = true; break;
2749             default: UNREACHABLE();
2750             }
2751             
2752             outputTriplet(visit, "faceforward(", ", ", ")");
2753         }
2754         break;
2755       case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
2756       case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
2757       case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
2758       default: UNREACHABLE();
2759     }
2760
2761     return true;
2762 }
2763
2764 bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
2765 {
2766     TInfoSinkBase &out = mBody;
2767
2768     if (node->usesTernaryOperator())
2769     {
2770         out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
2771     }
2772     else  // if/else statement
2773     {
2774         mUnfoldShortCircuit->traverse(node->getCondition());
2775
2776         out << "if (";
2777
2778         node->getCondition()->traverse(this);
2779
2780         out << ")\n";
2781         
2782         outputLineDirective(node->getLine().first_line);
2783         out << "{\n";
2784
2785         bool discard = false;
2786
2787         if (node->getTrueBlock())
2788         {
2789             traverseStatements(node->getTrueBlock());
2790
2791             // Detect true discard
2792             discard = (discard || FindDiscard::search(node->getTrueBlock()));
2793         }
2794
2795         outputLineDirective(node->getLine().first_line);
2796         out << ";\n}\n";
2797
2798         if (node->getFalseBlock())
2799         {
2800             out << "else\n";
2801
2802             outputLineDirective(node->getFalseBlock()->getLine().first_line);
2803             out << "{\n";
2804
2805             outputLineDirective(node->getFalseBlock()->getLine().first_line);
2806             traverseStatements(node->getFalseBlock());
2807
2808             outputLineDirective(node->getFalseBlock()->getLine().first_line);
2809             out << ";\n}\n";
2810
2811             // Detect false discard
2812             discard = (discard || FindDiscard::search(node->getFalseBlock()));
2813         }
2814
2815         // ANGLE issue 486: Detect problematic conditional discard
2816         if (discard && FindSideEffectRewriting::search(node))
2817         {
2818             mUsesDiscardRewriting = true;
2819         }
2820     }
2821
2822     return false;
2823 }
2824
2825 void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
2826 {
2827     writeConstantUnion(node->getType(), node->getUnionArrayPointer());
2828 }
2829
2830 bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
2831 {
2832     mNestedLoopDepth++;
2833
2834     bool wasDiscontinuous = mInsideDiscontinuousLoop;
2835
2836     if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop)
2837     {
2838         mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
2839     }
2840
2841     if (mOutputType == SH_HLSL9_OUTPUT)
2842     {
2843         if (handleExcessiveLoop(node))
2844         {
2845             mInsideDiscontinuousLoop = wasDiscontinuous;
2846             mNestedLoopDepth--;
2847
2848             return false;
2849         }
2850     }
2851
2852     TInfoSinkBase &out = mBody;
2853
2854     if (node->getType() == ELoopDoWhile)
2855     {
2856         out << "{do\n";
2857
2858         outputLineDirective(node->getLine().first_line);
2859         out << "{\n";
2860     }
2861     else
2862     {
2863         out << "{for(";
2864         
2865         if (node->getInit())
2866         {
2867             node->getInit()->traverse(this);
2868         }
2869
2870         out << "; ";
2871
2872         if (node->getCondition())
2873         {
2874             node->getCondition()->traverse(this);
2875         }
2876
2877         out << "; ";
2878
2879         if (node->getExpression())
2880         {
2881             node->getExpression()->traverse(this);
2882         }
2883
2884         out << ")\n";
2885         
2886         outputLineDirective(node->getLine().first_line);
2887         out << "{\n";
2888     }
2889
2890     if (node->getBody())
2891     {
2892         traverseStatements(node->getBody());
2893     }
2894
2895     outputLineDirective(node->getLine().first_line);
2896     out << ";}\n";
2897
2898     if (node->getType() == ELoopDoWhile)
2899     {
2900         outputLineDirective(node->getCondition()->getLine().first_line);
2901         out << "while(\n";
2902
2903         node->getCondition()->traverse(this);
2904
2905         out << ");";
2906     }
2907
2908     out << "}\n";
2909
2910     mInsideDiscontinuousLoop = wasDiscontinuous;
2911     mNestedLoopDepth--;
2912
2913     return false;
2914 }
2915
2916 bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
2917 {
2918     TInfoSinkBase &out = mBody;
2919
2920     switch (node->getFlowOp())
2921     {
2922       case EOpKill:
2923         outputTriplet(visit, "discard;\n", "", "");
2924         break;
2925       case EOpBreak:
2926         if (visit == PreVisit)
2927         {
2928             if (mNestedLoopDepth > 1)
2929             {
2930                 mUsesNestedBreak = true;
2931             }
2932
2933             if (mExcessiveLoopIndex)
2934             {
2935                 out << "{Break";
2936                 mExcessiveLoopIndex->traverse(this);
2937                 out << " = true; break;}\n";
2938             }
2939             else
2940             {
2941                 out << "break;\n";
2942             }
2943         }
2944         break;
2945       case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
2946       case EOpReturn:
2947         if (visit == PreVisit)
2948         {
2949             if (node->getExpression())
2950             {
2951                 out << "return ";
2952             }
2953             else
2954             {
2955                 out << "return;\n";
2956             }
2957         }
2958         else if (visit == PostVisit)
2959         {
2960             if (node->getExpression())
2961             {
2962                 out << ";\n";
2963             }
2964         }
2965         break;
2966       default: UNREACHABLE();
2967     }
2968
2969     return true;
2970 }
2971
2972 void OutputHLSL::traverseStatements(TIntermNode *node)
2973 {
2974     if (isSingleStatement(node))
2975     {
2976         mUnfoldShortCircuit->traverse(node);
2977     }
2978
2979     node->traverse(this);
2980 }
2981
2982 bool OutputHLSL::isSingleStatement(TIntermNode *node)
2983 {
2984     TIntermAggregate *aggregate = node->getAsAggregate();
2985
2986     if (aggregate)
2987     {
2988         if (aggregate->getOp() == EOpSequence)
2989         {
2990             return false;
2991         }
2992         else
2993         {
2994             for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
2995             {
2996                 if (!isSingleStatement(*sit))
2997                 {
2998                     return false;
2999                 }
3000             }
3001
3002             return true;
3003         }
3004     }
3005
3006     return true;
3007 }
3008
3009 // Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
3010 // (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
3011 bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
3012 {
3013     const int MAX_LOOP_ITERATIONS = 254;
3014     TInfoSinkBase &out = mBody;
3015
3016     // Parse loops of the form:
3017     // for(int index = initial; index [comparator] limit; index += increment)
3018     TIntermSymbol *index = NULL;
3019     TOperator comparator = EOpNull;
3020     int initial = 0;
3021     int limit = 0;
3022     int increment = 0;
3023
3024     // Parse index name and intial value
3025     if (node->getInit())
3026     {
3027         TIntermAggregate *init = node->getInit()->getAsAggregate();
3028
3029         if (init)
3030         {
3031             TIntermSequence &sequence = init->getSequence();
3032             TIntermTyped *variable = sequence[0]->getAsTyped();
3033
3034             if (variable && variable->getQualifier() == EvqTemporary)
3035             {
3036                 TIntermBinary *assign = variable->getAsBinaryNode();
3037
3038                 if (assign->getOp() == EOpInitialize)
3039                 {
3040                     TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
3041                     TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
3042
3043                     if (symbol && constant)
3044                     {
3045                         if (constant->getBasicType() == EbtInt && constant->isScalar())
3046                         {
3047                             index = symbol;
3048                             initial = constant->getIConst(0);
3049                         }
3050                     }
3051                 }
3052             }
3053         }
3054     }
3055
3056     // Parse comparator and limit value
3057     if (index != NULL && node->getCondition())
3058     {
3059         TIntermBinary *test = node->getCondition()->getAsBinaryNode();
3060         
3061         if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
3062         {
3063             TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
3064
3065             if (constant)
3066             {
3067                 if (constant->getBasicType() == EbtInt && constant->isScalar())
3068                 {
3069                     comparator = test->getOp();
3070                     limit = constant->getIConst(0);
3071                 }
3072             }
3073         }
3074     }
3075
3076     // Parse increment
3077     if (index != NULL && comparator != EOpNull && node->getExpression())
3078     {
3079         TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
3080         TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
3081         
3082         if (binaryTerminal)
3083         {
3084             TOperator op = binaryTerminal->getOp();
3085             TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
3086
3087             if (constant)
3088             {
3089                 if (constant->getBasicType() == EbtInt && constant->isScalar())
3090                 {
3091                     int value = constant->getIConst(0);
3092
3093                     switch (op)
3094                     {
3095                       case EOpAddAssign: increment = value;  break;
3096                       case EOpSubAssign: increment = -value; break;
3097                       default: UNIMPLEMENTED();
3098                     }
3099                 }
3100             }
3101         }
3102         else if (unaryTerminal)
3103         {
3104             TOperator op = unaryTerminal->getOp();
3105
3106             switch (op)
3107             {
3108               case EOpPostIncrement: increment = 1;  break;
3109               case EOpPostDecrement: increment = -1; break;
3110               case EOpPreIncrement:  increment = 1;  break;
3111               case EOpPreDecrement:  increment = -1; break;
3112               default: UNIMPLEMENTED();
3113             }
3114         }
3115     }
3116
3117     if (index != NULL && comparator != EOpNull && increment != 0)
3118     {
3119         if (comparator == EOpLessThanEqual)
3120         {
3121             comparator = EOpLessThan;
3122             limit += 1;
3123         }
3124
3125         if (comparator == EOpLessThan)
3126         {
3127             int iterations = (limit - initial) / increment;
3128
3129             if (iterations <= MAX_LOOP_ITERATIONS)
3130             {
3131                 return false;   // Not an excessive loop
3132             }
3133
3134             TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
3135             mExcessiveLoopIndex = index;
3136
3137             out << "{int ";
3138             index->traverse(this);
3139             out << ";\n"
3140                    "bool Break";
3141             index->traverse(this);
3142             out << " = false;\n";
3143
3144             bool firstLoopFragment = true;
3145
3146             while (iterations > 0)
3147             {
3148                 int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
3149
3150                 if (!firstLoopFragment)
3151                 {
3152                     out << "if (!Break";
3153                     index->traverse(this);
3154                     out << ") {\n";
3155                 }
3156
3157                 if (iterations <= MAX_LOOP_ITERATIONS)   // Last loop fragment
3158                 {
3159                     mExcessiveLoopIndex = NULL;   // Stops setting the Break flag
3160                 }
3161                 
3162                 // for(int index = initial; index < clampedLimit; index += increment)
3163
3164                 out << "for(";
3165                 index->traverse(this);
3166                 out << " = ";
3167                 out << initial;
3168
3169                 out << "; ";
3170                 index->traverse(this);
3171                 out << " < ";
3172                 out << clampedLimit;
3173
3174                 out << "; ";
3175                 index->traverse(this);
3176                 out << " += ";
3177                 out << increment;
3178                 out << ")\n";
3179                 
3180                 outputLineDirective(node->getLine().first_line);
3181                 out << "{\n";
3182
3183                 if (node->getBody())
3184                 {
3185                     node->getBody()->traverse(this);
3186                 }
3187
3188                 outputLineDirective(node->getLine().first_line);
3189                 out << ";}\n";
3190
3191                 if (!firstLoopFragment)
3192                 {
3193                     out << "}\n";
3194                 }
3195
3196                 firstLoopFragment = false;
3197
3198                 initial += MAX_LOOP_ITERATIONS * increment;
3199                 iterations -= MAX_LOOP_ITERATIONS;
3200             }
3201             
3202             out << "}";
3203
3204             mExcessiveLoopIndex = restoreIndex;
3205
3206             return true;
3207         }
3208         else UNIMPLEMENTED();
3209     }
3210
3211     return false;   // Not handled as an excessive loop
3212 }
3213
3214 void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
3215 {
3216     TInfoSinkBase &out = mBody;
3217
3218     if (visit == PreVisit)
3219     {
3220         out << preString;
3221     }
3222     else if (visit == InVisit)
3223     {
3224         out << inString;
3225     }
3226     else if (visit == PostVisit)
3227     {
3228         out << postString;
3229     }
3230 }
3231
3232 void OutputHLSL::outputLineDirective(int line)
3233 {
3234     if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
3235     {
3236         mBody << "\n";
3237         mBody << "#line " << line;
3238
3239         if (mContext.sourcePath)
3240         {
3241             mBody << " \"" << mContext.sourcePath << "\"";
3242         }
3243         
3244         mBody << "\n";
3245     }
3246 }
3247
3248 TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
3249 {
3250     TQualifier qualifier = symbol->getQualifier();
3251     const TType &type = symbol->getType();
3252     TString name = symbol->getSymbol();
3253
3254     if (name.empty())   // HLSL demands named arguments, also for prototypes
3255     {
3256         name = "x" + str(mUniqueIndex++);
3257     }
3258     else
3259     {
3260         name = decorate(name);
3261     }
3262
3263     if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
3264     {
3265         return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
3266                qualifierString(qualifier) + " " + samplerString(type) + " sampler_" + name + arrayString(type);        
3267     }
3268
3269     return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
3270 }
3271
3272 TString OutputHLSL::interpolationString(TQualifier qualifier)
3273 {
3274     switch(qualifier)
3275     {
3276       case EvqVaryingIn:           return "";
3277       case EvqFragmentIn:          return "";
3278       case EvqInvariantVaryingIn:  return "";
3279       case EvqSmoothIn:            return "linear";
3280       case EvqFlatIn:              return "nointerpolation";
3281       case EvqCentroidIn:          return "centroid";
3282       case EvqVaryingOut:          return "";
3283       case EvqVertexOut:           return "";
3284       case EvqInvariantVaryingOut: return "";
3285       case EvqSmoothOut:           return "linear";
3286       case EvqFlatOut:             return "nointerpolation";
3287       case EvqCentroidOut:         return "centroid";
3288       default: UNREACHABLE();
3289     }
3290
3291     return "";
3292 }
3293
3294 TString OutputHLSL::qualifierString(TQualifier qualifier)
3295 {
3296     switch(qualifier)
3297     {
3298       case EvqIn:            return "in";
3299       case EvqOut:           return "inout"; // 'out' results in an HLSL error if not all fields are written, for GLSL it's undefined
3300       case EvqInOut:         return "inout";
3301       case EvqConstReadOnly: return "const";
3302       default: UNREACHABLE();
3303     }
3304
3305     return "";
3306 }
3307
3308 TString OutputHLSL::typeString(const TType &type)
3309 {
3310     const TStructure* structure = type.getStruct();
3311     if (structure)
3312     {
3313         const TString& typeName = structure->name();
3314         if (typeName != "")
3315         {
3316             return structNameString(*type.getStruct());
3317         }
3318         else   // Nameless structure, define in place
3319         {
3320             return structureString(*structure, false, false);
3321         }
3322     }
3323     else if (type.isMatrix())
3324     {
3325         int cols = type.getCols();
3326         int rows = type.getRows();
3327         return "float" + str(cols) + "x" + str(rows);
3328     }
3329     else
3330     {
3331         switch (type.getBasicType())
3332         {
3333           case EbtFloat:
3334             switch (type.getNominalSize())
3335             {
3336               case 1: return "float";
3337               case 2: return "float2";
3338               case 3: return "float3";
3339               case 4: return "float4";
3340             }
3341           case EbtInt:
3342             switch (type.getNominalSize())
3343             {
3344               case 1: return "int";
3345               case 2: return "int2";
3346               case 3: return "int3";
3347               case 4: return "int4";
3348             }
3349           case EbtUInt:
3350             switch (type.getNominalSize())
3351             {
3352               case 1: return "uint";
3353               case 2: return "uint2";
3354               case 3: return "uint3";
3355               case 4: return "uint4";
3356             }
3357           case EbtBool:
3358             switch (type.getNominalSize())
3359             {
3360               case 1: return "bool";
3361               case 2: return "bool2";
3362               case 3: return "bool3";
3363               case 4: return "bool4";
3364             }
3365           case EbtVoid:
3366             return "void";
3367           case EbtSampler2D:
3368           case EbtISampler2D:
3369           case EbtUSampler2D:
3370           case EbtSampler2DArray:
3371           case EbtISampler2DArray:
3372           case EbtUSampler2DArray:
3373             return "sampler2D";
3374           case EbtSamplerCube:
3375           case EbtISamplerCube:
3376           case EbtUSamplerCube:
3377             return "samplerCUBE";
3378           case EbtSamplerExternalOES:
3379             return "sampler2D";
3380           default:
3381             break;
3382         }
3383     }
3384
3385     UNREACHABLE();
3386     return "<unknown type>";
3387 }
3388
3389 TString OutputHLSL::textureString(const TType &type)
3390 {
3391     switch (type.getBasicType())
3392     {
3393       case EbtSampler2D:            return "Texture2D";
3394       case EbtSamplerCube:          return "TextureCube";
3395       case EbtSamplerExternalOES:   return "Texture2D";
3396       case EbtSampler2DArray:       return "Texture2DArray";
3397       case EbtSampler3D:            return "Texture3D";
3398       case EbtISampler2D:           return "Texture2D<int4>";
3399       case EbtISampler3D:           return "Texture3D<int4>";
3400       case EbtISamplerCube:         return "Texture2DArray<int4>";
3401       case EbtISampler2DArray:      return "Texture2DArray<int4>";
3402       case EbtUSampler2D:           return "Texture2D<uint4>";
3403       case EbtUSampler3D:           return "Texture3D<uint4>";
3404       case EbtUSamplerCube:         return "Texture2DArray<uint4>";
3405       case EbtUSampler2DArray:      return "Texture2DArray<uint4>";
3406       case EbtSampler2DShadow:      return "Texture2D";
3407       case EbtSamplerCubeShadow:    return "TextureCube";
3408       case EbtSampler2DArrayShadow: return "Texture2DArray";
3409       default: UNREACHABLE();
3410     }
3411     
3412     return "<unknown texture type>";
3413 }
3414
3415 TString OutputHLSL::samplerString(const TType &type)
3416 {
3417     if (IsShadowSampler(type.getBasicType()))
3418     {
3419         return "SamplerComparisonState";
3420     }
3421     else
3422     {
3423         return "SamplerState";
3424     }
3425 }
3426
3427 TString OutputHLSL::arrayString(const TType &type)
3428 {
3429     if (!type.isArray())
3430     {
3431         return "";
3432     }
3433
3434     return "[" + str(type.getArraySize()) + "]";
3435 }
3436
3437 TString OutputHLSL::initializer(const TType &type)
3438 {
3439     TString string;
3440
3441     size_t size = type.getObjectSize();
3442     for (size_t component = 0; component < size; component++)
3443     {
3444         string += "0";
3445
3446         if (component + 1 < size)
3447         {
3448             string += ", ";
3449         }
3450     }
3451
3452     return "{" + string + "}";
3453 }
3454
3455 TString OutputHLSL::structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
3456 {
3457     const TFieldList &fields = structure.fields();
3458     const bool isNameless = (structure.name() == "");
3459     const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, useStd140Packing);
3460     const TString declareString = (isNameless ? "struct" : "struct " + structName);
3461
3462     TString string;
3463     string += declareString + "\n"
3464               "{\n";
3465
3466     int elementIndex = 0;
3467
3468     for (unsigned int i = 0; i < fields.size(); i++)
3469     {
3470         const TField &field = *fields[i];
3471         const TType &fieldType = *field.type();
3472         const TStructure *fieldStruct = fieldType.getStruct();
3473         const TString &fieldTypeString = fieldStruct ? structureTypeName(*fieldStruct, useHLSLRowMajorPacking, useStd140Packing) : typeString(fieldType);
3474
3475         if (useStd140Packing)
3476         {
3477             string += std140PrePaddingString(*field.type(), &elementIndex);
3478         }
3479
3480         string += "    " + fieldTypeString + " " + decorateField(field.name(), structure) + arrayString(fieldType) + ";\n";
3481
3482         if (useStd140Packing)
3483         {
3484             string += std140PostPaddingString(*field.type(), useHLSLRowMajorPacking);
3485         }
3486     }
3487
3488     // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
3489     string += (isNameless ? "} " : "};\n");
3490
3491     // Add remaining element index to the global map, for use with nested structs in standard layouts
3492     if (useStd140Packing)
3493     {
3494         mStd140StructElementIndexes[structName] = elementIndex;
3495     }
3496
3497     return string;
3498 }
3499
3500 TString OutputHLSL::structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
3501 {
3502     if (structure.name() == "")
3503     {
3504         return "";
3505     }
3506
3507     TString prefix = "";
3508
3509     // Structs packed with row-major matrices in HLSL are prefixed with "rm"
3510     // GLSL column-major maps to HLSL row-major, and the converse is true
3511
3512     if (useStd140Packing)
3513     {
3514         prefix += "std";
3515     }
3516
3517     if (useHLSLRowMajorPacking)
3518     {
3519         if (prefix != "") prefix += "_";
3520         prefix += "rm";
3521     }
3522
3523     return prefix + structNameString(structure);
3524 }
3525
3526 void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
3527 {
3528     if (name == "")
3529     {
3530         return;   // Nameless structures don't have constructors
3531     }
3532
3533     if (type.getStruct() && mStructNames.find(name) != mStructNames.end())
3534     {
3535         return;   // Already added
3536     }
3537
3538     TType ctorType = type;
3539     ctorType.clearArrayness();
3540     ctorType.setPrecision(EbpHigh);
3541     ctorType.setQualifier(EvqTemporary);
3542
3543     typedef std::vector<TType> ParameterArray;
3544     ParameterArray ctorParameters;
3545
3546     const TStructure* structure = type.getStruct();
3547     if (structure)
3548     {
3549         mStructNames.insert(name);
3550
3551         const TString &structString = structureString(*structure, false, false);
3552
3553         if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end())
3554         {
3555             // Add row-major packed struct for interface blocks
3556             TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
3557                                      structureString(*structure, true, false) +
3558                                      "#pragma pack_matrix(column_major)\n";
3559
3560             TString std140String = structureString(*structure, false, true);
3561             TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
3562                                            structureString(*structure, true, true) +
3563                                            "#pragma pack_matrix(column_major)\n";
3564
3565             mStructDeclarations.push_back(structString);
3566             mStructDeclarations.push_back(rowMajorString);
3567             mStructDeclarations.push_back(std140String);
3568             mStructDeclarations.push_back(std140RowMajorString);
3569         }
3570
3571         const TFieldList &fields = structure->fields();
3572         for (unsigned int i = 0; i < fields.size(); i++)
3573         {
3574             ctorParameters.push_back(*fields[i]->type());
3575         }
3576     }
3577     else if (parameters)
3578     {
3579         for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
3580         {
3581             ctorParameters.push_back((*parameter)->getAsTyped()->getType());
3582         }
3583     }
3584     else UNREACHABLE();
3585
3586     TString constructor;
3587
3588     if (ctorType.getStruct())
3589     {
3590         constructor += name + " " + name + "_ctor(";
3591     }
3592     else   // Built-in type
3593     {
3594         constructor += typeString(ctorType) + " " + name + "(";
3595     }
3596
3597     for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
3598     {
3599         const TType &type = ctorParameters[parameter];
3600
3601         constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
3602
3603         if (parameter < ctorParameters.size() - 1)
3604         {
3605             constructor += ", ";
3606         }
3607     }
3608
3609     constructor += ")\n"
3610                    "{\n";
3611
3612     if (ctorType.getStruct())
3613     {
3614         constructor += "    " + name + " structure = {";
3615     }
3616     else
3617     {
3618         constructor += "    return " + typeString(ctorType) + "(";
3619     }
3620
3621     if (ctorType.isMatrix() && ctorParameters.size() == 1)
3622     {
3623         int rows = ctorType.getRows();
3624         int cols = ctorType.getCols();
3625         const TType &parameter = ctorParameters[0];
3626
3627         if (parameter.isScalar())
3628         {
3629             for (int row = 0; row < rows; row++)
3630             {
3631                 for (int col = 0; col < cols; col++)
3632                 {
3633                     constructor += TString((row == col) ? "x0" : "0.0");
3634                     
3635                     if (row < rows - 1 || col < cols - 1)
3636                     {
3637                         constructor += ", ";
3638                     }
3639                 }
3640             }
3641         }
3642         else if (parameter.isMatrix())
3643         {
3644             for (int row = 0; row < rows; row++)
3645             {
3646                 for (int col = 0; col < cols; col++)
3647                 {
3648                     if (row < parameter.getRows() && col < parameter.getCols())
3649                     {
3650                         constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
3651                     }
3652                     else
3653                     {
3654                         constructor += TString((row == col) ? "1.0" : "0.0");
3655                     }
3656
3657                     if (row < rows - 1 || col < cols - 1)
3658                     {
3659                         constructor += ", ";
3660                     }
3661                 }
3662             }
3663         }
3664         else UNREACHABLE();
3665     }
3666     else
3667     {
3668         size_t remainingComponents = ctorType.getObjectSize();
3669         size_t parameterIndex = 0;
3670
3671         while (remainingComponents > 0)
3672         {
3673             const TType &parameter = ctorParameters[parameterIndex];
3674             const size_t parameterSize = parameter.getObjectSize();
3675             bool moreParameters = parameterIndex + 1 < ctorParameters.size();
3676
3677             constructor += "x" + str(parameterIndex);
3678
3679             if (parameter.isScalar())
3680             {
3681                 remainingComponents -= parameter.getObjectSize();
3682             }
3683             else if (parameter.isVector())
3684             {
3685                 if (remainingComponents == parameterSize || moreParameters)
3686                 {
3687                     ASSERT(parameterSize <= remainingComponents);
3688                     remainingComponents -= parameterSize;
3689                 }
3690                 else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
3691                 {
3692                     switch (remainingComponents)
3693                     {
3694                       case 1: constructor += ".x";    break;
3695                       case 2: constructor += ".xy";   break;
3696                       case 3: constructor += ".xyz";  break;
3697                       case 4: constructor += ".xyzw"; break;
3698                       default: UNREACHABLE();
3699                     }
3700
3701                     remainingComponents = 0;
3702                 }
3703                 else UNREACHABLE();
3704             }
3705             else if (parameter.isMatrix() || parameter.getStruct())
3706             {
3707                 ASSERT(remainingComponents == parameterSize || moreParameters);
3708                 ASSERT(parameterSize <= remainingComponents);
3709                 
3710                 remainingComponents -= parameterSize;
3711             }
3712             else UNREACHABLE();
3713
3714             if (moreParameters)
3715             {
3716                 parameterIndex++;
3717             }
3718
3719             if (remainingComponents)
3720             {
3721                 constructor += ", ";
3722             }
3723         }
3724     }
3725
3726     if (ctorType.getStruct())
3727     {
3728         constructor += "};\n"
3729                        "    return structure;\n"
3730                        "}\n";
3731     }
3732     else
3733     {
3734         constructor += ");\n"
3735                        "}\n";
3736     }
3737
3738     mConstructors.insert(constructor);
3739 }
3740
3741 const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
3742 {
3743     TInfoSinkBase &out = mBody;
3744
3745     const TStructure* structure = type.getStruct();
3746     if (structure)
3747     {
3748         out << structNameString(*structure) + "_ctor(";
3749         
3750         const TFieldList& fields = structure->fields();
3751
3752         for (size_t i = 0; i < fields.size(); i++)
3753         {
3754             const TType *fieldType = fields[i]->type();
3755
3756             constUnion = writeConstantUnion(*fieldType, constUnion);
3757
3758             if (i != fields.size() - 1)
3759             {
3760                 out << ", ";
3761             }
3762         }
3763
3764         out << ")";
3765     }
3766     else
3767     {
3768         size_t size = type.getObjectSize();
3769         bool writeType = size > 1;
3770         
3771         if (writeType)
3772         {
3773             out << typeString(type) << "(";
3774         }
3775
3776         for (size_t i = 0; i < size; i++, constUnion++)
3777         {
3778             switch (constUnion->getType())
3779             {
3780               case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break;
3781               case EbtInt:   out << constUnion->getIConst(); break;
3782               case EbtUInt:  out << constUnion->getUConst(); break;
3783               case EbtBool:  out << constUnion->getBConst(); break;
3784               default: UNREACHABLE();
3785             }
3786
3787             if (i != size - 1)
3788             {
3789                 out << ", ";
3790             }
3791         }
3792
3793         if (writeType)
3794         {
3795             out << ")";
3796         }
3797     }
3798
3799     return constUnion;
3800 }
3801
3802 TString OutputHLSL::structNameString(const TStructure &structure)
3803 {
3804     if (structure.name().empty())
3805     {
3806         return "";
3807     }
3808
3809     return "ss_" + str(structure.uniqueId()) + structure.name();
3810 }
3811
3812 TString OutputHLSL::decorate(const TString &string)
3813 {
3814     if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
3815     {
3816         return "_" + string;
3817     }
3818     
3819     return string;
3820 }
3821
3822 TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
3823 {
3824     if (type.getBasicType() == EbtSamplerExternalOES)
3825     {
3826         return "ex_" + string;
3827     }
3828     
3829     return decorate(string);
3830 }
3831
3832 TString OutputHLSL::decorateField(const TString &string, const TStructure &structure)
3833 {
3834     if (structure.name().compare(0, 3, "gl_") != 0)
3835     {
3836         return decorate(string);
3837     }
3838
3839     return string;
3840 }
3841
3842 void OutputHLSL::declareInterfaceBlockField(const TType &type, const TString &name, std::vector<gl::InterfaceBlockField>& output)
3843 {
3844     const TStructure *structure = type.getStruct();
3845
3846     if (!structure)
3847     {
3848         const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
3849         gl::InterfaceBlockField field(glVariableType(type), glVariablePrecision(type), name.c_str(),
3850                                       (unsigned int)type.getArraySize(), isRowMajorMatrix);
3851         output.push_back(field);
3852    }
3853     else
3854     {
3855         gl::InterfaceBlockField structField(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false);
3856
3857         const TFieldList &fields = structure->fields();
3858
3859         for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
3860         {
3861             TField *field = fields[fieldIndex];
3862             TType *fieldType = field->type();
3863
3864             // make sure to copy matrix packing information
3865             fieldType->setLayoutQualifier(type.getLayoutQualifier());
3866
3867             declareInterfaceBlockField(*fieldType, field->name(), structField.fields);
3868         }
3869
3870         output.push_back(structField);
3871     }
3872 }
3873
3874 gl::Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<gl::Uniform>& output)
3875 {
3876     const TStructure *structure = type.getStruct();
3877
3878     if (!structure)
3879     {
3880         gl::Uniform uniform(glVariableType(type), glVariablePrecision(type), name.c_str(),
3881                             (unsigned int)type.getArraySize(), (unsigned int)registerIndex, 0);
3882         output.push_back(uniform);
3883
3884         return uniform;
3885    }
3886     else
3887     {
3888         gl::Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(),
3889                                   (unsigned int)registerIndex, GL_INVALID_INDEX);
3890
3891         const TFieldList &fields = structure->fields();
3892
3893         for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
3894         {
3895             TField *field = fields[fieldIndex];
3896             TType *fieldType = field->type();
3897
3898             declareUniformToList(*fieldType, field->name(), GL_INVALID_INDEX, structUniform.fields);
3899         }
3900
3901         // assign register offset information -- this will override the information in any sub-structures.
3902         HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType);
3903
3904         output.push_back(structUniform);
3905
3906         return structUniform;
3907     }
3908 }
3909
3910 gl::InterpolationType getInterpolationType(TQualifier qualifier)
3911 {
3912     switch (qualifier)
3913     {
3914       case EvqFlatIn:
3915       case EvqFlatOut:
3916         return gl::INTERPOLATION_FLAT;
3917
3918       case EvqSmoothIn:
3919       case EvqSmoothOut:
3920       case EvqVertexOut:
3921       case EvqFragmentIn:
3922       case EvqVaryingIn:
3923       case EvqVaryingOut:
3924         return gl::INTERPOLATION_SMOOTH;
3925
3926       case EvqCentroidIn:
3927       case EvqCentroidOut:
3928         return gl::INTERPOLATION_CENTROID;
3929
3930       default: UNREACHABLE();
3931         return gl::INTERPOLATION_SMOOTH;
3932     }
3933 }
3934
3935 void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<gl::Varying>& fieldsOut)
3936 {
3937     const TStructure *structure = type.getStruct();
3938
3939     gl::InterpolationType interpolation = getInterpolationType(baseTypeQualifier);
3940     if (!structure)
3941     {
3942         gl::Varying varying(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), interpolation);
3943         fieldsOut.push_back(varying);
3944     }
3945     else
3946     {
3947         gl::Varying structVarying(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), interpolation);
3948         const TFieldList &fields = structure->fields();
3949
3950         structVarying.structName = structure->name().c_str();
3951
3952         for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
3953         {
3954             const TField &field = *fields[fieldIndex];
3955             declareVaryingToList(*field.type(), baseTypeQualifier, field.name(), structVarying.fields);
3956         }
3957
3958         fieldsOut.push_back(structVarying);
3959     }
3960 }
3961
3962 int OutputHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
3963 {
3964     int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
3965
3966     const gl::Uniform &uniform = declareUniformToList(type, name, registerIndex, mActiveUniforms);
3967
3968     if (IsSampler(type.getBasicType()))
3969     {
3970         mSamplerRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
3971     }
3972     else
3973     {
3974         mUniformRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
3975     }
3976
3977     return registerIndex;
3978 }
3979
3980 GLenum OutputHLSL::glVariableType(const TType &type)
3981 {
3982     if (type.getBasicType() == EbtFloat)
3983     {
3984         if (type.isScalar())
3985         {
3986             return GL_FLOAT;
3987         }
3988         else if (type.isVector())
3989         {
3990             switch(type.getNominalSize())
3991             {
3992               case 2: return GL_FLOAT_VEC2;
3993               case 3: return GL_FLOAT_VEC3;
3994               case 4: return GL_FLOAT_VEC4;
3995               default: UNREACHABLE();
3996             }
3997         }
3998         else if (type.isMatrix())
3999         {
4000             switch (type.getCols())
4001             {
4002               case 2:
4003                 switch(type.getRows())
4004                 {
4005                   case 2: return GL_FLOAT_MAT2;
4006                   case 3: return GL_FLOAT_MAT2x3;
4007                   case 4: return GL_FLOAT_MAT2x4;
4008                   default: UNREACHABLE();
4009                 }
4010
4011               case 3:
4012                 switch(type.getRows())
4013                 {
4014                   case 2: return GL_FLOAT_MAT3x2;
4015                   case 3: return GL_FLOAT_MAT3;
4016                   case 4: return GL_FLOAT_MAT3x4;
4017                   default: UNREACHABLE();
4018                 }
4019
4020               case 4:
4021                 switch(type.getRows())
4022                 {
4023                   case 2: return GL_FLOAT_MAT4x2;
4024                   case 3: return GL_FLOAT_MAT4x3;
4025                   case 4: return GL_FLOAT_MAT4;
4026                   default: UNREACHABLE();
4027                 }
4028
4029               default: UNREACHABLE();
4030             }
4031         }
4032         else UNREACHABLE();
4033     }
4034     else if (type.getBasicType() == EbtInt)
4035     {
4036         if (type.isScalar())
4037         {
4038             return GL_INT;
4039         }
4040         else if (type.isVector())
4041         {
4042             switch(type.getNominalSize())
4043             {
4044               case 2: return GL_INT_VEC2;
4045               case 3: return GL_INT_VEC3;
4046               case 4: return GL_INT_VEC4;
4047               default: UNREACHABLE();
4048             }
4049         }
4050         else UNREACHABLE();
4051     }
4052     else if (type.getBasicType() == EbtUInt)
4053     {
4054         if (type.isScalar())
4055         {
4056             return GL_UNSIGNED_INT;
4057         }
4058         else if (type.isVector())
4059         {
4060             switch(type.getNominalSize())
4061             {
4062               case 2: return GL_UNSIGNED_INT_VEC2;
4063               case 3: return GL_UNSIGNED_INT_VEC3;
4064               case 4: return GL_UNSIGNED_INT_VEC4;
4065               default: UNREACHABLE();
4066             }
4067         }
4068         else UNREACHABLE();
4069     }
4070     else if (type.getBasicType() == EbtBool)
4071     {
4072         if (type.isScalar())
4073         {
4074             return GL_BOOL;
4075         }
4076         else if (type.isVector())
4077         {
4078             switch(type.getNominalSize())
4079             {
4080               case 2: return GL_BOOL_VEC2;
4081               case 3: return GL_BOOL_VEC3;
4082               case 4: return GL_BOOL_VEC4;
4083               default: UNREACHABLE();
4084             }
4085         }
4086         else UNREACHABLE();
4087     }
4088
4089     switch(type.getBasicType())
4090     {
4091       case EbtSampler2D:            return GL_SAMPLER_2D;
4092       case EbtSampler3D:            return GL_SAMPLER_3D;
4093       case EbtSamplerCube:          return GL_SAMPLER_CUBE;
4094       case EbtSampler2DArray:       return GL_SAMPLER_2D_ARRAY;
4095       case EbtISampler2D:           return GL_INT_SAMPLER_2D;
4096       case EbtISampler3D:           return GL_INT_SAMPLER_3D;
4097       case EbtISamplerCube:         return GL_INT_SAMPLER_CUBE;
4098       case EbtISampler2DArray:      return GL_INT_SAMPLER_2D_ARRAY;
4099       case EbtUSampler2D:           return GL_UNSIGNED_INT_SAMPLER_2D;
4100       case EbtUSampler3D:           return GL_UNSIGNED_INT_SAMPLER_3D;
4101       case EbtUSamplerCube:         return GL_UNSIGNED_INT_SAMPLER_CUBE;
4102       case EbtUSampler2DArray:      return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
4103       case EbtSampler2DShadow:      return GL_SAMPLER_2D_SHADOW;
4104       case EbtSamplerCubeShadow:    return GL_SAMPLER_CUBE_SHADOW;
4105       case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW;
4106       default: UNREACHABLE();
4107     }
4108
4109     return GL_NONE;
4110 }
4111
4112 GLenum OutputHLSL::glVariablePrecision(const TType &type)
4113 {
4114     if (type.getBasicType() == EbtFloat)
4115     {
4116         switch (type.getPrecision())
4117         {
4118           case EbpHigh:   return GL_HIGH_FLOAT;
4119           case EbpMedium: return GL_MEDIUM_FLOAT;
4120           case EbpLow:    return GL_LOW_FLOAT;
4121           case EbpUndefined:
4122             // Should be defined as the default precision by the parser
4123           default: UNREACHABLE();
4124         }
4125     }
4126     else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
4127     {
4128         switch (type.getPrecision())
4129         {
4130           case EbpHigh:   return GL_HIGH_INT;
4131           case EbpMedium: return GL_MEDIUM_INT;
4132           case EbpLow:    return GL_LOW_INT;
4133           case EbpUndefined:
4134             // Should be defined as the default precision by the parser
4135           default: UNREACHABLE();
4136         }
4137     }
4138
4139     // Other types (boolean, sampler) don't have a precision
4140     return GL_NONE;
4141 }
4142
4143 bool OutputHLSL::isVaryingOut(TQualifier qualifier)
4144 {
4145     switch(qualifier)
4146     {
4147       case EvqVaryingOut:
4148       case EvqInvariantVaryingOut:
4149       case EvqSmoothOut:
4150       case EvqFlatOut:
4151       case EvqCentroidOut:
4152       case EvqVertexOut:
4153         return true;
4154
4155       default: break;
4156     }
4157
4158     return false;
4159 }
4160
4161 bool OutputHLSL::isVaryingIn(TQualifier qualifier)
4162 {
4163     switch(qualifier)
4164     {
4165       case EvqVaryingIn:
4166       case EvqInvariantVaryingIn:
4167       case EvqSmoothIn:
4168       case EvqFlatIn:
4169       case EvqCentroidIn:
4170       case EvqFragmentIn:
4171         return true;
4172
4173       default: break;
4174     }
4175
4176     return false;
4177 }
4178
4179 bool OutputHLSL::isVarying(TQualifier qualifier)
4180 {
4181     return isVaryingIn(qualifier) || isVaryingOut(qualifier);
4182 }
4183
4184 }