blob: 88220dae28bf8a0fce46b258aa70a370e4e08d07 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00007#include "compiler/OutputHLSL.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00008
alokp@chromium.org79fb1012012-04-26 21:07:39 +00009#include "common/angleutils.h"
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +000010#include "common/utilities.h"
alokp@chromium.org91b72322010-06-02 15:50:56 +000011#include "compiler/debug.h"
daniel@transgaming.com89431aa2012-05-31 01:20:29 +000012#include "compiler/DetectDiscontinuity.h"
shannon.woods@transgaming.comfff89b32013-02-28 23:20:15 +000013#include "compiler/InfoSink.h"
14#include "compiler/SearchSymbol.h"
15#include "compiler/UnfoldShortCircuit.h"
Jamie Madill440dc742013-06-20 11:55:55 -040016#include "compiler/HLSLLayoutEncoder.h"
Jamie Madill570e04d2013-06-21 09:15:33 -040017#include "compiler/FlagStd140Structs.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000018
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +000019#include <algorithm>
shannon.woods@transgaming.comfff89b32013-02-28 23:20:15 +000020#include <cfloat>
21#include <stdio.h>
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +000022
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023namespace sh
24{
daniel@transgaming.com005c7392010-04-15 20:45:27 +000025// Integer to TString conversion
26TString str(int i)
27{
28 char buffer[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +000029 snprintf(buffer, sizeof(buffer), "%d", i);
daniel@transgaming.com005c7392010-04-15 20:45:27 +000030 return buffer;
31}
32
Nicolas Capense0ba27a2013-06-24 16:10:52 -040033TString OutputHLSL::TextureFunction::name() const
34{
35 TString name = "gl_texture";
36
37 if (sampler == EbtSampler2D ||
38 sampler == EbtISampler2D ||
Nicolas Capensfb50dff2013-06-24 16:16:23 -040039 sampler == EbtUSampler2D ||
40 sampler == EbtSampler2DArray ||
41 sampler == EbtISampler2DArray ||
42 sampler == EbtUSampler2DArray)
Nicolas Capense0ba27a2013-06-24 16:10:52 -040043 {
44 name += "2D";
45 }
46 else if (sampler == EbtSampler3D ||
47 sampler == EbtISampler3D ||
48 sampler == EbtUSampler3D)
49 {
50 name += "3D";
51 }
52 else if (sampler == EbtSamplerCube ||
53 sampler == EbtISamplerCube ||
54 sampler == EbtUSamplerCube)
55 {
56 name += "Cube";
57 }
58 else UNREACHABLE();
59
60 if (proj)
61 {
62 name += "Proj";
63 }
64
65 switch(mipmap)
66 {
67 case IMPLICIT: break;
68 case BIAS: break;
69 case LOD: name += "Lod"; break;
70 case LOD0: name += "Lod0"; break;
71 default: UNREACHABLE();
72 }
73
74 return name + "(";
75}
76
77bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
78{
79 if (sampler < rhs.sampler) return true;
80 if (coords < rhs.coords) return true;
81 if (!proj && rhs.proj) return true;
82 if (mipmap < rhs.mipmap) return true;
83
84 return false;
85}
86
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +000087OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +000088 : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089{
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +000090 mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +000091 mInsideFunction = false;
daniel@transgaming.comb5875982010-04-15 20:44:53 +000092
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +000093 mUsesFragColor = false;
94 mUsesFragData = false;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +000095 mUsesDepthRange = false;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000096 mUsesFragCoord = false;
97 mUsesPointCoord = false;
98 mUsesFrontFacing = false;
99 mUsesPointSize = false;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400100 mUsesFragDepth = false;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +0000101 mUsesXor = false;
102 mUsesMod1 = false;
daniel@transgaming.com4229f592011-11-24 22:34:04 +0000103 mUsesMod2v = false;
104 mUsesMod2f = false;
105 mUsesMod3v = false;
106 mUsesMod3f = false;
107 mUsesMod4v = false;
108 mUsesMod4f = false;
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +0000109 mUsesFaceforward1 = false;
110 mUsesFaceforward2 = false;
111 mUsesFaceforward3 = false;
112 mUsesFaceforward4 = false;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000113
114 for (unsigned int col = 0; col <= 4; col++)
115 {
116 for (unsigned int row = 0; row <= 4; row++)
117 {
118 mUsesEqualMat[col][row] = false;
119 }
120 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000121 mUsesEqualVec2 = false;
122 mUsesEqualVec3 = false;
123 mUsesEqualVec4 = false;
124 mUsesEqualIVec2 = false;
125 mUsesEqualIVec3 = false;
126 mUsesEqualIVec4 = false;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000127 mUsesEqualUVec2 = false;
128 mUsesEqualUVec3 = false;
129 mUsesEqualUVec4 = false;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000130 mUsesEqualBVec2 = false;
131 mUsesEqualBVec3 = false;
132 mUsesEqualBVec4 = false;
daniel@transgaming.com35342dc2012-02-28 02:01:22 +0000133 mUsesAtan2_1 = false;
134 mUsesAtan2_2 = false;
135 mUsesAtan2_3 = false;
136 mUsesAtan2_4 = false;
daniel@transgaming.com005c7392010-04-15 20:45:27 +0000137
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000138 mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
139
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +0000140 mScopeDepth = 0;
141
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +0000142 mUniqueIndex = 0;
daniel@transgaming.com89431aa2012-05-31 01:20:29 +0000143
144 mContainsLoopDiscontinuity = false;
145 mOutputLod0Function = false;
daniel@transgaming.come11100c2012-05-31 01:20:32 +0000146 mInsideDiscontinuousLoop = false;
daniel@transgaming.come9b3f602012-07-11 20:37:31 +0000147
148 mExcessiveLoopIndex = NULL;
daniel@transgaming.com652468c2012-12-20 21:11:57 +0000149
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000150 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +0000151 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000152 if (mContext.shaderType == SH_FRAGMENT_SHADER)
153 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000154 mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000155 }
156 else
157 {
shannon.woods@transgaming.com42832a62013-02-28 23:18:38 +0000158 mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000159 }
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +0000160 }
161 else
162 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000163 mUniformRegister = 0;
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +0000164 }
165
daniel@transgaming.com652468c2012-12-20 21:11:57 +0000166 mSamplerRegister = 0;
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000167 mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
Jamie Madill574d9dd2013-06-20 11:55:56 -0400168 mPaddingCounter = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169}
170
daniel@transgaming.comb5875982010-04-15 20:44:53 +0000171OutputHLSL::~OutputHLSL()
172{
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +0000173 delete mUnfoldShortCircuit;
daniel@transgaming.comb5875982010-04-15 20:44:53 +0000174}
175
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000176void OutputHLSL::output()
177{
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +0000178 mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
Jamie Madill570e04d2013-06-21 09:15:33 -0400179 const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
180 makeFlaggedStructMaps(flaggedStructs);
daniel@transgaming.com89431aa2012-05-31 01:20:29 +0000181
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000182 mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000183 header();
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000184
alokp@chromium.org646ea1e2012-06-15 17:36:31 +0000185 mContext.infoSink().obj << mHeader.c_str();
186 mContext.infoSink().obj << mBody.c_str();
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000187}
188
Jamie Madill570e04d2013-06-21 09:15:33 -0400189void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs)
190{
191 for (unsigned int structIndex = 0; structIndex < flaggedStructs.size(); structIndex++)
192 {
193 TIntermTyped *flaggedNode = flaggedStructs[structIndex];
194
195 // This will mark the necessary block elements as referenced
196 flaggedNode->traverse(this);
197 TString structName(mBody.c_str());
198 mBody.erase();
199
200 mFlaggedStructOriginalNames[flaggedNode] = structName;
201
202 for (size_t pos = structName.find('.'); pos != std::string::npos; pos = structName.find('.'))
203 {
204 structName.erase(pos, 1);
205 }
206
207 mFlaggedStructMappedNames[flaggedNode] = "map" + structName;
208 }
209}
210
daniel@transgaming.comb5875982010-04-15 20:44:53 +0000211TInfoSinkBase &OutputHLSL::getBodyStream()
212{
213 return mBody;
214}
215
daniel@transgaming.com043da132012-12-20 21:12:22 +0000216const ActiveUniforms &OutputHLSL::getUniforms()
217{
218 return mActiveUniforms;
219}
220
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000221const ActiveInterfaceBlocks &OutputHLSL::getInterfaceBlocks() const
222{
223 return mActiveInterfaceBlocks;
224}
225
Jamie Madill46131a32013-06-20 11:55:50 -0400226const ActiveShaderVariables &OutputHLSL::getOutputVariables() const
227{
228 return mActiveOutputVariables;
229}
230
Jamie Madilldefb6742013-06-20 11:55:51 -0400231const ActiveShaderVariables &OutputHLSL::getAttributes() const
232{
233 return mActiveAttributes;
234}
235
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000236int OutputHLSL::vectorSize(const TType &type) const
237{
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000238 int elementSize = type.isMatrix() ? type.getCols() : 1;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000239 int arraySize = type.isArray() ? type.getArraySize() : 1;
240
241 return elementSize * arraySize;
242}
243
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000244TString OutputHLSL::interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType)
245{
246 if (interfaceBlockType.hasInstanceName())
247 {
248 return interfaceBlockType.getTypeName() + "." + uniformType.getFieldName();
249 }
250 else
251 {
252 return uniformType.getFieldName();
253 }
254}
255
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000256TString OutputHLSL::decoratePrivate(const TString &privateText)
257{
258 return "dx_" + privateText;
259}
260
261TString OutputHLSL::interfaceBlockStructName(const TType &interfaceBlockType)
262{
263 return decoratePrivate(interfaceBlockType.getTypeName()) + "_type";
264}
265
266TString OutputHLSL::interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex)
267{
268 if (!interfaceBlockType.hasInstanceName())
269 {
270 return "";
271 }
272 else if (interfaceBlockType.isArray())
273 {
274 return decoratePrivate(interfaceBlockType.getInstanceName()) + "_" + str(arrayIndex);
275 }
276 else
277 {
278 return decorate(interfaceBlockType.getInstanceName());
279 }
280}
281
Jamie Madillc835df62013-06-21 09:15:32 -0400282TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType, TLayoutBlockStorage blockStorage)
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000283{
Jamie Madill529077d2013-06-20 11:55:54 -0400284 const TLayoutMatrixPacking matrixPacking = memberType.getLayoutQualifier().matrixPacking;
285 ASSERT(matrixPacking != EmpUnspecified);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000286
287 if (memberType.isMatrix())
288 {
Jamie Madill9cf6c072013-06-20 11:55:53 -0400289 // Use HLSL row-major packing for GLSL column-major matrices
Jamie Madill529077d2013-06-20 11:55:54 -0400290 const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
291 return matrixPackString + " " + typeString(memberType);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000292 }
293 else if (memberType.getBasicType() == EbtStruct)
294 {
Jamie Madill9cf6c072013-06-20 11:55:53 -0400295 // Use HLSL row-major packing for GLSL column-major matrices
Jamie Madillc835df62013-06-21 09:15:32 -0400296 return structureTypeName(memberType, matrixPacking == EmpColumnMajor, blockStorage == EbsStd140);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000297 }
298 else
299 {
300 return typeString(memberType);
301 }
302}
303
Jamie Madill574d9dd2013-06-20 11:55:56 -0400304TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex)
305{
306 if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
307 {
308 // no padding needed, HLSL will align the field to a new register
309 *elementIndex = 0;
310 return "";
311 }
312
313 const GLenum glType = glVariableType(type);
314 const int numComponents = gl::UniformComponentCount(glType);
315
316 if (numComponents >= 4)
317 {
318 // no padding needed, HLSL will align the field to a new register
319 *elementIndex = 0;
320 return "";
321 }
322
323 if (*elementIndex + numComponents > 4)
324 {
325 // no padding needed, HLSL will align the field to a new register
326 *elementIndex = numComponents;
327 return "";
328 }
329
330 TString padding;
331
332 const int alignment = numComponents == 3 ? 4 : numComponents;
333 const int paddingOffset = (*elementIndex % alignment);
334
335 if (paddingOffset != 0)
336 {
337 // padding is neccessary
338 for (int paddingIndex = paddingOffset; paddingIndex < alignment; paddingIndex++)
339 {
340 padding += " float pad_" + str(mPaddingCounter++) + ";\n";
341 }
342
343 *elementIndex += (alignment - paddingOffset);
344 }
345
346 *elementIndex += numComponents;
347 *elementIndex %= 4;
348
349 return padding;
350}
351
Jamie Madille4075c92013-06-21 09:15:32 -0400352TString OutputHLSL::std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking)
Jamie Madill574d9dd2013-06-20 11:55:56 -0400353{
Jamie Madillc835df62013-06-21 09:15:32 -0400354 if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
Jamie Madill574d9dd2013-06-20 11:55:56 -0400355 {
356 return "";
357 }
358
Jamie Madill574d9dd2013-06-20 11:55:56 -0400359 int numComponents = 0;
360
361 if (type.isMatrix())
362 {
Jamie Madille4075c92013-06-21 09:15:32 -0400363 // This method can also be called from structureString, which does not use layout qualifiers.
364 // Thus, use the method parameter for determining the matrix packing.
365 //
366 // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
367 // wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
368 //
369 const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
Jamie Madillc835df62013-06-21 09:15:32 -0400370 const GLenum glType = glVariableType(type);
Jamie Madill574d9dd2013-06-20 11:55:56 -0400371 numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
372 }
Jamie Madillc835df62013-06-21 09:15:32 -0400373 else if (type.getBasicType() == EbtStruct)
374 {
Jamie Madille4075c92013-06-21 09:15:32 -0400375 const TString &structName = structureTypeName(type, useHLSLRowMajorPacking, true);
376 numComponents = mStd140StructElementIndexes[structName];
377
378 if (numComponents == 0)
379 {
380 return "";
381 }
Jamie Madillc835df62013-06-21 09:15:32 -0400382 }
Jamie Madill574d9dd2013-06-20 11:55:56 -0400383 else
384 {
Jamie Madillc835df62013-06-21 09:15:32 -0400385 const GLenum glType = glVariableType(type);
Jamie Madill574d9dd2013-06-20 11:55:56 -0400386 numComponents = gl::UniformComponentCount(glType);
387 }
388
389 TString padding;
390 for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
391 {
392 padding += " float pad_" + str(mPaddingCounter++) + ";\n";
393 }
394 return padding;
395}
396
397TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage)
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000398{
399 TString hlsl;
400
Jamie Madill574d9dd2013-06-20 11:55:56 -0400401 int elementIndex = 0;
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000402
403 for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
404 {
405 const TType &memberType = *typeList[typeIndex].type;
Jamie Madill574d9dd2013-06-20 11:55:56 -0400406
407 if (blockStorage == EbsStd140)
408 {
Jamie Madillc835df62013-06-21 09:15:32 -0400409 // 2 and 3 component vector types in some cases need pre-padding
410 hlsl += std140PrePaddingString(memberType, &elementIndex);
Jamie Madill574d9dd2013-06-20 11:55:56 -0400411 }
412
Jamie Madillc835df62013-06-21 09:15:32 -0400413 hlsl += " " + interfaceBlockMemberTypeString(memberType, blockStorage) +
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000414 " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
Jamie Madill574d9dd2013-06-20 11:55:56 -0400415
416 // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
417 if (blockStorage == EbsStd140)
418 {
Jamie Madille4075c92013-06-21 09:15:32 -0400419 const bool useHLSLRowMajorPacking = (memberType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
420 hlsl += std140PostPaddingString(memberType, useHLSLRowMajorPacking);
Jamie Madill574d9dd2013-06-20 11:55:56 -0400421 }
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000422 }
423
424 return hlsl;
425}
426
427TString OutputHLSL::interfaceBlockStructString(const TType &interfaceBlockType)
428{
429 const TTypeList &typeList = *interfaceBlockType.getStruct();
Jamie Madill574d9dd2013-06-20 11:55:56 -0400430 const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000431
432 return "struct " + interfaceBlockStructName(interfaceBlockType) + "\n"
433 "{\n" +
Jamie Madill574d9dd2013-06-20 11:55:56 -0400434 interfaceBlockMemberString(typeList, blockStorage) +
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000435 "};\n\n";
436}
437
438TString OutputHLSL::interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex)
439{
440 const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : "");
441 const TString &blockName = interfaceBlockType.getTypeName() + arrayIndexString;
442 TString hlsl;
443
444 hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
445 "{\n";
446
447 if (interfaceBlockType.hasInstanceName())
448 {
449 hlsl += " " + interfaceBlockStructName(interfaceBlockType) + " " + interfaceBlockInstanceString(interfaceBlockType, arrayIndex) + ";\n";
450 }
451 else
452 {
453 const TTypeList &typeList = *interfaceBlockType.getStruct();
Jamie Madill574d9dd2013-06-20 11:55:56 -0400454 const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
455 hlsl += interfaceBlockMemberString(typeList, blockStorage);
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000456 }
457
458 hlsl += "};\n\n";
459
460 return hlsl;
461}
462
Jamie Madill440dc742013-06-20 11:55:55 -0400463// Use the same layout for packed and shared
464void setBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLayout)
465{
466 interfaceBlock->layout = newLayout;
467 interfaceBlock->blockInfo.clear();
468
469 switch (newLayout)
470 {
471 case BLOCKLAYOUT_SHARED:
472 case BLOCKLAYOUT_PACKED:
473 {
474 HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo);
475 hlslEncoder.encodeFields(interfaceBlock->activeUniforms);
476 interfaceBlock->dataSize = hlslEncoder.getBlockSize();
477 }
478 break;
479
480 case BLOCKLAYOUT_STANDARD:
481 {
482 Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo);
483 stdEncoder.encodeFields(interfaceBlock->activeUniforms);
484 interfaceBlock->dataSize = stdEncoder.getBlockSize();
485 }
486 break;
487
488 default:
489 UNREACHABLE();
490 break;
491 }
492}
493
Jamie Madill574d9dd2013-06-20 11:55:56 -0400494BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage)
495{
496 switch (blockStorage)
497 {
498 case EbsPacked: return BLOCKLAYOUT_PACKED;
499 case EbsShared: return BLOCKLAYOUT_SHARED;
500 case EbsStd140: return BLOCKLAYOUT_STANDARD;
501 default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
502 }
503}
504
Jamie Madill570e04d2013-06-21 09:15:33 -0400505TString OutputHLSL::structInitializerString(int indent, const TTypeList &structMembers, const TString &structName)
506{
507 TString init;
508
509 TString preIndentString;
510 TString fullIndentString;
511
512 for (int spaces = 0; spaces < (indent * 4); spaces++)
513 {
514 preIndentString += ' ';
515 }
516
517 for (int spaces = 0; spaces < ((indent+1) * 4); spaces++)
518 {
519 fullIndentString += ' ';
520 }
521
522 init += preIndentString + "{\n";
523
524 for (unsigned int memberIndex = 0; memberIndex < structMembers.size(); memberIndex++)
525 {
526 const TType &memberType = *structMembers[memberIndex].type;
527 const TString &fieldName = decorate(memberType.getFieldName());
528
529 if (memberType.getBasicType() == EbtStruct)
530 {
531 const TTypeList &nestedStructMembers = *memberType.getStruct();
532 init += structInitializerString(indent + 1, nestedStructMembers, structName + "." + fieldName);
533 }
534 else
535 {
536 init += fullIndentString + structName + "." + fieldName + ",\n";
537 }
538 }
539
540 init += preIndentString + "}" + (indent == 0 ? ";" : ",") + "\n";
541
542 return init;
543}
544
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545void OutputHLSL::header()
546{
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000547 TInfoSinkBase &out = mHeader;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000548
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000549 TString uniforms;
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000550 TString interfaceBlocks;
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000551 TString varyings;
552 TString attributes;
Jamie Madill570e04d2013-06-21 09:15:33 -0400553 TString flaggedStructs;
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000554
555 for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++)
556 {
557 const TType &type = uniform->second->getType();
558 const TString &name = uniform->second->getSymbol();
559
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000560 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture
561 {
562 int index = samplerRegister(mReferencedUniforms[name]);
563
564 uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) +
565 " : register(s" + str(index) + ");\n";
566
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000567 uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000568 " : register(t" + str(index) + ");\n";
569 }
570 else
571 {
572 uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) +
573 " : register(" + registerString(mReferencedUniforms[name]) + ");\n";
574 }
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000575 }
576
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000577 for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
578 {
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000579 const TType &nodeType = interfaceBlockIt->second->getType();
580 const TType &interfaceBlockType = nodeType.isInterfaceBlockMember() ? *nodeType.getInterfaceBlockType() : nodeType;
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000581 const TString &blockName = interfaceBlockType.getTypeName();
582 const TTypeList &typeList = *interfaceBlockType.getStruct();
583
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000584 const unsigned int arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getArraySize() : 0;
585 sh::InterfaceBlock interfaceBlock(blockName.c_str(), arraySize, mInterfaceBlockRegister);
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000586 for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
587 {
588 const TType &memberType = *typeList[typeIndex].type;
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000589 const TString &fullUniformName = interfaceBlockUniformName(interfaceBlockType, memberType);
590 declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms);
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000591 }
592
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000593 mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
594
Jamie Madill574d9dd2013-06-20 11:55:56 -0400595 BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlockType.getLayoutQualifier().blockStorage);
596 setBlockLayout(&interfaceBlock, blockLayoutType);
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000597 mActiveInterfaceBlocks.push_back(interfaceBlock);
598
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000599 if (interfaceBlockType.hasInstanceName())
600 {
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000601 interfaceBlocks += interfaceBlockStructString(interfaceBlockType);
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000602 }
603
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000604 if (arraySize > 0)
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000605 {
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000606 for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
607 {
608 interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex + arrayIndex, arrayIndex);
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000609 }
610 }
611 else
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000612 {
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000613 interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex, GL_INVALID_INDEX);
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000614 }
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000615 }
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000616
Jamie Madill570e04d2013-06-21 09:15:33 -0400617 for (auto flaggedStructIt = mFlaggedStructMappedNames.begin(); flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++)
618 {
619 TIntermTyped *structNode = flaggedStructIt->first;
620 const TString &mappedName = flaggedStructIt->second;
621 const TType &structType = structNode->getType();
622 const TTypeList &structMembers = *structType.getStruct();
623 const TString &originalName = mFlaggedStructOriginalNames[structNode];
624
625 flaggedStructs += "static " + decorate(structType.getTypeName()) + " " + mappedName + " =\n";
626 flaggedStructs += structInitializerString(0, structMembers, originalName);
627 flaggedStructs += "\n";
628 }
629
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000630 for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
631 {
632 const TType &type = varying->second->getType();
633 const TString &name = varying->second->getSymbol();
634
635 // Program linking depends on this exact format
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000636 varyings += "static " + interpolationString(type.getQualifier()) + " " + typeString(type) + " " +
637 decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000638 }
639
640 for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
641 {
642 const TType &type = attribute->second->getType();
643 const TString &name = attribute->second->getSymbol();
644
645 attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
Jamie Madilldefb6742013-06-20 11:55:51 -0400646
647 ShaderVariable shaderVar(glVariableType(type), glVariablePrecision(type), name.c_str(),
648 (unsigned int)type.getArraySize(), type.getLayoutQualifier().location);
649 mActiveAttributes.push_back(shaderVar);
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000650 }
651
Jamie Madill529077d2013-06-20 11:55:54 -0400652 for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
653 {
654 out << *structDeclaration;
655 }
656
657 for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
658 {
659 out << *constructor;
660 }
661
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400662 if (mContext.shaderType == SH_FRAGMENT_SHADER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663 {
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000664 TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
shannon.woods%transgaming.com@gtempaccount.com99ab6eb2013-04-13 03:42:00 +0000665 const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000666
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000667 out << "// Varyings\n";
668 out << varyings;
Jamie Madill46131a32013-06-20 11:55:50 -0400669 out << "\n";
670
671 if (mContext.getShaderVersion() >= 300)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000672 {
Jamie Madill46131a32013-06-20 11:55:50 -0400673 for (auto outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000674 {
Jamie Madill46131a32013-06-20 11:55:50 -0400675 const TString &variableName = outputVariableIt->first;
676 const TType &variableType = outputVariableIt->second->getType();
677 const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier();
678
679 out << "static " + typeString(variableType) + " out_" + variableName + arrayString(variableType) +
680 " = " + initializer(variableType) + ";\n";
681
682 ShaderVariable outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(),
683 (unsigned int)variableType.getArraySize(), layoutQualifier.location);
684 mActiveOutputVariables.push_back(outputVar);
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000685 }
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000686 }
Jamie Madill46131a32013-06-20 11:55:50 -0400687 else
688 {
689 const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
690
691 out << "static float4 gl_Color[" << numColorValues << "] =\n"
692 "{\n";
693 for (unsigned int i = 0; i < numColorValues; i++)
694 {
695 out << " float4(0, 0, 0, 0)";
696 if (i + 1 != numColorValues)
697 {
698 out << ",";
699 }
700 out << "\n";
701 }
702
703 out << "};\n";
704 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000705
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400706 if (mUsesFragDepth)
707 {
708 out << "static float gl_Depth = 0.0;\n";
709 }
710
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000711 if (mUsesFragCoord)
712 {
713 out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
714 }
715
716 if (mUsesPointCoord)
717 {
718 out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
719 }
720
721 if (mUsesFrontFacing)
722 {
723 out << "static bool gl_FrontFacing = false;\n";
724 }
725
726 out << "\n";
727
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000728 if (mUsesDepthRange)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000729 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000730 out << "struct gl_DepthRangeParameters\n"
731 "{\n"
732 " float near;\n"
733 " float far;\n"
734 " float diff;\n"
735 "};\n"
736 "\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000737 }
738
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000739 if (mOutputType == SH_HLSL11_OUTPUT)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000740 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000741 out << "cbuffer DriverConstants : register(b1)\n"
742 "{\n";
743
744 if (mUsesDepthRange)
745 {
746 out << " float3 dx_DepthRange : packoffset(c0);\n";
747 }
748
749 if (mUsesFragCoord)
750 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000751 out << " float4 dx_ViewCoords : packoffset(c1);\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000752 }
753
754 if (mUsesFragCoord || mUsesFrontFacing)
755 {
756 out << " float3 dx_DepthFront : packoffset(c2);\n";
757 }
758
759 out << "};\n";
760 }
761 else
762 {
763 if (mUsesDepthRange)
764 {
765 out << "uniform float3 dx_DepthRange : register(c0);";
766 }
767
768 if (mUsesFragCoord)
769 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000770 out << "uniform float4 dx_ViewCoords : register(c1);\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000771 }
772
773 if (mUsesFragCoord || mUsesFrontFacing)
774 {
775 out << "uniform float3 dx_DepthFront : register(c2);\n";
776 }
777 }
778
779 out << "\n";
780
781 if (mUsesDepthRange)
782 {
783 out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
784 "\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000785 }
786
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000787 out << uniforms;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000788 out << "\n";
daniel@transgaming.com5024cc42010-04-20 18:52:04 +0000789
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000790 if (!interfaceBlocks.empty())
791 {
792 out << interfaceBlocks;
793 out << "\n";
Jamie Madill570e04d2013-06-21 09:15:33 -0400794
795 if (!flaggedStructs.empty())
796 {
797 out << "// Std140 Structures accessed by value\n";
798 out << "\n";
799 out << flaggedStructs;
800 out << "\n";
801 }
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000802 }
803
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000804 if (usingMRTExtension && mNumRenderTargets > 1)
805 {
806 out << "#define GL_USES_MRT\n";
807 }
808
809 if (mUsesFragColor)
810 {
811 out << "#define GL_USES_FRAG_COLOR\n";
812 }
813
814 if (mUsesFragData)
815 {
816 out << "#define GL_USES_FRAG_DATA\n";
817 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818 }
daniel@transgaming.comd25ab252010-03-30 03:36:26 +0000819 else // Vertex shader
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000821 out << "// Attributes\n";
822 out << attributes;
823 out << "\n"
824 "static float4 gl_Position = float4(0, 0, 0, 0);\n";
825
826 if (mUsesPointSize)
827 {
828 out << "static float gl_PointSize = float(1);\n";
829 }
830
831 out << "\n"
832 "// Varyings\n";
833 out << varyings;
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000834 out << "\n";
835
836 if (mUsesDepthRange)
837 {
838 out << "struct gl_DepthRangeParameters\n"
839 "{\n"
840 " float near;\n"
841 " float far;\n"
842 " float diff;\n"
843 "};\n"
844 "\n";
845 }
846
847 if (mOutputType == SH_HLSL11_OUTPUT)
848 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000849 if (mUsesDepthRange)
850 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000851 out << "cbuffer DriverConstants : register(b1)\n"
852 "{\n"
853 " float3 dx_DepthRange : packoffset(c0);\n"
854 "};\n"
855 "\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000856 }
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000857 }
858 else
859 {
860 if (mUsesDepthRange)
861 {
862 out << "uniform float3 dx_DepthRange : register(c0);\n";
863 }
864
shannon.woods@transgaming.com42832a62013-02-28 23:18:38 +0000865 out << "uniform float4 dx_ViewAdjust : register(c1);\n"
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000866 "\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000867 }
868
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000869 if (mUsesDepthRange)
870 {
871 out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
872 "\n";
873 }
874
875 out << uniforms;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876 out << "\n";
daniel@transgaming.com15795192011-05-11 15:36:20 +0000877
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000878 if (!interfaceBlocks.empty())
879 {
880 out << interfaceBlocks;
881 out << "\n";
Jamie Madill570e04d2013-06-21 09:15:33 -0400882
883 if (!flaggedStructs.empty())
884 {
885 out << "// Std140 Structures accessed by value\n";
886 out << "\n";
887 out << flaggedStructs;
888 out << "\n";
889 }
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000890 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400891 }
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000892
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400893 for (TextureFunctionSet::const_iterator textureFunction = mUsesTexture.begin(); textureFunction != mUsesTexture.end(); textureFunction++)
894 {
895 // Return type
896 switch(textureFunction->sampler)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000897 {
Nicolas Capensfb50dff2013-06-24 16:16:23 -0400898 case EbtSampler2D: out << "float4 "; break;
899 case EbtSampler3D: out << "float4 "; break;
900 case EbtSamplerCube: out << "float4 "; break;
901 case EbtSampler2DArray: out << "float4 "; break;
902 case EbtISampler2D: out << "int4 "; break;
903 case EbtISampler3D: out << "int4 "; break;
904 case EbtISamplerCube: out << "int4 "; break;
905 case EbtISampler2DArray: out << "int4 "; break;
906 case EbtUSampler2D: out << "uint4 "; break;
907 case EbtUSampler3D: out << "uint4 "; break;
908 case EbtUSamplerCube: out << "uint4 "; break;
909 case EbtUSampler2DArray: out << "uint4 "; break;
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400910 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000911 }
912
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400913 // Function name
914 out << textureFunction->name();
915
916 // Argument list
917 int hlslCoords = 4;
918
919 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000920 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400921 switch(textureFunction->sampler)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000922 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400923 case EbtSampler2D: out << "sampler2D s"; hlslCoords = 2; break;
924 case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break;
925 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000926 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400927
928 switch(textureFunction->mipmap)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000929 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400930 case TextureFunction::IMPLICIT: break;
931 case TextureFunction::BIAS: hlslCoords = 4; break;
932 case TextureFunction::LOD: hlslCoords = 4; break;
933 case TextureFunction::LOD0: hlslCoords = 4; break;
934 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000935 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400936 }
937 else if (mOutputType == SH_HLSL11_OUTPUT)
938 {
939 switch(textureFunction->sampler)
940 {
Nicolas Capensfb50dff2013-06-24 16:16:23 -0400941 case EbtSampler2D: out << "Texture2D x, SamplerState s"; hlslCoords = 2; break;
942 case EbtSampler3D: out << "Texture3D x, SamplerState s"; hlslCoords = 3; break;
943 case EbtSamplerCube: out << "TextureCube x, SamplerState s"; hlslCoords = 3; break;
944 case EbtSampler2DArray: out << "Texture2DArray x, SamplerState s"; hlslCoords = 2; break;
945 case EbtISampler2D: out << "Texture2D<int4> x, SamplerState s"; hlslCoords = 2; break;
946 case EbtISampler3D: out << "Texture3D<int4> x, SamplerState s"; hlslCoords = 3; break;
947 case EbtISamplerCube: out << "TextureCube<int4> x, SamplerState s"; hlslCoords = 3; break;
948 case EbtISampler2DArray: out << "Texture2DArray<int4> x, SamplerState s"; hlslCoords = 2; break;
949 case EbtUSampler2D: out << "Texture2D<uint4> x, SamplerState s"; hlslCoords = 2; break;
950 case EbtUSampler3D: out << "Texture3D<uint4> x, SamplerState s"; hlslCoords = 3; break;
951 case EbtUSamplerCube: out << "TextureCube<uint4> x, SamplerState s"; hlslCoords = 3; break;
952 case EbtUSampler2DArray: out << "Texture2DArray<uint4> x, SamplerState s"; hlslCoords = 2; break;
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400953 default: UNREACHABLE();
954 }
955 }
956 else UNREACHABLE();
957
958 switch(textureFunction->coords)
959 {
960 case 2: out << ", float2 t"; break;
961 case 3: out << ", float3 t"; break;
962 case 4: out << ", float4 t"; break;
963 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000964 }
965
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400966 switch(textureFunction->mipmap)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000967 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400968 case TextureFunction::IMPLICIT: break;
969 case TextureFunction::BIAS: out << ", float bias"; break;
970 case TextureFunction::LOD: out << ", float lod"; break;
971 case TextureFunction::LOD0: break;
972 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000973 }
974
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400975 out << ")\n"
976 "{\n"
977 " return ";
978
979 // HLSL intrinsic
980 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000981 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400982 switch(textureFunction->sampler)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000983 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400984 case EbtSampler2D: out << "tex2D"; break;
985 case EbtSamplerCube: out << "texCUBE"; break;
986 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000987 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400988 }
989 else if (mOutputType == SH_HLSL11_OUTPUT)
990 {
991 out << "x.Sample";
992 }
993 else UNREACHABLE();
994
995 if (mOutputType == SH_HLSL9_OUTPUT)
996 {
997 switch(textureFunction->mipmap)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000998 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400999 case TextureFunction::IMPLICIT: out << "(s, "; break;
1000 case TextureFunction::BIAS: out << "bias(s, "; break;
1001 case TextureFunction::LOD: out << "lod(s, "; break;
1002 case TextureFunction::LOD0: out << "lod(s, "; break;
1003 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00001004 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001005 }
1006 else if (mOutputType == SH_HLSL11_OUTPUT)
1007 {
1008 switch(textureFunction->mipmap)
1009 {
1010 case TextureFunction::IMPLICIT: out << "(s, "; break;
1011 case TextureFunction::BIAS: out << "Bias(s, "; break;
1012 case TextureFunction::LOD: out << "Level(s, "; break;
1013 case TextureFunction::LOD0: out << "Level(s, "; break;
1014 default: UNREACHABLE();
1015 }
1016 }
1017 else UNREACHABLE();
1018
1019 switch(hlslCoords)
1020 {
1021 case 2: out << "float2("; break;
1022 case 3: out << "float3("; break;
1023 case 4: out << "float4("; break;
1024 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +00001025 }
1026
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001027 TString proj = "";
1028
1029 if (textureFunction->proj)
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001030 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001031 switch(textureFunction->coords)
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001032 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001033 case 3: proj = " / t.z"; break;
1034 case 4: proj = " / t.w"; break;
1035 default: UNREACHABLE();
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001036 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001037 }
1038
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001039 out << "t.x" + proj + ", t.y" + proj;
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001040
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001041 if (mOutputType == SH_HLSL9_OUTPUT)
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001042 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001043 if (hlslCoords >= 3)
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001044 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001045 if (textureFunction->coords < 3)
1046 {
1047 out << ", 0";
1048 }
1049 else
1050 {
1051 out << ", t.z" + proj;
1052 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001053 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001054
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001055 if (hlslCoords == 4)
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001056 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001057 switch(textureFunction->mipmap)
1058 {
1059 case TextureFunction::BIAS: out << ", bias"; break;
1060 case TextureFunction::LOD: out << ", lod"; break;
1061 case TextureFunction::LOD0: out << ", 0"; break;
1062 default: UNREACHABLE();
1063 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001064 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04001065
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001066 out << "));\n";
daniel@transgaming.com15795192011-05-11 15:36:20 +00001067 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001068 else if (mOutputType == SH_HLSL11_OUTPUT)
1069 {
1070 if (hlslCoords >= 3)
1071 {
1072 out << ", t.z" + proj;
1073 }
daniel@transgaming.com15795192011-05-11 15:36:20 +00001074
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001075 switch(textureFunction->mipmap)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00001076 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001077 case TextureFunction::IMPLICIT: out << "));"; break;
1078 case TextureFunction::BIAS: out << "), bias);"; break;
1079 case TextureFunction::LOD: out << "), lod);"; break;
1080 case TextureFunction::LOD0: out << "), 0);"; break;
1081 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00001082 }
daniel@transgaming.com15795192011-05-11 15:36:20 +00001083 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04001084 else UNREACHABLE();
1085
1086 out << "}\n"
1087 "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001088 }
1089
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001090 if (mUsesFragCoord)
1091 {
1092 out << "#define GL_USES_FRAG_COORD\n";
1093 }
1094
1095 if (mUsesPointCoord)
1096 {
1097 out << "#define GL_USES_POINT_COORD\n";
1098 }
1099
1100 if (mUsesFrontFacing)
1101 {
1102 out << "#define GL_USES_FRONT_FACING\n";
1103 }
1104
1105 if (mUsesPointSize)
1106 {
1107 out << "#define GL_USES_POINT_SIZE\n";
1108 }
1109
Jamie Madill2aeb26a2013-07-08 14:02:55 -04001110 if (mUsesFragDepth)
1111 {
1112 out << "#define GL_USES_FRAG_DEPTH\n";
1113 }
1114
shannonwoods@chromium.org03299882013-05-30 00:05:26 +00001115 if (mUsesDepthRange)
1116 {
1117 out << "#define GL_USES_DEPTH_RANGE\n";
1118 }
1119
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001120 if (mUsesXor)
1121 {
1122 out << "bool xor(bool p, bool q)\n"
1123 "{\n"
1124 " return (p || q) && !(p && q);\n"
1125 "}\n"
1126 "\n";
1127 }
1128
1129 if (mUsesMod1)
1130 {
1131 out << "float mod(float x, float y)\n"
1132 "{\n"
1133 " return x - y * floor(x / y);\n"
1134 "}\n"
1135 "\n";
1136 }
daniel@transgaming.com4229f592011-11-24 22:34:04 +00001137
1138 if (mUsesMod2v)
1139 {
1140 out << "float2 mod(float2 x, float2 y)\n"
1141 "{\n"
1142 " return x - y * floor(x / y);\n"
1143 "}\n"
1144 "\n";
1145 }
1146
1147 if (mUsesMod2f)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001148 {
1149 out << "float2 mod(float2 x, float y)\n"
1150 "{\n"
1151 " return x - y * floor(x / y);\n"
1152 "}\n"
1153 "\n";
1154 }
1155
daniel@transgaming.com4229f592011-11-24 22:34:04 +00001156 if (mUsesMod3v)
1157 {
1158 out << "float3 mod(float3 x, float3 y)\n"
1159 "{\n"
1160 " return x - y * floor(x / y);\n"
1161 "}\n"
1162 "\n";
1163 }
1164
1165 if (mUsesMod3f)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001166 {
1167 out << "float3 mod(float3 x, float y)\n"
1168 "{\n"
1169 " return x - y * floor(x / y);\n"
1170 "}\n"
1171 "\n";
1172 }
1173
daniel@transgaming.com4229f592011-11-24 22:34:04 +00001174 if (mUsesMod4v)
1175 {
1176 out << "float4 mod(float4 x, float4 y)\n"
1177 "{\n"
1178 " return x - y * floor(x / y);\n"
1179 "}\n"
1180 "\n";
1181 }
1182
1183 if (mUsesMod4f)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001184 {
1185 out << "float4 mod(float4 x, float y)\n"
1186 "{\n"
1187 " return x - y * floor(x / y);\n"
1188 "}\n"
1189 "\n";
1190 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001191
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001192 if (mUsesFaceforward1)
1193 {
1194 out << "float faceforward(float N, float I, float Nref)\n"
1195 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001196 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001197 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001198 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001199 " }\n"
1200 " else\n"
1201 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001202 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001203 " }\n"
1204 "}\n"
1205 "\n";
1206 }
1207
1208 if (mUsesFaceforward2)
1209 {
1210 out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
1211 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001212 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001213 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001214 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001215 " }\n"
1216 " else\n"
1217 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001218 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001219 " }\n"
1220 "}\n"
1221 "\n";
1222 }
1223
1224 if (mUsesFaceforward3)
1225 {
1226 out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
1227 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001228 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001229 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001230 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001231 " }\n"
1232 " else\n"
1233 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001234 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001235 " }\n"
1236 "}\n"
1237 "\n";
1238 }
1239
1240 if (mUsesFaceforward4)
1241 {
1242 out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
1243 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001244 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001245 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001246 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001247 " }\n"
1248 " else\n"
1249 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001250 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001251 " }\n"
1252 "}\n"
1253 "\n";
1254 }
1255
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001256 for (unsigned int cols = 2; cols <= 4; cols++)
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001257 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001258 for (unsigned int rows = 2; rows <= 4; rows++)
1259 {
1260 if (mUsesEqualMat[cols][rows])
1261 {
1262 TString matrixType = "float" + str(cols) + "x" + str(rows);
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001263
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001264 out << "bool equal(" + matrixType + " m, " + matrixType + " n)\n"
1265 "{\n";
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001266
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001267 for (unsigned int row = 0; row < rows; row++)
1268 {
1269 if (row == 0)
1270 {
1271 out << " return ";
1272 }
1273 else
1274 {
1275 out << " ";
1276 }
1277
1278 for (unsigned int col = 0; col < cols; col++)
1279 {
1280 TString index = "[" + str(col) + "][" + str(row) + "]";
1281 out << "m" + index + " == n" + index;
1282
1283 if (col == cols-1 && row == rows-1)
1284 {
1285 out << ";\n";
1286 }
1287 else if (col == cols-1)
1288 {
1289 out << " &&\n";
1290 }
1291 else
1292 {
1293 out << " && ";
1294 }
1295 }
1296 }
1297
1298 out << "}\n";
1299 }
1300 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001301 }
1302
1303 if (mUsesEqualVec2)
1304 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001305 out << "bool equal(float2 v, float2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001306 "{\n"
1307 " return v.x == u.x && v.y == u.y;\n"
1308 "}\n";
1309 }
1310
1311 if (mUsesEqualVec3)
1312 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001313 out << "bool equal(float3 v, float3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001314 "{\n"
1315 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1316 "}\n";
1317 }
1318
1319 if (mUsesEqualVec4)
1320 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001321 out << "bool equal(float4 v, float4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001322 "{\n"
1323 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1324 "}\n";
1325 }
1326
1327 if (mUsesEqualIVec2)
1328 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001329 out << "bool equal(int2 v, int2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001330 "{\n"
1331 " return v.x == u.x && v.y == u.y;\n"
1332 "}\n";
1333 }
1334
1335 if (mUsesEqualIVec3)
1336 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001337 out << "bool equal(int3 v, int3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001338 "{\n"
1339 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1340 "}\n";
1341 }
1342
1343 if (mUsesEqualIVec4)
1344 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001345 out << "bool equal(int4 v, int4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001346 "{\n"
1347 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1348 "}\n";
1349 }
1350
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00001351 if (mUsesEqualUVec2)
1352 {
1353 out << "bool equal(uint2 v, uint2 u)\n"
1354 "{\n"
1355 " return v.x == u.x && v.y == u.y;\n"
1356 "}\n";
1357 }
1358
1359 if (mUsesEqualUVec3)
1360 {
1361 out << "bool equal(uint3 v, uint3 u)\n"
1362 "{\n"
1363 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1364 "}\n";
1365 }
1366
1367 if (mUsesEqualUVec4)
1368 {
1369 out << "bool equal(uint4 v, uint4 u)\n"
1370 "{\n"
1371 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1372 "}\n";
1373 }
1374
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001375 if (mUsesEqualBVec2)
1376 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001377 out << "bool equal(bool2 v, bool2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001378 "{\n"
1379 " return v.x == u.x && v.y == u.y;\n"
1380 "}\n";
1381 }
1382
1383 if (mUsesEqualBVec3)
1384 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001385 out << "bool equal(bool3 v, bool3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001386 "{\n"
1387 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1388 "}\n";
1389 }
1390
1391 if (mUsesEqualBVec4)
1392 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001393 out << "bool equal(bool4 v, bool4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001394 "{\n"
1395 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1396 "}\n";
1397 }
daniel@transgaming.com0f189612010-05-07 13:03:36 +00001398
daniel@transgaming.com35342dc2012-02-28 02:01:22 +00001399 if (mUsesAtan2_1)
daniel@transgaming.com0f189612010-05-07 13:03:36 +00001400 {
1401 out << "float atanyx(float y, float x)\n"
1402 "{\n"
1403 " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
1404 " return atan2(y, x);\n"
1405 "}\n";
1406 }
daniel@transgaming.com35342dc2012-02-28 02:01:22 +00001407
1408 if (mUsesAtan2_2)
1409 {
1410 out << "float2 atanyx(float2 y, float2 x)\n"
1411 "{\n"
1412 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1413 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1414 " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
1415 "}\n";
1416 }
1417
1418 if (mUsesAtan2_3)
1419 {
1420 out << "float3 atanyx(float3 y, float3 x)\n"
1421 "{\n"
1422 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1423 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1424 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
1425 " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
1426 "}\n";
1427 }
1428
1429 if (mUsesAtan2_4)
1430 {
1431 out << "float4 atanyx(float4 y, float4 x)\n"
1432 "{\n"
1433 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1434 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1435 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
1436 " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
1437 " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
1438 "}\n";
1439 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001440}
1441
1442void OutputHLSL::visitSymbol(TIntermSymbol *node)
1443{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001444 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001445
Jamie Madill570e04d2013-06-21 09:15:33 -04001446 // Handle accessing std140 structs by value
1447 if (mFlaggedStructMappedNames.count(node) > 0)
1448 {
1449 out << mFlaggedStructMappedNames[node];
1450 return;
1451 }
1452
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001453 TString name = node->getSymbol();
1454
shannon.woods%transgaming.com@gtempaccount.come7d4a242013-04-13 03:38:33 +00001455 if (name == "gl_DepthRange")
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001456 {
1457 mUsesDepthRange = true;
1458 out << name;
1459 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001460 else
1461 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001462 TQualifier qualifier = node->getQualifier();
1463
1464 if (qualifier == EvqUniform)
1465 {
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +00001466 if (node->getType().isInterfaceBlockMember())
1467 {
1468 const TString& interfaceBlockTypeName = node->getType().getInterfaceBlockType()->getTypeName();
1469 mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
1470 out << decorateUniform(name, node->getType());
1471 }
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +00001472 else if (node->getBasicType() == EbtInterfaceBlock)
1473 {
1474 const TString& interfaceBlockTypeName = node->getType().getTypeName();
1475 mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
1476 out << decorateUniform(name, node->getType());
1477 }
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +00001478 else
1479 {
1480 mReferencedUniforms[name] = node;
1481 out << decorateUniform(name, node->getType());
1482 }
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001483 }
Jamie Madillb120eac2013-06-12 14:08:13 -04001484 else if (qualifier == EvqAttribute || qualifier == EvqVertexInput)
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001485 {
daniel@transgaming.com8803b852012-12-20 21:11:47 +00001486 mReferencedAttributes[name] = node;
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001487 out << decorate(name);
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001488 }
shannon.woods%transgaming.com@gtempaccount.com6f273e32013-04-13 03:41:15 +00001489 else if (isVarying(qualifier))
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001490 {
daniel@transgaming.com8803b852012-12-20 21:11:47 +00001491 mReferencedVaryings[name] = node;
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001492 out << decorate(name);
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001493 }
Jamie Madill46131a32013-06-20 11:55:50 -04001494 else if (qualifier == EvqFragmentOutput)
1495 {
1496 mReferencedOutputVariables[name] = node;
1497 out << "out_" << name;
1498 }
1499 else if (qualifier == EvqFragColor)
shannon.woods%transgaming.com@gtempaccount.come7d4a242013-04-13 03:38:33 +00001500 {
1501 out << "gl_Color[0]";
1502 mUsesFragColor = true;
1503 }
1504 else if (qualifier == EvqFragData)
1505 {
1506 out << "gl_Color";
1507 mUsesFragData = true;
1508 }
1509 else if (qualifier == EvqFragCoord)
1510 {
1511 mUsesFragCoord = true;
1512 out << name;
1513 }
1514 else if (qualifier == EvqPointCoord)
1515 {
1516 mUsesPointCoord = true;
1517 out << name;
1518 }
1519 else if (qualifier == EvqFrontFacing)
1520 {
1521 mUsesFrontFacing = true;
1522 out << name;
1523 }
1524 else if (qualifier == EvqPointSize)
1525 {
1526 mUsesPointSize = true;
1527 out << name;
1528 }
Jamie Madill2aeb26a2013-07-08 14:02:55 -04001529 else if (name == "gl_FragDepthEXT")
1530 {
1531 mUsesFragDepth = true;
1532 out << "gl_Depth";
1533 }
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001534 else
1535 {
1536 out << decorate(name);
1537 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001538 }
1539}
1540
1541bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
1542{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001543 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001544
Jamie Madill570e04d2013-06-21 09:15:33 -04001545 // Handle accessing std140 structs by value
1546 if (mFlaggedStructMappedNames.count(node) > 0)
1547 {
1548 out << mFlaggedStructMappedNames[node];
1549 return false;
1550 }
1551
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001552 switch (node->getOp())
1553 {
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001554 case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001555 case EOpInitialize:
1556 if (visit == PreVisit)
1557 {
1558 // GLSL allows to write things like "float x = x;" where a new variable x is defined
1559 // and the value of an existing variable x is assigned. HLSL uses C semantics (the
1560 // new variable is created before the assignment is evaluated), so we need to convert
1561 // this to "float t = x, x = t;".
1562
daniel@transgaming.combdfb2e52010-11-15 16:41:20 +00001563 TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
1564 TIntermTyped *expression = node->getRight();
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001565
daniel@transgaming.combdfb2e52010-11-15 16:41:20 +00001566 sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
1567 expression->traverse(&searchSymbol);
1568 bool sameSymbol = searchSymbol.foundMatch();
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001569
daniel@transgaming.combdfb2e52010-11-15 16:41:20 +00001570 if (sameSymbol)
1571 {
1572 // Type already printed
1573 out << "t" + str(mUniqueIndex) + " = ";
1574 expression->traverse(this);
1575 out << ", ";
1576 symbolNode->traverse(this);
1577 out << " = t" + str(mUniqueIndex);
1578
1579 mUniqueIndex++;
1580 return false;
1581 }
1582 }
1583 else if (visit == InVisit)
1584 {
1585 out << " = ";
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001586 }
1587 break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001588 case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break;
1589 case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break;
1590 case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break;
1591 case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
1592 case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
1593 case EOpVectorTimesMatrixAssign:
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001594 if (visit == PreVisit)
1595 {
1596 out << "(";
1597 }
1598 else if (visit == InVisit)
1599 {
1600 out << " = mul(";
1601 node->getLeft()->traverse(this);
1602 out << ", transpose(";
1603 }
1604 else
1605 {
daniel@transgaming.com3aa74202010-04-29 03:39:04 +00001606 out << ")))";
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001607 }
1608 break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001609 case EOpMatrixTimesMatrixAssign:
1610 if (visit == PreVisit)
1611 {
1612 out << "(";
1613 }
1614 else if (visit == InVisit)
1615 {
1616 out << " = mul(";
1617 node->getLeft()->traverse(this);
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001618 out << ", ";
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001619 }
1620 else
1621 {
daniel@transgaming.com3aa74202010-04-29 03:39:04 +00001622 out << "))";
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001623 }
1624 break;
1625 case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
Jamie Madillb4e664b2013-06-20 11:55:54 -04001626 case EOpIndexDirect:
1627 if (node->getLeft()->getBasicType() == EbtInterfaceBlock)
1628 {
1629 if (visit == PreVisit)
1630 {
1631 const TType &interfaceBlockType = node->getLeft()->getType();
1632 mReferencedInterfaceBlocks[interfaceBlockType.getInstanceName()] = node->getLeft()->getAsSymbolNode();
1633 out << interfaceBlockInstanceString(interfaceBlockType, node->getRight()->getAsConstantUnion()->getIConst(0));
1634 return false;
1635 }
1636 }
1637 else
1638 {
1639 outputTriplet(visit, "", "[", "]");
1640 }
1641 break;
1642 case EOpIndexIndirect:
1643 // We do not currently support indirect references to interface blocks
1644 ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
1645 outputTriplet(visit, "", "[", "]");
1646 break;
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00001647 case EOpIndexDirectStruct:
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +00001648 case EOpIndexDirectInterfaceBlock:
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00001649 if (visit == InVisit)
1650 {
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00001651 out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00001652
1653 return false;
1654 }
1655 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001656 case EOpVectorSwizzle:
1657 if (visit == InVisit)
1658 {
1659 out << ".";
1660
1661 TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
1662
1663 if (swizzle)
1664 {
1665 TIntermSequence &sequence = swizzle->getSequence();
1666
1667 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
1668 {
1669 TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
1670
1671 if (element)
1672 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00001673 int i = element->getIConst(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001674
1675 switch (i)
1676 {
1677 case 0: out << "x"; break;
1678 case 1: out << "y"; break;
1679 case 2: out << "z"; break;
1680 case 3: out << "w"; break;
1681 default: UNREACHABLE();
1682 }
1683 }
1684 else UNREACHABLE();
1685 }
1686 }
1687 else UNREACHABLE();
1688
1689 return false; // Fully processed
1690 }
1691 break;
1692 case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break;
1693 case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
1694 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
1695 case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001696 case EOpEqual:
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001697 case EOpNotEqual:
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001698 if (node->getLeft()->isScalar())
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001699 {
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001700 if (node->getOp() == EOpEqual)
1701 {
1702 outputTriplet(visit, "(", " == ", ")");
1703 }
1704 else
1705 {
1706 outputTriplet(visit, "(", " != ", ")");
1707 }
1708 }
1709 else if (node->getLeft()->getBasicType() == EbtStruct)
1710 {
1711 if (node->getOp() == EOpEqual)
1712 {
1713 out << "(";
1714 }
1715 else
1716 {
1717 out << "!(";
1718 }
1719
1720 const TTypeList *fields = node->getLeft()->getType().getStruct();
1721
1722 for (size_t i = 0; i < fields->size(); i++)
1723 {
1724 const TType *fieldType = (*fields)[i].type;
1725
1726 node->getLeft()->traverse(this);
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00001727 out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001728 node->getRight()->traverse(this);
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00001729 out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001730
1731 if (i < fields->size() - 1)
1732 {
1733 out << " && ";
1734 }
1735 }
1736
1737 out << ")";
1738
1739 return false;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001740 }
1741 else
1742 {
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001743 if (node->getLeft()->isMatrix())
1744 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001745 mUsesEqualMat[node->getLeft()->getCols()][node->getLeft()->getRows()] = true;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001746 }
1747 else if (node->getLeft()->isVector())
1748 {
1749 switch (node->getLeft()->getBasicType())
1750 {
1751 case EbtFloat:
alokp@chromium.org58e54292010-08-24 21:40:03 +00001752 switch (node->getLeft()->getNominalSize())
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001753 {
1754 case 2: mUsesEqualVec2 = true; break;
1755 case 3: mUsesEqualVec3 = true; break;
1756 case 4: mUsesEqualVec4 = true; break;
1757 default: UNREACHABLE();
1758 }
1759 break;
1760 case EbtInt:
alokp@chromium.org58e54292010-08-24 21:40:03 +00001761 switch (node->getLeft()->getNominalSize())
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001762 {
1763 case 2: mUsesEqualIVec2 = true; break;
1764 case 3: mUsesEqualIVec3 = true; break;
1765 case 4: mUsesEqualIVec4 = true; break;
1766 default: UNREACHABLE();
1767 }
1768 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001769 case EbtUInt:
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00001770 switch (node->getLeft()->getNominalSize())
1771 {
1772 case 2: mUsesEqualUVec2 = true; break;
1773 case 3: mUsesEqualUVec3 = true; break;
1774 case 4: mUsesEqualUVec4 = true; break;
1775 default: UNREACHABLE();
1776 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001777 break;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001778 case EbtBool:
alokp@chromium.org58e54292010-08-24 21:40:03 +00001779 switch (node->getLeft()->getNominalSize())
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001780 {
1781 case 2: mUsesEqualBVec2 = true; break;
1782 case 3: mUsesEqualBVec3 = true; break;
1783 case 4: mUsesEqualBVec4 = true; break;
1784 default: UNREACHABLE();
1785 }
1786 break;
1787 default: UNREACHABLE();
1788 }
1789 }
1790 else UNREACHABLE();
1791
1792 if (node->getOp() == EOpEqual)
1793 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001794 outputTriplet(visit, "equal(", ", ", ")");
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001795 }
1796 else
1797 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001798 outputTriplet(visit, "!equal(", ", ", ")");
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001799 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001800 }
1801 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001802 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
1803 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
1804 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
1805 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
1806 case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001807 case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001808 case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
1809 case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
daniel@transgaming.com69f084b2010-04-23 18:34:46 +00001810 case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001811 case EOpLogicalOr:
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00001812 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001813 return false;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001814 case EOpLogicalXor:
1815 mUsesXor = true;
1816 outputTriplet(visit, "xor(", ", ", ")");
1817 break;
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001818 case EOpLogicalAnd:
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00001819 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001820 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001821 default: UNREACHABLE();
1822 }
1823
1824 return true;
1825}
1826
1827bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
1828{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001829 switch (node->getOp())
1830 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001831 case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
1832 case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
1833 case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
1834 case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
1835 case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
1836 case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
1837 case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001838 case EOpConvIntToBool:
Nicolas Capensab60b932013-06-05 10:31:21 -04001839 case EOpConvUIntToBool:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001840 case EOpConvFloatToBool:
1841 switch (node->getOperand()->getType().getNominalSize())
1842 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001843 case 1: outputTriplet(visit, "bool(", "", ")"); break;
1844 case 2: outputTriplet(visit, "bool2(", "", ")"); break;
1845 case 3: outputTriplet(visit, "bool3(", "", ")"); break;
1846 case 4: outputTriplet(visit, "bool4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001847 default: UNREACHABLE();
1848 }
1849 break;
1850 case EOpConvBoolToFloat:
1851 case EOpConvIntToFloat:
Nicolas Capensab60b932013-06-05 10:31:21 -04001852 case EOpConvUIntToFloat:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001853 switch (node->getOperand()->getType().getNominalSize())
1854 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001855 case 1: outputTriplet(visit, "float(", "", ")"); break;
1856 case 2: outputTriplet(visit, "float2(", "", ")"); break;
1857 case 3: outputTriplet(visit, "float3(", "", ")"); break;
1858 case 4: outputTriplet(visit, "float4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001859 default: UNREACHABLE();
1860 }
1861 break;
1862 case EOpConvFloatToInt:
1863 case EOpConvBoolToInt:
Nicolas Capensab60b932013-06-05 10:31:21 -04001864 case EOpConvUIntToInt:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001865 switch (node->getOperand()->getType().getNominalSize())
1866 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001867 case 1: outputTriplet(visit, "int(", "", ")"); break;
1868 case 2: outputTriplet(visit, "int2(", "", ")"); break;
1869 case 3: outputTriplet(visit, "int3(", "", ")"); break;
1870 case 4: outputTriplet(visit, "int4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001871 default: UNREACHABLE();
1872 }
1873 break;
Nicolas Capensab60b932013-06-05 10:31:21 -04001874 case EOpConvFloatToUInt:
1875 case EOpConvBoolToUInt:
1876 case EOpConvIntToUInt:
Jamie Madilla16f1672013-07-03 15:15:17 -04001877 switch (node->getOperand()->getType().getNominalSize())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001878 {
1879 case 1: outputTriplet(visit, "uint(", "", ")"); break;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00001880 case 2: outputTriplet(visit, "uint2(", "", ")"); break;
1881 case 3: outputTriplet(visit, "uint3(", "", ")"); break;
1882 case 4: outputTriplet(visit, "uint4(", "", ")"); break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001883 default: UNREACHABLE();
1884 }
1885 break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001886 case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break;
1887 case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break;
1888 case EOpSin: outputTriplet(visit, "sin(", "", ")"); break;
1889 case EOpCos: outputTriplet(visit, "cos(", "", ")"); break;
1890 case EOpTan: outputTriplet(visit, "tan(", "", ")"); break;
1891 case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
1892 case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
1893 case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
1894 case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
1895 case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
1896 case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
1897 case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break;
1898 case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break;
1899 case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break;
1900 case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break;
1901 case EOpSign: outputTriplet(visit, "sign(", "", ")"); break;
1902 case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break;
1903 case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
1904 case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
1905 case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
1906 case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
daniel@transgaming.comddbb45d2012-05-31 01:21:41 +00001907 case EOpDFdx:
1908 if(mInsideDiscontinuousLoop || mOutputLod0Function)
1909 {
1910 outputTriplet(visit, "(", "", ", 0.0)");
1911 }
1912 else
1913 {
1914 outputTriplet(visit, "ddx(", "", ")");
1915 }
1916 break;
1917 case EOpDFdy:
1918 if(mInsideDiscontinuousLoop || mOutputLod0Function)
1919 {
1920 outputTriplet(visit, "(", "", ", 0.0)");
1921 }
1922 else
1923 {
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001924 outputTriplet(visit, "ddy(", "", ")");
daniel@transgaming.comddbb45d2012-05-31 01:21:41 +00001925 }
1926 break;
1927 case EOpFwidth:
1928 if(mInsideDiscontinuousLoop || mOutputLod0Function)
1929 {
1930 outputTriplet(visit, "(", "", ", 0.0)");
1931 }
1932 else
1933 {
1934 outputTriplet(visit, "fwidth(", "", ")");
1935 }
1936 break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001937 case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
1938 case EOpAll: outputTriplet(visit, "all(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001939 default: UNREACHABLE();
1940 }
1941
1942 return true;
1943}
1944
1945bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
1946{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001947 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001948
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001949 switch (node->getOp())
1950 {
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001951 case EOpSequence:
1952 {
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001953 if (mInsideFunction)
1954 {
Jamie Madill075edd82013-07-08 13:30:19 -04001955 outputLineDirective(node->getLine().first_line);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001956 out << "{\n";
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00001957
1958 mScopeDepth++;
1959
1960 if (mScopeBracket.size() < mScopeDepth)
1961 {
1962 mScopeBracket.push_back(0); // New scope level
1963 }
1964 else
1965 {
1966 mScopeBracket[mScopeDepth - 1]++; // New scope at existing level
1967 }
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001968 }
1969
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001970 for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
1971 {
Jamie Madill075edd82013-07-08 13:30:19 -04001972 outputLineDirective((*sit)->getLine().first_line);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001973
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00001974 traverseStatements(*sit);
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001975
1976 out << ";\n";
1977 }
1978
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001979 if (mInsideFunction)
1980 {
Jamie Madill075edd82013-07-08 13:30:19 -04001981 outputLineDirective(node->getLine().last_line);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001982 out << "}\n";
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00001983
1984 mScopeDepth--;
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001985 }
1986
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001987 return false;
1988 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001989 case EOpDeclaration:
1990 if (visit == PreVisit)
1991 {
1992 TIntermSequence &sequence = node->getSequence();
1993 TIntermTyped *variable = sequence[0]->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001994
daniel@transgaming.comd25ab252010-03-30 03:36:26 +00001995 if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001996 {
daniel@transgaming.comead23042010-04-29 03:35:36 +00001997 if (variable->getType().getStruct())
1998 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00001999 addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
daniel@transgaming.comead23042010-04-29 03:35:36 +00002000 }
2001
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002002 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002003 {
daniel@transgaming.comd2cf25d2010-04-22 16:27:35 +00002004 if (!mInsideFunction)
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00002005 {
2006 out << "static ";
2007 }
2008
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002009 out << typeString(variable->getType()) + " ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002010
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002011 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002012 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002013 TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002014
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002015 if (symbol)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002016 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002017 symbol->traverse(this);
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002018 out << arrayString(symbol->getType());
daniel@transgaming.com7127f202010-04-15 20:45:22 +00002019 out << " = " + initializer(variable->getType());
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002020 }
2021 else
2022 {
2023 (*sit)->traverse(this);
2024 }
2025
shannon.woods@transgaming.comcb332ab2013-02-28 23:12:18 +00002026 if (*sit != sequence.back())
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002027 {
shannon.woods@transgaming.comcb332ab2013-02-28 23:12:18 +00002028 out << ", ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002029 }
2030 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002031 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002032 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
2033 {
daniel@transgaming.comead23042010-04-29 03:35:36 +00002034 // Already added to constructor map
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002035 }
2036 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002037 }
shannon.woods%transgaming.com@gtempaccount.com6f273e32013-04-13 03:41:15 +00002038 else if (variable && isVaryingOut(variable->getQualifier()))
shannon.woods@transgaming.comcb332ab2013-02-28 23:12:18 +00002039 {
2040 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
2041 {
2042 TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
2043
2044 if (symbol)
2045 {
2046 // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
2047 mReferencedVaryings[symbol->getSymbol()] = symbol;
2048 }
2049 else
2050 {
2051 (*sit)->traverse(this);
2052 }
2053 }
2054 }
2055
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002056 return false;
2057 }
2058 else if (visit == InVisit)
2059 {
2060 out << ", ";
2061 }
2062 break;
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002063 case EOpPrototype:
2064 if (visit == PreVisit)
2065 {
daniel@transgaming.com0e5bb402012-10-17 18:24:53 +00002066 out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002067
2068 TIntermSequence &arguments = node->getSequence();
2069
2070 for (unsigned int i = 0; i < arguments.size(); i++)
2071 {
2072 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
2073
2074 if (symbol)
2075 {
2076 out << argumentString(symbol);
2077
2078 if (i < arguments.size() - 1)
2079 {
2080 out << ", ";
2081 }
2082 }
2083 else UNREACHABLE();
2084 }
2085
2086 out << ");\n";
2087
daniel@transgaming.com0e5bb402012-10-17 18:24:53 +00002088 // Also prototype the Lod0 variant if needed
2089 if (mContainsLoopDiscontinuity && !mOutputLod0Function)
2090 {
2091 mOutputLod0Function = true;
2092 node->traverse(this);
2093 mOutputLod0Function = false;
2094 }
2095
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002096 return false;
2097 }
2098 break;
daniel@transgaming.comed2180d2012-03-26 17:08:54 +00002099 case EOpComma: outputTriplet(visit, "(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002100 case EOpFunction:
2101 {
alokp@chromium.org43884872010-03-30 00:08:52 +00002102 TString name = TFunction::unmangleName(node->getName());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002103
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002104 out << typeString(node->getType()) << " ";
2105
2106 if (name == "main")
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002107 {
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002108 out << "gl_main(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002109 }
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002110 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002111 {
daniel@transgaming.com89431aa2012-05-31 01:20:29 +00002112 out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002113 }
daniel@transgaming.com63691862010-04-29 03:32:42 +00002114
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002115 TIntermSequence &sequence = node->getSequence();
2116 TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
2117
2118 for (unsigned int i = 0; i < arguments.size(); i++)
2119 {
2120 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
2121
2122 if (symbol)
2123 {
2124 if (symbol->getType().getStruct())
2125 {
2126 addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
2127 }
2128
2129 out << argumentString(symbol);
2130
2131 if (i < arguments.size() - 1)
2132 {
2133 out << ", ";
2134 }
2135 }
2136 else UNREACHABLE();
2137 }
2138
2139 out << ")\n"
2140 "{\n";
2141
2142 if (sequence.size() > 1)
2143 {
2144 mInsideFunction = true;
2145 sequence[1]->traverse(this);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00002146 mInsideFunction = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002147 }
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002148
2149 out << "}\n";
2150
daniel@transgaming.com89431aa2012-05-31 01:20:29 +00002151 if (mContainsLoopDiscontinuity && !mOutputLod0Function)
2152 {
daniel@transgaming.comecdf44a2012-06-01 01:45:15 +00002153 if (name != "main")
daniel@transgaming.com89431aa2012-05-31 01:20:29 +00002154 {
2155 mOutputLod0Function = true;
2156 node->traverse(this);
2157 mOutputLod0Function = false;
2158 }
2159 }
2160
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002161 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002162 }
2163 break;
2164 case EOpFunctionCall:
2165 {
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002166 TString name = TFunction::unmangleName(node->getName());
2167 bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
shannonwoods@chromium.orgc6ac65f2013-05-30 00:02:50 +00002168 TIntermSequence &arguments = node->getSequence();
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002169
2170 if (node->isUserDefined())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002171 {
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002172 out << decorate(name) << (lod0 ? "Lod0(" : "(");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002173 }
2174 else
2175 {
shannonwoods@chromium.orgc6ac65f2013-05-30 00:02:50 +00002176 TBasicType samplerType = arguments[0]->getAsTyped()->getType().getBasicType();
2177
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002178 TextureFunction textureFunction;
2179 textureFunction.sampler = samplerType;
2180 textureFunction.coords = arguments[1]->getAsTyped()->getNominalSize();
2181 textureFunction.mipmap = TextureFunction::IMPLICIT;
2182
2183 if (name == "texture2D" || name == "textureCube" || name == "texture")
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002184 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002185 textureFunction.mipmap = TextureFunction::IMPLICIT;
2186 textureFunction.proj = false;
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002187 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002188 else if (name == "texture2DProj" || name == "textureProj")
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002189 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002190 textureFunction.mipmap = TextureFunction::IMPLICIT;
2191 textureFunction.proj = true;
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002192 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002193 else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod")
Nicolas Capens9fe6f982013-06-24 16:05:25 -04002194 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002195 textureFunction.mipmap = TextureFunction::LOD;
2196 textureFunction.proj = false;
Nicolas Capens9fe6f982013-06-24 16:05:25 -04002197 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002198 else if (name == "texture2DProjLod" || name == "textureProjLod")
Nicolas Capens9fe6f982013-06-24 16:05:25 -04002199 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002200 textureFunction.mipmap = TextureFunction::LOD;
2201 textureFunction.proj = true;
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002202 }
2203 else UNREACHABLE();
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002204
2205 if (textureFunction.mipmap != TextureFunction::LOD)
2206 {
2207 if (lod0 || mContext.shaderType == SH_VERTEX_SHADER)
2208 {
2209 textureFunction.mipmap = TextureFunction::LOD0;
2210 }
2211 else if (arguments.size() == 3)
2212 {
2213 textureFunction.mipmap = TextureFunction::BIAS;
2214 }
2215 }
2216
2217 mUsesTexture.insert(textureFunction);
2218
2219 out << textureFunction.name();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002220 }
shannonwoods@chromium.orgc6ac65f2013-05-30 00:02:50 +00002221
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002222 for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++)
2223 {
2224 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
2225 {
2226 out << "texture_";
2227 (*arg)->traverse(this);
2228 out << ", sampler_";
2229 }
2230
2231 (*arg)->traverse(this);
2232
2233 if (arg < arguments.end() - 1)
2234 {
2235 out << ", ";
2236 }
2237 }
2238
2239 out << ")";
2240
2241 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002242 }
2243 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002244 case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002245 case EOpConstructFloat:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002246 addConstructor(node->getType(), "vec1", &node->getSequence());
2247 outputTriplet(visit, "vec1(", "", ")");
2248 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002249 case EOpConstructVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002250 addConstructor(node->getType(), "vec2", &node->getSequence());
2251 outputTriplet(visit, "vec2(", ", ", ")");
2252 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002253 case EOpConstructVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002254 addConstructor(node->getType(), "vec3", &node->getSequence());
2255 outputTriplet(visit, "vec3(", ", ", ")");
2256 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002257 case EOpConstructVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002258 addConstructor(node->getType(), "vec4", &node->getSequence());
2259 outputTriplet(visit, "vec4(", ", ", ")");
2260 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002261 case EOpConstructBool:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002262 addConstructor(node->getType(), "bvec1", &node->getSequence());
2263 outputTriplet(visit, "bvec1(", "", ")");
2264 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002265 case EOpConstructBVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002266 addConstructor(node->getType(), "bvec2", &node->getSequence());
2267 outputTriplet(visit, "bvec2(", ", ", ")");
2268 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002269 case EOpConstructBVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002270 addConstructor(node->getType(), "bvec3", &node->getSequence());
2271 outputTriplet(visit, "bvec3(", ", ", ")");
2272 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002273 case EOpConstructBVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002274 addConstructor(node->getType(), "bvec4", &node->getSequence());
2275 outputTriplet(visit, "bvec4(", ", ", ")");
2276 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002277 case EOpConstructInt:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002278 addConstructor(node->getType(), "ivec1", &node->getSequence());
2279 outputTriplet(visit, "ivec1(", "", ")");
2280 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002281 case EOpConstructIVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002282 addConstructor(node->getType(), "ivec2", &node->getSequence());
2283 outputTriplet(visit, "ivec2(", ", ", ")");
2284 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002285 case EOpConstructIVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002286 addConstructor(node->getType(), "ivec3", &node->getSequence());
2287 outputTriplet(visit, "ivec3(", ", ", ")");
2288 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002289 case EOpConstructIVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002290 addConstructor(node->getType(), "ivec4", &node->getSequence());
2291 outputTriplet(visit, "ivec4(", ", ", ")");
2292 break;
Nicolas Capensab60b932013-06-05 10:31:21 -04002293 case EOpConstructUInt:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002294 addConstructor(node->getType(), "uvec1", &node->getSequence());
2295 outputTriplet(visit, "uvec1(", "", ")");
2296 break;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00002297 case EOpConstructUVec2:
2298 addConstructor(node->getType(), "uvec2", &node->getSequence());
2299 outputTriplet(visit, "uvec2(", ", ", ")");
2300 break;
2301 case EOpConstructUVec3:
2302 addConstructor(node->getType(), "uvec3", &node->getSequence());
2303 outputTriplet(visit, "uvec3(", ", ", ")");
2304 break;
2305 case EOpConstructUVec4:
2306 addConstructor(node->getType(), "uvec4", &node->getSequence());
2307 outputTriplet(visit, "uvec4(", ", ", ")");
2308 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002309 case EOpConstructMat2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002310 addConstructor(node->getType(), "mat2", &node->getSequence());
2311 outputTriplet(visit, "mat2(", ", ", ")");
2312 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002313 case EOpConstructMat3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002314 addConstructor(node->getType(), "mat3", &node->getSequence());
2315 outputTriplet(visit, "mat3(", ", ", ")");
2316 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002317 case EOpConstructMat4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002318 addConstructor(node->getType(), "mat4", &node->getSequence());
2319 outputTriplet(visit, "mat4(", ", ", ")");
2320 break;
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002321 case EOpConstructStruct:
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002322 addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
2323 outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002324 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002325 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
2326 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
2327 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
2328 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
2329 case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
2330 case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00002331 case EOpMod:
2332 {
daniel@transgaming.com4229f592011-11-24 22:34:04 +00002333 // We need to look at the number of components in both arguments
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002334 const int modValue = node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
2335 + node->getSequence()[1]->getAsTyped()->getNominalSize();
2336 switch (modValue)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00002337 {
daniel@transgaming.com4229f592011-11-24 22:34:04 +00002338 case 11: mUsesMod1 = true; break;
2339 case 22: mUsesMod2v = true; break;
2340 case 21: mUsesMod2f = true; break;
2341 case 33: mUsesMod3v = true; break;
2342 case 31: mUsesMod3f = true; break;
2343 case 44: mUsesMod4v = true; break;
2344 case 41: mUsesMod4f = true; break;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00002345 default: UNREACHABLE();
2346 }
2347
2348 outputTriplet(visit, "mod(", ", ", ")");
2349 }
2350 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002351 case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002352 case EOpAtan:
daniel@transgaming.com0f189612010-05-07 13:03:36 +00002353 ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator
daniel@transgaming.com35342dc2012-02-28 02:01:22 +00002354 switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
2355 {
2356 case 1: mUsesAtan2_1 = true; break;
2357 case 2: mUsesAtan2_2 = true; break;
2358 case 3: mUsesAtan2_3 = true; break;
2359 case 4: mUsesAtan2_4 = true; break;
2360 default: UNREACHABLE();
2361 }
daniel@transgaming.com0f189612010-05-07 13:03:36 +00002362 outputTriplet(visit, "atanyx(", ", ", ")");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002363 break;
2364 case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
2365 case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
2366 case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break;
2367 case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break;
2368 case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break;
2369 case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break;
2370 case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break;
2371 case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
2372 case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00002373 case EOpFaceForward:
2374 {
alokp@chromium.org58e54292010-08-24 21:40:03 +00002375 switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00002376 {
2377 case 1: mUsesFaceforward1 = true; break;
2378 case 2: mUsesFaceforward2 = true; break;
2379 case 3: mUsesFaceforward3 = true; break;
2380 case 4: mUsesFaceforward4 = true; break;
2381 default: UNREACHABLE();
2382 }
2383
2384 outputTriplet(visit, "faceforward(", ", ", ")");
2385 }
2386 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002387 case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
2388 case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
2389 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002390 default: UNREACHABLE();
2391 }
2392
2393 return true;
2394}
2395
2396bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
2397{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002398 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002399
alokp@chromium.org60fe4072010-03-29 20:58:29 +00002400 if (node->usesTernaryOperator())
2401 {
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00002402 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
alokp@chromium.org60fe4072010-03-29 20:58:29 +00002403 }
2404 else // if/else statement
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002405 {
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00002406 mUnfoldShortCircuit->traverse(node->getCondition());
daniel@transgaming.comb5875982010-04-15 20:44:53 +00002407
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002408 out << "if(";
2409
2410 node->getCondition()->traverse(this);
2411
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002412 out << ")\n";
2413
Jamie Madill075edd82013-07-08 13:30:19 -04002414 outputLineDirective(node->getLine().first_line);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002415 out << "{\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002416
daniel@transgaming.combb885322010-04-15 20:45:24 +00002417 if (node->getTrueBlock())
2418 {
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002419 traverseStatements(node->getTrueBlock());
daniel@transgaming.combb885322010-04-15 20:45:24 +00002420 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002421
Jamie Madill075edd82013-07-08 13:30:19 -04002422 outputLineDirective(node->getLine().first_line);
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002423 out << ";\n}\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002424
2425 if (node->getFalseBlock())
2426 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002427 out << "else\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002428
Jamie Madill075edd82013-07-08 13:30:19 -04002429 outputLineDirective(node->getFalseBlock()->getLine().first_line);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002430 out << "{\n";
2431
Jamie Madill075edd82013-07-08 13:30:19 -04002432 outputLineDirective(node->getFalseBlock()->getLine().first_line);
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002433 traverseStatements(node->getFalseBlock());
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002434
Jamie Madill075edd82013-07-08 13:30:19 -04002435 outputLineDirective(node->getFalseBlock()->getLine().first_line);
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002436 out << ";\n}\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002437 }
2438 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002439
2440 return false;
2441}
2442
2443void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
2444{
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00002445 writeConstantUnion(node->getType(), node->getUnionArrayPointer());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002446}
2447
2448bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
2449{
daniel@transgaming.come11100c2012-05-31 01:20:32 +00002450 bool wasDiscontinuous = mInsideDiscontinuousLoop;
2451
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +00002452 if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop)
daniel@transgaming.come11100c2012-05-31 01:20:32 +00002453 {
2454 mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
2455 }
2456
shannon.woods@transgaming.com9cbce922013-02-28 23:14:24 +00002457 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002458 {
shannon.woods@transgaming.com9cbce922013-02-28 23:14:24 +00002459 if (handleExcessiveLoop(node))
2460 {
2461 return false;
2462 }
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002463 }
2464
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002465 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002466
alokp@chromium.org52813552010-11-16 18:36:09 +00002467 if (node->getType() == ELoopDoWhile)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002468 {
daniel@transgaming.com2a073de2012-03-09 21:56:43 +00002469 out << "{do\n";
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002470
Jamie Madill075edd82013-07-08 13:30:19 -04002471 outputLineDirective(node->getLine().first_line);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002472 out << "{\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002473 }
2474 else
2475 {
daniel@transgaming.com2a073de2012-03-09 21:56:43 +00002476 out << "{for(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002477
2478 if (node->getInit())
2479 {
2480 node->getInit()->traverse(this);
2481 }
2482
2483 out << "; ";
2484
alokp@chromium.org52813552010-11-16 18:36:09 +00002485 if (node->getCondition())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002486 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002487 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002488 }
2489
2490 out << "; ";
2491
alokp@chromium.org52813552010-11-16 18:36:09 +00002492 if (node->getExpression())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002493 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002494 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002495 }
2496
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002497 out << ")\n";
2498
Jamie Madill075edd82013-07-08 13:30:19 -04002499 outputLineDirective(node->getLine().first_line);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002500 out << "{\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002501 }
2502
2503 if (node->getBody())
2504 {
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002505 traverseStatements(node->getBody());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002506 }
2507
Jamie Madill075edd82013-07-08 13:30:19 -04002508 outputLineDirective(node->getLine().first_line);
daniel@transgaming.com7fb81e82011-09-23 18:20:46 +00002509 out << ";}\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002510
alokp@chromium.org52813552010-11-16 18:36:09 +00002511 if (node->getType() == ELoopDoWhile)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002512 {
Jamie Madill075edd82013-07-08 13:30:19 -04002513 outputLineDirective(node->getCondition()->getLine().first_line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002514 out << "while(\n";
2515
alokp@chromium.org52813552010-11-16 18:36:09 +00002516 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002517
daniel@transgaming.com73536982012-03-21 20:45:49 +00002518 out << ");";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002519 }
2520
daniel@transgaming.com73536982012-03-21 20:45:49 +00002521 out << "}\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002522
daniel@transgaming.come11100c2012-05-31 01:20:32 +00002523 mInsideDiscontinuousLoop = wasDiscontinuous;
2524
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002525 return false;
2526}
2527
2528bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
2529{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002530 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002531
2532 switch (node->getFlowOp())
2533 {
apatrick@chromium.org05a5d8e2011-02-16 19:07:20 +00002534 case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break;
daniel@transgaming.com8c77f852012-07-11 20:37:35 +00002535 case EOpBreak:
2536 if (visit == PreVisit)
2537 {
2538 if (mExcessiveLoopIndex)
2539 {
2540 out << "{Break";
2541 mExcessiveLoopIndex->traverse(this);
2542 out << " = true; break;}\n";
2543 }
2544 else
2545 {
2546 out << "break;\n";
2547 }
2548 }
2549 break;
apatrick@chromium.org05a5d8e2011-02-16 19:07:20 +00002550 case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002551 case EOpReturn:
2552 if (visit == PreVisit)
2553 {
2554 if (node->getExpression())
2555 {
2556 out << "return ";
2557 }
2558 else
2559 {
2560 out << "return;\n";
2561 }
2562 }
2563 else if (visit == PostVisit)
2564 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002565 if (node->getExpression())
2566 {
2567 out << ";\n";
2568 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002569 }
2570 break;
2571 default: UNREACHABLE();
2572 }
2573
2574 return true;
2575}
2576
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002577void OutputHLSL::traverseStatements(TIntermNode *node)
2578{
2579 if (isSingleStatement(node))
2580 {
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00002581 mUnfoldShortCircuit->traverse(node);
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002582 }
2583
2584 node->traverse(this);
2585}
2586
daniel@transgaming.comb5875982010-04-15 20:44:53 +00002587bool OutputHLSL::isSingleStatement(TIntermNode *node)
2588{
2589 TIntermAggregate *aggregate = node->getAsAggregate();
2590
2591 if (aggregate)
2592 {
2593 if (aggregate->getOp() == EOpSequence)
2594 {
2595 return false;
2596 }
2597 else
2598 {
2599 for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
2600 {
2601 if (!isSingleStatement(*sit))
2602 {
2603 return false;
2604 }
2605 }
2606
2607 return true;
2608 }
2609 }
2610
2611 return true;
2612}
2613
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002614// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
2615// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002616bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
2617{
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002618 const int MAX_LOOP_ITERATIONS = 254;
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002619 TInfoSinkBase &out = mBody;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002620
2621 // Parse loops of the form:
2622 // for(int index = initial; index [comparator] limit; index += increment)
2623 TIntermSymbol *index = NULL;
2624 TOperator comparator = EOpNull;
2625 int initial = 0;
2626 int limit = 0;
2627 int increment = 0;
2628
2629 // Parse index name and intial value
2630 if (node->getInit())
2631 {
2632 TIntermAggregate *init = node->getInit()->getAsAggregate();
2633
2634 if (init)
2635 {
2636 TIntermSequence &sequence = init->getSequence();
2637 TIntermTyped *variable = sequence[0]->getAsTyped();
2638
2639 if (variable && variable->getQualifier() == EvqTemporary)
2640 {
2641 TIntermBinary *assign = variable->getAsBinaryNode();
2642
2643 if (assign->getOp() == EOpInitialize)
2644 {
2645 TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
2646 TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
2647
2648 if (symbol && constant)
2649 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002650 if (constant->getBasicType() == EbtInt && constant->isScalar())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002651 {
2652 index = symbol;
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002653 initial = constant->getIConst(0);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002654 }
2655 }
2656 }
2657 }
2658 }
2659 }
2660
2661 // Parse comparator and limit value
alokp@chromium.org52813552010-11-16 18:36:09 +00002662 if (index != NULL && node->getCondition())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002663 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002664 TIntermBinary *test = node->getCondition()->getAsBinaryNode();
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002665
2666 if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
2667 {
2668 TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
2669
2670 if (constant)
2671 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002672 if (constant->getBasicType() == EbtInt && constant->isScalar())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002673 {
2674 comparator = test->getOp();
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002675 limit = constant->getIConst(0);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002676 }
2677 }
2678 }
2679 }
2680
2681 // Parse increment
alokp@chromium.org52813552010-11-16 18:36:09 +00002682 if (index != NULL && comparator != EOpNull && node->getExpression())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002683 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002684 TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
2685 TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002686
2687 if (binaryTerminal)
2688 {
2689 TOperator op = binaryTerminal->getOp();
2690 TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
2691
2692 if (constant)
2693 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002694 if (constant->getBasicType() == EbtInt && constant->isScalar())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002695 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002696 int value = constant->getIConst(0);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002697
2698 switch (op)
2699 {
2700 case EOpAddAssign: increment = value; break;
2701 case EOpSubAssign: increment = -value; break;
2702 default: UNIMPLEMENTED();
2703 }
2704 }
2705 }
2706 }
2707 else if (unaryTerminal)
2708 {
2709 TOperator op = unaryTerminal->getOp();
2710
2711 switch (op)
2712 {
2713 case EOpPostIncrement: increment = 1; break;
2714 case EOpPostDecrement: increment = -1; break;
2715 case EOpPreIncrement: increment = 1; break;
2716 case EOpPreDecrement: increment = -1; break;
2717 default: UNIMPLEMENTED();
2718 }
2719 }
2720 }
2721
2722 if (index != NULL && comparator != EOpNull && increment != 0)
2723 {
2724 if (comparator == EOpLessThanEqual)
2725 {
2726 comparator = EOpLessThan;
2727 limit += 1;
2728 }
2729
2730 if (comparator == EOpLessThan)
2731 {
daniel@transgaming.comf1f538e2011-02-09 16:30:01 +00002732 int iterations = (limit - initial) / increment;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002733
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002734 if (iterations <= MAX_LOOP_ITERATIONS)
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002735 {
2736 return false; // Not an excessive loop
2737 }
2738
daniel@transgaming.come9b3f602012-07-11 20:37:31 +00002739 TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
2740 mExcessiveLoopIndex = index;
2741
daniel@transgaming.com0933b0c2012-07-11 20:37:28 +00002742 out << "{int ";
2743 index->traverse(this);
daniel@transgaming.com8c77f852012-07-11 20:37:35 +00002744 out << ";\n"
2745 "bool Break";
2746 index->traverse(this);
2747 out << " = false;\n";
daniel@transgaming.comc264de42012-07-11 20:37:25 +00002748
daniel@transgaming.com5b60f5e2012-07-11 20:37:38 +00002749 bool firstLoopFragment = true;
2750
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002751 while (iterations > 0)
2752 {
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002753 int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002754
daniel@transgaming.com5b60f5e2012-07-11 20:37:38 +00002755 if (!firstLoopFragment)
2756 {
2757 out << "if(!Break";
2758 index->traverse(this);
2759 out << ") {\n";
2760 }
daniel@transgaming.com2fe20a82012-07-11 20:37:41 +00002761
2762 if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment
2763 {
2764 mExcessiveLoopIndex = NULL; // Stops setting the Break flag
2765 }
daniel@transgaming.com8c77f852012-07-11 20:37:35 +00002766
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002767 // for(int index = initial; index < clampedLimit; index += increment)
2768
daniel@transgaming.com0933b0c2012-07-11 20:37:28 +00002769 out << "for(";
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002770 index->traverse(this);
2771 out << " = ";
2772 out << initial;
2773
2774 out << "; ";
2775 index->traverse(this);
2776 out << " < ";
2777 out << clampedLimit;
2778
2779 out << "; ";
2780 index->traverse(this);
2781 out << " += ";
2782 out << increment;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002783 out << ")\n";
2784
Jamie Madill075edd82013-07-08 13:30:19 -04002785 outputLineDirective(node->getLine().first_line);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002786 out << "{\n";
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002787
2788 if (node->getBody())
2789 {
2790 node->getBody()->traverse(this);
2791 }
2792
Jamie Madill075edd82013-07-08 13:30:19 -04002793 outputLineDirective(node->getLine().first_line);
daniel@transgaming.com5b60f5e2012-07-11 20:37:38 +00002794 out << ";}\n";
2795
2796 if (!firstLoopFragment)
2797 {
2798 out << "}\n";
2799 }
2800
2801 firstLoopFragment = false;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002802
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002803 initial += MAX_LOOP_ITERATIONS * increment;
2804 iterations -= MAX_LOOP_ITERATIONS;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002805 }
daniel@transgaming.comc264de42012-07-11 20:37:25 +00002806
2807 out << "}";
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002808
daniel@transgaming.come9b3f602012-07-11 20:37:31 +00002809 mExcessiveLoopIndex = restoreIndex;
2810
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002811 return true;
2812 }
2813 else UNIMPLEMENTED();
2814 }
2815
2816 return false; // Not handled as an excessive loop
2817}
2818
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002819void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002820{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002821 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002822
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002823 if (visit == PreVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002824 {
2825 out << preString;
2826 }
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002827 else if (visit == InVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002828 {
2829 out << inString;
2830 }
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002831 else if (visit == PostVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002832 {
2833 out << postString;
2834 }
2835}
2836
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002837void OutputHLSL::outputLineDirective(int line)
2838{
2839 if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
2840 {
baustin@google.com8ab69842011-06-02 21:53:45 +00002841 mBody << "\n";
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002842 mBody << "#line " << line;
2843
2844 if (mContext.sourcePath)
2845 {
2846 mBody << " \"" << mContext.sourcePath << "\"";
2847 }
2848
2849 mBody << "\n";
2850 }
2851}
2852
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002853TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
2854{
2855 TQualifier qualifier = symbol->getQualifier();
2856 const TType &type = symbol->getType();
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002857 TString name = symbol->getSymbol();
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002858
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002859 if (name.empty()) // HLSL demands named arguments, also for prototypes
2860 {
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00002861 name = "x" + str(mUniqueIndex++);
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002862 }
2863 else
2864 {
2865 name = decorate(name);
2866 }
2867
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002868 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
2869 {
2870 return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
2871 qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type);
2872 }
2873
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002874 return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002875}
2876
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +00002877TString OutputHLSL::interpolationString(TQualifier qualifier)
2878{
2879 switch(qualifier)
2880 {
2881 case EvqVaryingIn: return "";
2882 case EvqInvariantVaryingIn: return "";
2883 case EvqSmoothIn: return "linear";
2884 case EvqFlatIn: return "nointerpolation";
2885 case EvqCentroidIn: return "centroid";
2886 case EvqVaryingOut: return "";
2887 case EvqInvariantVaryingOut: return "";
2888 case EvqSmoothOut: return "linear";
2889 case EvqFlatOut: return "nointerpolation";
2890 case EvqCentroidOut: return "centroid";
2891 default: UNREACHABLE();
2892 }
2893
2894 return "";
2895}
2896
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002897TString OutputHLSL::qualifierString(TQualifier qualifier)
2898{
2899 switch(qualifier)
2900 {
2901 case EvqIn: return "in";
2902 case EvqOut: return "out";
2903 case EvqInOut: return "inout";
2904 case EvqConstReadOnly: return "const";
2905 default: UNREACHABLE();
2906 }
2907
2908 return "";
2909}
2910
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002911TString OutputHLSL::typeString(const TType &type)
2912{
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002913 if (type.getBasicType() == EbtStruct)
2914 {
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002915 if (type.getTypeName() != "")
2916 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002917 return structLookup(type.getTypeName());
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002918 }
daniel@transgaming.com6b998402010-05-04 03:35:07 +00002919 else // Nameless structure, define in place
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002920 {
Jamie Madillc835df62013-06-21 09:15:32 -04002921 return structureString(type, false, false);
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002922 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002923 }
2924 else if (type.isMatrix())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002925 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00002926 int cols = type.getCols();
2927 int rows = type.getRows();
2928 return "float" + str(cols) + "x" + str(rows);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002929 }
2930 else
2931 {
2932 switch (type.getBasicType())
2933 {
2934 case EbtFloat:
2935 switch (type.getNominalSize())
2936 {
2937 case 1: return "float";
2938 case 2: return "float2";
2939 case 3: return "float3";
2940 case 4: return "float4";
2941 }
2942 case EbtInt:
2943 switch (type.getNominalSize())
2944 {
2945 case 1: return "int";
2946 case 2: return "int2";
2947 case 3: return "int3";
2948 case 4: return "int4";
2949 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002950 case EbtUInt:
Jamie Madill22d63da2013-06-07 12:45:12 -04002951 switch (type.getNominalSize())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002952 {
2953 case 1: return "uint";
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00002954 case 2: return "uint2";
2955 case 3: return "uint3";
2956 case 4: return "uint4";
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002957 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002958 case EbtBool:
2959 switch (type.getNominalSize())
2960 {
2961 case 1: return "bool";
2962 case 2: return "bool2";
2963 case 3: return "bool3";
2964 case 4: return "bool4";
2965 }
2966 case EbtVoid:
2967 return "void";
2968 case EbtSampler2D:
Nicolas Capens1f1a8332013-06-24 15:42:27 -04002969 case EbtISampler2D:
Nicolas Capens075368e2013-06-24 15:58:30 -04002970 case EbtUSampler2D:
Nicolas Capensfb50dff2013-06-24 16:16:23 -04002971 case EbtSampler2DArray:
2972 case EbtISampler2DArray:
2973 case EbtUSampler2DArray:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002974 return "sampler2D";
2975 case EbtSamplerCube:
Nicolas Capens1f1a8332013-06-24 15:42:27 -04002976 case EbtISamplerCube:
Nicolas Capens075368e2013-06-24 15:58:30 -04002977 case EbtUSamplerCube:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002978 return "samplerCUBE";
apatrick@chromium.org65756022012-01-17 21:45:38 +00002979 case EbtSamplerExternalOES:
2980 return "sampler2D";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002981 default:
2982 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002983 }
2984 }
2985
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00002986 UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002987 return "<unknown type>";
2988}
2989
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00002990TString OutputHLSL::textureString(const TType &type)
2991{
2992 switch (type.getBasicType())
2993 {
Nicolas Capensfb50dff2013-06-24 16:16:23 -04002994 case EbtSampler2D: return "Texture2D";
2995 case EbtSamplerCube: return "TextureCube";
2996 case EbtSamplerExternalOES: return "Texture2D";
2997 case EbtSampler2DArray: return "Texture2DArray";
Jamie Madill94c3f422013-07-03 15:16:13 -04002998 case EbtSampler3D: return "Texture3D";
Nicolas Capensfb50dff2013-06-24 16:16:23 -04002999 case EbtISampler2D: return "Texture2D<int4>";
3000 case EbtISamplerCube: return "TextureCube<int4>";
3001 case EbtISampler2DArray: return "Texture2DArray<int4>";
3002 case EbtUSampler2D: return "Texture2D<uint4>";
3003 case EbtUSamplerCube: return "TextureCube<uint4>";
3004 case EbtUSampler2DArray: return "Texture2DArray<uint4>";
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00003005 default:
3006 break;
3007 }
3008
3009 UNREACHABLE();
3010 return "<unknown texture type>";
3011}
3012
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003013TString OutputHLSL::arrayString(const TType &type)
3014{
3015 if (!type.isArray())
3016 {
3017 return "";
3018 }
3019
daniel@transgaming.com005c7392010-04-15 20:45:27 +00003020 return "[" + str(type.getArraySize()) + "]";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003021}
3022
3023TString OutputHLSL::initializer(const TType &type)
3024{
3025 TString string;
3026
Jamie Madill94bf7f22013-07-08 13:31:15 -04003027 size_t size = type.getObjectSize();
3028 for (size_t component = 0; component < size; component++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003029 {
daniel@transgaming.comead23042010-04-29 03:35:36 +00003030 string += "0";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003031
Jamie Madill94bf7f22013-07-08 13:31:15 -04003032 if (component + 1 < size)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003033 {
3034 string += ", ";
3035 }
3036 }
3037
daniel@transgaming.comead23042010-04-29 03:35:36 +00003038 return "{" + string + "}";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003039}
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003040
Jamie Madillc835df62013-06-21 09:15:32 -04003041TString OutputHLSL::structureString(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing)
Jamie Madill9cf6c072013-06-20 11:55:53 -04003042{
3043 ASSERT(structType.getStruct());
3044
3045 const TTypeList &fields = *structType.getStruct();
3046 const bool isNameless = (structType.getTypeName() == "");
Jamie Madillc835df62013-06-21 09:15:32 -04003047 const TString &structName = structureTypeName(structType, useHLSLRowMajorPacking, useStd140Packing);
Jamie Madill9cf6c072013-06-20 11:55:53 -04003048
3049 const TString declareString = (isNameless ? "struct" : "struct " + structName);
3050
3051 TString structure;
3052 structure += declareString + "\n"
3053 "{\n";
3054
Jamie Madillc835df62013-06-21 09:15:32 -04003055 int elementIndex = 0;
3056
Jamie Madill9cf6c072013-06-20 11:55:53 -04003057 for (unsigned int i = 0; i < fields.size(); i++)
3058 {
3059 const TType &field = *fields[i].type;
3060
Jamie Madillc835df62013-06-21 09:15:32 -04003061 if (useStd140Packing)
3062 {
3063 structure += std140PrePaddingString(field, &elementIndex);
3064 }
3065
3066 structure += " " + structureTypeName(field, useHLSLRowMajorPacking, useStd140Packing) + " " +
Jamie Madill9cf6c072013-06-20 11:55:53 -04003067 decorateField(field.getFieldName(), structType) + arrayString(field) + ";\n";
Jamie Madillc835df62013-06-21 09:15:32 -04003068
3069 if (useStd140Packing)
3070 {
Jamie Madille4075c92013-06-21 09:15:32 -04003071 structure += std140PostPaddingString(field, useHLSLRowMajorPacking);
Jamie Madillc835df62013-06-21 09:15:32 -04003072 }
Jamie Madill9cf6c072013-06-20 11:55:53 -04003073 }
3074
3075 // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
3076 structure += (isNameless ? "} " : "};\n");
3077
Jamie Madille4075c92013-06-21 09:15:32 -04003078 // Add remaining element index to the global map, for use with nested structs in standard layouts
3079 if (useStd140Packing)
3080 {
3081 mStd140StructElementIndexes[structName] = elementIndex;
3082 }
3083
Jamie Madill9cf6c072013-06-20 11:55:53 -04003084 return structure;
3085}
3086
Jamie Madillc835df62013-06-21 09:15:32 -04003087TString OutputHLSL::structureTypeName(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing)
Jamie Madill9cf6c072013-06-20 11:55:53 -04003088{
3089 if (structType.getBasicType() != EbtStruct)
3090 {
3091 return typeString(structType);
3092 }
3093
3094 if (structType.getTypeName() == "")
3095 {
3096 return "";
3097 }
3098
3099 TString prefix = "";
3100
3101 // Structs packed with row-major matrices in HLSL are prefixed with "rm"
3102 // GLSL column-major maps to HLSL row-major, and the converse is true
Jamie Madillc835df62013-06-21 09:15:32 -04003103
3104 if (useStd140Packing)
3105 {
3106 prefix += "std";
3107 }
3108
Jamie Madill9cf6c072013-06-20 11:55:53 -04003109 if (useHLSLRowMajorPacking)
3110 {
Jamie Madillc835df62013-06-21 09:15:32 -04003111 if (prefix != "") prefix += "_";
Jamie Madill9cf6c072013-06-20 11:55:53 -04003112 prefix += "rm";
3113 }
3114
3115 return prefix + typeString(structType);
3116}
3117
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00003118void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
daniel@transgaming.com63691862010-04-29 03:32:42 +00003119{
daniel@transgaming.coma637e552010-04-29 03:39:08 +00003120 if (name == "")
3121 {
daniel@transgaming.com6b998402010-05-04 03:35:07 +00003122 return; // Nameless structures don't have constructors
daniel@transgaming.coma637e552010-04-29 03:39:08 +00003123 }
3124
daniel@transgaming.com43eecdc2012-03-20 20:10:33 +00003125 if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end())
3126 {
3127 return; // Already added
3128 }
3129
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003130 TType ctorType = type;
3131 ctorType.clearArrayness();
alokp@chromium.org58e54292010-08-24 21:40:03 +00003132 ctorType.setPrecision(EbpHigh);
3133 ctorType.setQualifier(EvqTemporary);
daniel@transgaming.com63691862010-04-29 03:32:42 +00003134
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003135 TString ctorName = type.getStruct() ? decorate(name) : name;
3136
3137 typedef std::vector<TType> ParameterArray;
3138 ParameterArray ctorParameters;
daniel@transgaming.com63691862010-04-29 03:32:42 +00003139
daniel@transgaming.com55d48c72011-09-26 18:24:36 +00003140 if (type.getStruct())
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00003141 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003142 mStructNames.insert(decorate(name));
3143
Jamie Madillc835df62013-06-21 09:15:32 -04003144 const TString &structure = structureString(type, false, false);
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00003145
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003146 if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00003147 {
Jamie Madill9cf6c072013-06-20 11:55:53 -04003148 // Add row-major packed struct for interface blocks
3149 TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
Jamie Madillc835df62013-06-21 09:15:32 -04003150 structureString(type, true, false) +
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00003151 "#pragma pack_matrix(column_major)\n";
3152
Jamie Madillc835df62013-06-21 09:15:32 -04003153 const TString &std140Prefix = "std";
3154 TString std140String = structureString(type, false, true);
3155
3156 const TString &std140RowMajorPrefix = "std_rm";
3157 TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
3158 structureString(type, true, true) +
3159 "#pragma pack_matrix(column_major)\n";
3160
Jamie Madill9cf6c072013-06-20 11:55:53 -04003161 mStructDeclarations.push_back(structure);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00003162 mStructDeclarations.push_back(rowMajorString);
Jamie Madillc835df62013-06-21 09:15:32 -04003163 mStructDeclarations.push_back(std140String);
3164 mStructDeclarations.push_back(std140RowMajorString);
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003165 }
3166
Jamie Madill9cf6c072013-06-20 11:55:53 -04003167 const TTypeList &fields = *type.getStruct();
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003168 for (unsigned int i = 0; i < fields.size(); i++)
3169 {
3170 ctorParameters.push_back(*fields[i].type);
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00003171 }
3172 }
daniel@transgaming.com55d48c72011-09-26 18:24:36 +00003173 else if (parameters)
3174 {
3175 for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
3176 {
3177 ctorParameters.push_back((*parameter)->getAsTyped()->getType());
3178 }
3179 }
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00003180 else UNREACHABLE();
daniel@transgaming.com63691862010-04-29 03:32:42 +00003181
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003182 TString constructor;
3183
3184 if (ctorType.getStruct())
3185 {
3186 constructor += ctorName + " " + ctorName + "_ctor(";
3187 }
3188 else // Built-in type
3189 {
3190 constructor += typeString(ctorType) + " " + ctorName + "(";
3191 }
3192
3193 for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
3194 {
3195 const TType &type = ctorParameters[parameter];
3196
3197 constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
3198
3199 if (parameter < ctorParameters.size() - 1)
3200 {
3201 constructor += ", ";
3202 }
3203 }
3204
3205 constructor += ")\n"
3206 "{\n";
3207
3208 if (ctorType.getStruct())
3209 {
3210 constructor += " " + ctorName + " structure = {";
3211 }
3212 else
3213 {
3214 constructor += " return " + typeString(ctorType) + "(";
3215 }
3216
3217 if (ctorType.isMatrix() && ctorParameters.size() == 1)
3218 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003219 int rows = ctorType.getRows();
3220 int cols = ctorType.getCols();
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003221 const TType &parameter = ctorParameters[0];
3222
3223 if (parameter.isScalar())
3224 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003225 for (int row = 0; row < rows; row++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003226 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003227 for (int col = 0; col < cols; col++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003228 {
3229 constructor += TString((row == col) ? "x0" : "0.0");
3230
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003231 if (row < rows - 1 || col < cols - 1)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003232 {
3233 constructor += ", ";
3234 }
3235 }
3236 }
3237 }
3238 else if (parameter.isMatrix())
3239 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003240 for (int row = 0; row < rows; row++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003241 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003242 for (int col = 0; col < cols; col++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003243 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003244 if (row < parameter.getRows() && col < parameter.getCols())
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003245 {
3246 constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
3247 }
3248 else
3249 {
3250 constructor += TString((row == col) ? "1.0" : "0.0");
3251 }
3252
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003253 if (row < rows - 1 || col < cols - 1)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003254 {
3255 constructor += ", ";
3256 }
3257 }
3258 }
3259 }
3260 else UNREACHABLE();
3261 }
3262 else
3263 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04003264 size_t remainingComponents = ctorType.getObjectSize();
3265 size_t parameterIndex = 0;
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003266
3267 while (remainingComponents > 0)
3268 {
3269 const TType &parameter = ctorParameters[parameterIndex];
Jamie Madill94bf7f22013-07-08 13:31:15 -04003270 const size_t parameterSize = parameter.getObjectSize();
3271 bool moreParameters = parameterIndex + 1 < ctorParameters.size();
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003272
3273 constructor += "x" + str(parameterIndex);
3274
3275 if (parameter.isScalar())
3276 {
3277 remainingComponents -= parameter.getObjectSize();
3278 }
3279 else if (parameter.isVector())
3280 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04003281 if (remainingComponents == parameterSize || moreParameters)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003282 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04003283 ASSERT(parameterSize <= remainingComponents);
3284 remainingComponents -= parameterSize;
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003285 }
Jamie Madill94bf7f22013-07-08 13:31:15 -04003286 else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003287 {
3288 switch (remainingComponents)
3289 {
3290 case 1: constructor += ".x"; break;
3291 case 2: constructor += ".xy"; break;
3292 case 3: constructor += ".xyz"; break;
3293 case 4: constructor += ".xyzw"; break;
3294 default: UNREACHABLE();
3295 }
3296
3297 remainingComponents = 0;
3298 }
3299 else UNREACHABLE();
3300 }
3301 else if (parameter.isMatrix() || parameter.getStruct())
3302 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04003303 ASSERT(remainingComponents == parameterSize || moreParameters);
3304 ASSERT(parameterSize <= remainingComponents);
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003305
Jamie Madill94bf7f22013-07-08 13:31:15 -04003306 remainingComponents -= parameterSize;
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003307 }
3308 else UNREACHABLE();
3309
3310 if (moreParameters)
3311 {
3312 parameterIndex++;
3313 }
3314
3315 if (remainingComponents)
3316 {
3317 constructor += ", ";
3318 }
3319 }
3320 }
3321
3322 if (ctorType.getStruct())
3323 {
3324 constructor += "};\n"
3325 " return structure;\n"
3326 "}\n";
3327 }
3328 else
3329 {
3330 constructor += ");\n"
3331 "}\n";
3332 }
3333
daniel@transgaming.com63691862010-04-29 03:32:42 +00003334 mConstructors.insert(constructor);
3335}
3336
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003337const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
3338{
3339 TInfoSinkBase &out = mBody;
3340
3341 if (type.getBasicType() == EbtStruct)
3342 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003343 out << structLookup(type.getTypeName()) + "_ctor(";
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003344
3345 const TTypeList *structure = type.getStruct();
3346
3347 for (size_t i = 0; i < structure->size(); i++)
3348 {
3349 const TType *fieldType = (*structure)[i].type;
3350
3351 constUnion = writeConstantUnion(*fieldType, constUnion);
3352
3353 if (i != structure->size() - 1)
3354 {
3355 out << ", ";
3356 }
3357 }
3358
3359 out << ")";
3360 }
3361 else
3362 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04003363 size_t size = type.getObjectSize();
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003364 bool writeType = size > 1;
3365
3366 if (writeType)
3367 {
3368 out << typeString(type) << "(";
3369 }
3370
Jamie Madill94bf7f22013-07-08 13:31:15 -04003371 for (size_t i = 0; i < size; i++, constUnion++)
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003372 {
3373 switch (constUnion->getType())
3374 {
daniel@transgaming.com6c1203f2013-01-11 04:12:43 +00003375 case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break;
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003376 case EbtInt: out << constUnion->getIConst(); break;
Nicolas Capensc0f7c612013-06-05 11:46:09 -04003377 case EbtUInt: out << constUnion->getUConst(); break;
alokp@chromium.org4e4facd2010-06-02 15:21:22 +00003378 case EbtBool: out << constUnion->getBConst(); break;
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003379 default: UNREACHABLE();
3380 }
3381
3382 if (i != size - 1)
3383 {
3384 out << ", ";
3385 }
3386 }
3387
3388 if (writeType)
3389 {
3390 out << ")";
3391 }
3392 }
3393
3394 return constUnion;
3395}
3396
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003397TString OutputHLSL::scopeString(unsigned int depthLimit)
3398{
3399 TString string;
3400
3401 for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
3402 {
3403 string += "_" + str(i);
3404 }
3405
3406 return string;
3407}
3408
3409TString OutputHLSL::scopedStruct(const TString &typeName)
3410{
3411 if (typeName == "")
3412 {
3413 return typeName;
3414 }
3415
3416 return typeName + scopeString(mScopeDepth);
3417}
3418
3419TString OutputHLSL::structLookup(const TString &typeName)
3420{
3421 for (int depth = mScopeDepth; depth >= 0; depth--)
3422 {
3423 TString scopedName = decorate(typeName + scopeString(depth));
3424
3425 for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
3426 {
3427 if (*structName == scopedName)
3428 {
3429 return scopedName;
3430 }
3431 }
3432 }
3433
3434 UNREACHABLE(); // Should have found a matching constructor
3435
3436 return typeName;
3437}
3438
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003439TString OutputHLSL::decorate(const TString &string)
3440{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00003441 if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003442 {
3443 return "_" + string;
3444 }
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00003445
3446 return string;
3447}
3448
apatrick@chromium.org65756022012-01-17 21:45:38 +00003449TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00003450{
daniel@transgaming.comdb019952012-12-20 21:13:32 +00003451 if (type.getBasicType() == EbtSamplerExternalOES)
apatrick@chromium.org65756022012-01-17 21:45:38 +00003452 {
3453 return "ex_" + string;
3454 }
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00003455
3456 return decorate(string);
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003457}
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00003458
3459TString OutputHLSL::decorateField(const TString &string, const TType &structure)
3460{
3461 if (structure.getTypeName().compare(0, 3, "gl_") != 0)
3462 {
3463 return decorate(string);
3464 }
3465
3466 return string;
3467}
daniel@transgaming.com652468c2012-12-20 21:11:57 +00003468
3469TString OutputHLSL::registerString(TIntermSymbol *operand)
3470{
3471 ASSERT(operand->getQualifier() == EvqUniform);
3472
3473 if (IsSampler(operand->getBasicType()))
3474 {
3475 return "s" + str(samplerRegister(operand));
3476 }
3477
3478 return "c" + str(uniformRegister(operand));
3479}
3480
3481int OutputHLSL::samplerRegister(TIntermSymbol *sampler)
3482{
3483 const TType &type = sampler->getType();
3484 ASSERT(IsSampler(type.getBasicType()));
3485
3486 int index = mSamplerRegister;
3487 mSamplerRegister += sampler->totalRegisterCount();
3488
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003489 declareUniform(type, sampler->getSymbol(), index);
3490
daniel@transgaming.com652468c2012-12-20 21:11:57 +00003491 return index;
3492}
3493
3494int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
3495{
3496 const TType &type = uniform->getType();
3497 ASSERT(!IsSampler(type.getBasicType()));
3498
3499 int index = mUniformRegister;
3500 mUniformRegister += uniform->totalRegisterCount();
3501
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003502 declareUniform(type, uniform->getSymbol(), index);
3503
daniel@transgaming.com652468c2012-12-20 21:11:57 +00003504 return index;
3505}
3506
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003507void OutputHLSL::declareUniformToList(const TType &type, const TString &name, int index, ActiveUniforms& output)
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003508{
3509 const TTypeList *structure = type.getStruct();
3510
3511 if (!structure)
3512 {
Jamie Madill010fffa2013-06-20 11:55:53 -04003513 const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
3514 output.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index, isRowMajorMatrix));
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003515 }
3516 else
3517 {
Jamie Madill010fffa2013-06-20 11:55:53 -04003518 Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index, false);
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003519
3520 int fieldIndex = index;
3521
3522 for (size_t i = 0; i < structure->size(); i++)
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003523 {
Jamie Madill010fffa2013-06-20 11:55:53 -04003524 TType fieldType = *(*structure)[i].type;
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003525 const TString &fieldName = fieldType.getFieldName();
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003526
Jamie Madill010fffa2013-06-20 11:55:53 -04003527 // make sure to copy matrix packing information
3528 fieldType.setLayoutQualifier(type.getLayoutQualifier());
3529
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003530 declareUniformToList(fieldType, fieldName, fieldIndex, structUniform.fields);
3531 fieldIndex += fieldType.totalRegisterCount();
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003532 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003533
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003534 output.push_back(structUniform);
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003535 }
3536}
3537
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003538void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
3539{
3540 declareUniformToList(type, name, index, mActiveUniforms);
3541}
3542
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003543GLenum OutputHLSL::glVariableType(const TType &type)
3544{
3545 if (type.getBasicType() == EbtFloat)
3546 {
3547 if (type.isScalar())
3548 {
3549 return GL_FLOAT;
3550 }
3551 else if (type.isVector())
3552 {
3553 switch(type.getNominalSize())
3554 {
3555 case 2: return GL_FLOAT_VEC2;
3556 case 3: return GL_FLOAT_VEC3;
3557 case 4: return GL_FLOAT_VEC4;
3558 default: UNREACHABLE();
3559 }
3560 }
3561 else if (type.isMatrix())
3562 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00003563 switch (type.getCols())
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003564 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00003565 case 2:
3566 switch(type.getRows())
3567 {
3568 case 2: return GL_FLOAT_MAT2;
3569 case 3: return GL_FLOAT_MAT2x3;
3570 case 4: return GL_FLOAT_MAT2x4;
3571 default: UNREACHABLE();
3572 }
3573
3574 case 3:
3575 switch(type.getRows())
3576 {
3577 case 2: return GL_FLOAT_MAT3x2;
3578 case 3: return GL_FLOAT_MAT3;
3579 case 4: return GL_FLOAT_MAT3x4;
3580 default: UNREACHABLE();
3581 }
3582
3583 case 4:
3584 switch(type.getRows())
3585 {
3586 case 2: return GL_FLOAT_MAT4x2;
3587 case 3: return GL_FLOAT_MAT4x3;
3588 case 4: return GL_FLOAT_MAT4;
3589 default: UNREACHABLE();
3590 }
3591
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003592 default: UNREACHABLE();
3593 }
3594 }
3595 else UNREACHABLE();
3596 }
3597 else if (type.getBasicType() == EbtInt)
3598 {
3599 if (type.isScalar())
3600 {
3601 return GL_INT;
3602 }
3603 else if (type.isVector())
3604 {
3605 switch(type.getNominalSize())
3606 {
3607 case 2: return GL_INT_VEC2;
3608 case 3: return GL_INT_VEC3;
3609 case 4: return GL_INT_VEC4;
3610 default: UNREACHABLE();
3611 }
3612 }
3613 else UNREACHABLE();
3614 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00003615 else if (type.getBasicType() == EbtUInt)
3616 {
3617 if (type.isScalar())
3618 {
3619 return GL_UNSIGNED_INT;
3620 }
3621 else if (type.isVector())
3622 {
Jamie Madill22d63da2013-06-07 12:45:12 -04003623 switch(type.getNominalSize())
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00003624 {
3625 case 2: return GL_UNSIGNED_INT_VEC2;
3626 case 3: return GL_UNSIGNED_INT_VEC3;
3627 case 4: return GL_UNSIGNED_INT_VEC4;
3628 default: UNREACHABLE();
3629 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00003630 }
3631 else UNREACHABLE();
3632 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003633 else if (type.getBasicType() == EbtBool)
3634 {
3635 if (type.isScalar())
3636 {
3637 return GL_BOOL;
3638 }
3639 else if (type.isVector())
3640 {
3641 switch(type.getNominalSize())
3642 {
3643 case 2: return GL_BOOL_VEC2;
3644 case 3: return GL_BOOL_VEC3;
3645 case 4: return GL_BOOL_VEC4;
3646 default: UNREACHABLE();
3647 }
3648 }
3649 else UNREACHABLE();
3650 }
3651 else if (type.getBasicType() == EbtSampler2D)
3652 {
3653 return GL_SAMPLER_2D;
3654 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04003655 else if (type.getBasicType() == EbtSampler3D)
3656 {
3657 return GL_SAMPLER_3D;
3658 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003659 else if (type.getBasicType() == EbtSamplerCube)
3660 {
3661 return GL_SAMPLER_CUBE;
3662 }
Nicolas Capensfb50dff2013-06-24 16:16:23 -04003663 else if (type.getBasicType() == EbtSampler2DArray)
3664 {
3665 return GL_SAMPLER_2D_ARRAY;
3666 }
Nicolas Capens1f1a8332013-06-24 15:42:27 -04003667 else if (type.getBasicType() == EbtISampler2D)
3668 {
3669 return GL_INT_SAMPLER_2D;
3670 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04003671 else if (type.getBasicType() == EbtISampler3D)
3672 {
3673 return GL_INT_SAMPLER_3D;
3674 }
Nicolas Capens1f1a8332013-06-24 15:42:27 -04003675 else if (type.getBasicType() == EbtISamplerCube)
3676 {
3677 return GL_INT_SAMPLER_CUBE;
3678 }
Nicolas Capensfb50dff2013-06-24 16:16:23 -04003679 else if (type.getBasicType() == EbtISampler2DArray)
3680 {
3681 return GL_INT_SAMPLER_2D_ARRAY;
3682 }
Nicolas Capens075368e2013-06-24 15:58:30 -04003683 else if (type.getBasicType() == EbtUSampler2D)
3684 {
3685 return GL_UNSIGNED_INT_SAMPLER_2D;
3686 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04003687 else if (type.getBasicType() == EbtUSampler3D)
3688 {
3689 return GL_UNSIGNED_INT_SAMPLER_3D;
3690 }
Nicolas Capens075368e2013-06-24 15:58:30 -04003691 else if (type.getBasicType() == EbtUSamplerCube)
3692 {
3693 return GL_UNSIGNED_INT_SAMPLER_CUBE;
3694 }
Nicolas Capensfb50dff2013-06-24 16:16:23 -04003695 else if (type.getBasicType() == EbtUSampler2DArray)
3696 {
3697 return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
3698 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003699 else UNREACHABLE();
3700
3701 return GL_NONE;
3702}
3703
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003704GLenum OutputHLSL::glVariablePrecision(const TType &type)
3705{
3706 if (type.getBasicType() == EbtFloat)
3707 {
3708 switch (type.getPrecision())
3709 {
3710 case EbpHigh: return GL_HIGH_FLOAT;
3711 case EbpMedium: return GL_MEDIUM_FLOAT;
3712 case EbpLow: return GL_LOW_FLOAT;
3713 case EbpUndefined:
3714 // Should be defined as the default precision by the parser
3715 default: UNREACHABLE();
3716 }
3717 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00003718 else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003719 {
3720 switch (type.getPrecision())
3721 {
3722 case EbpHigh: return GL_HIGH_INT;
3723 case EbpMedium: return GL_MEDIUM_INT;
3724 case EbpLow: return GL_LOW_INT;
3725 case EbpUndefined:
3726 // Should be defined as the default precision by the parser
3727 default: UNREACHABLE();
3728 }
3729 }
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003730
shannon.woods@transgaming.com10aadb22013-02-28 23:17:52 +00003731 // Other types (boolean, sampler) don't have a precision
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003732 return GL_NONE;
3733}
3734
shannon.woods%transgaming.com@gtempaccount.com6f273e32013-04-13 03:41:15 +00003735bool OutputHLSL::isVaryingOut(TQualifier qualifier)
3736{
3737 switch(qualifier)
3738 {
3739 case EvqVaryingOut:
3740 case EvqInvariantVaryingOut:
3741 case EvqSmoothOut:
3742 case EvqFlatOut:
3743 case EvqCentroidOut:
3744 return true;
3745 }
3746
3747 return false;
3748}
3749
3750bool OutputHLSL::isVaryingIn(TQualifier qualifier)
3751{
3752 switch(qualifier)
3753 {
3754 case EvqVaryingIn:
3755 case EvqInvariantVaryingIn:
3756 case EvqSmoothIn:
3757 case EvqFlatIn:
3758 case EvqCentroidIn:
3759 return true;
3760 }
3761
3762 return false;
3763}
3764
3765bool OutputHLSL::isVarying(TQualifier qualifier)
3766{
3767 return isVaryingIn(qualifier) || isVaryingOut(qualifier);
3768}
3769
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003770}