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