blob: 0d41d644696ba65c2f1118e34d5dc4ab56e033fc [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"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000017
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +000018#include <algorithm>
shannon.woods@transgaming.comfff89b32013-02-28 23:20:15 +000019#include <cfloat>
20#include <stdio.h>
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +000021
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022namespace sh
23{
daniel@transgaming.com005c7392010-04-15 20:45:27 +000024// Integer to TString conversion
25TString str(int i)
26{
27 char buffer[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +000028 snprintf(buffer, sizeof(buffer), "%d", i);
daniel@transgaming.com005c7392010-04-15 20:45:27 +000029 return buffer;
30}
31
Nicolas Capense0ba27a2013-06-24 16:10:52 -040032TString OutputHLSL::TextureFunction::name() const
33{
34 TString name = "gl_texture";
35
36 if (sampler == EbtSampler2D ||
37 sampler == EbtISampler2D ||
38 sampler == EbtUSampler2D)
39 {
40 name += "2D";
41 }
42 else if (sampler == EbtSampler3D ||
43 sampler == EbtISampler3D ||
44 sampler == EbtUSampler3D)
45 {
46 name += "3D";
47 }
48 else if (sampler == EbtSamplerCube ||
49 sampler == EbtISamplerCube ||
50 sampler == EbtUSamplerCube)
51 {
52 name += "Cube";
53 }
54 else UNREACHABLE();
55
56 if (proj)
57 {
58 name += "Proj";
59 }
60
61 switch(mipmap)
62 {
63 case IMPLICIT: break;
64 case BIAS: break;
65 case LOD: name += "Lod"; break;
66 case LOD0: name += "Lod0"; break;
67 default: UNREACHABLE();
68 }
69
70 return name + "(";
71}
72
73bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
74{
75 if (sampler < rhs.sampler) return true;
76 if (coords < rhs.coords) return true;
77 if (!proj && rhs.proj) return true;
78 if (mipmap < rhs.mipmap) return true;
79
80 return false;
81}
82
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +000083OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +000084 : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085{
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +000086 mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +000087 mInsideFunction = false;
daniel@transgaming.comb5875982010-04-15 20:44:53 +000088
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +000089 mUsesFragColor = false;
90 mUsesFragData = false;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +000091 mUsesDepthRange = false;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000092 mUsesFragCoord = false;
93 mUsesPointCoord = false;
94 mUsesFrontFacing = false;
95 mUsesPointSize = false;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +000096 mUsesXor = false;
97 mUsesMod1 = false;
daniel@transgaming.com4229f592011-11-24 22:34:04 +000098 mUsesMod2v = false;
99 mUsesMod2f = false;
100 mUsesMod3v = false;
101 mUsesMod3f = false;
102 mUsesMod4v = false;
103 mUsesMod4f = false;
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +0000104 mUsesFaceforward1 = false;
105 mUsesFaceforward2 = false;
106 mUsesFaceforward3 = false;
107 mUsesFaceforward4 = false;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000108
109 for (unsigned int col = 0; col <= 4; col++)
110 {
111 for (unsigned int row = 0; row <= 4; row++)
112 {
113 mUsesEqualMat[col][row] = false;
114 }
115 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000116 mUsesEqualVec2 = false;
117 mUsesEqualVec3 = false;
118 mUsesEqualVec4 = false;
119 mUsesEqualIVec2 = false;
120 mUsesEqualIVec3 = false;
121 mUsesEqualIVec4 = false;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000122 mUsesEqualUVec2 = false;
123 mUsesEqualUVec3 = false;
124 mUsesEqualUVec4 = false;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000125 mUsesEqualBVec2 = false;
126 mUsesEqualBVec3 = false;
127 mUsesEqualBVec4 = false;
daniel@transgaming.com35342dc2012-02-28 02:01:22 +0000128 mUsesAtan2_1 = false;
129 mUsesAtan2_2 = false;
130 mUsesAtan2_3 = false;
131 mUsesAtan2_4 = false;
daniel@transgaming.com005c7392010-04-15 20:45:27 +0000132
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000133 mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
134
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +0000135 mScopeDepth = 0;
136
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +0000137 mUniqueIndex = 0;
daniel@transgaming.com89431aa2012-05-31 01:20:29 +0000138
139 mContainsLoopDiscontinuity = false;
140 mOutputLod0Function = false;
daniel@transgaming.come11100c2012-05-31 01:20:32 +0000141 mInsideDiscontinuousLoop = false;
daniel@transgaming.come9b3f602012-07-11 20:37:31 +0000142
143 mExcessiveLoopIndex = NULL;
daniel@transgaming.com652468c2012-12-20 21:11:57 +0000144
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000145 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +0000146 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000147 if (mContext.shaderType == SH_FRAGMENT_SHADER)
148 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000149 mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000150 }
151 else
152 {
shannon.woods@transgaming.com42832a62013-02-28 23:18:38 +0000153 mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000154 }
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +0000155 }
156 else
157 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000158 mUniformRegister = 0;
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +0000159 }
160
daniel@transgaming.com652468c2012-12-20 21:11:57 +0000161 mSamplerRegister = 0;
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000162 mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
Jamie Madill574d9dd2013-06-20 11:55:56 -0400163 mPaddingCounter = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164}
165
daniel@transgaming.comb5875982010-04-15 20:44:53 +0000166OutputHLSL::~OutputHLSL()
167{
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +0000168 delete mUnfoldShortCircuit;
daniel@transgaming.comb5875982010-04-15 20:44:53 +0000169}
170
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000171void OutputHLSL::output()
172{
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +0000173 mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
daniel@transgaming.com89431aa2012-05-31 01:20:29 +0000174
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000175 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 +0000176 header();
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000177
alokp@chromium.org646ea1e2012-06-15 17:36:31 +0000178 mContext.infoSink().obj << mHeader.c_str();
179 mContext.infoSink().obj << mBody.c_str();
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000180}
181
daniel@transgaming.comb5875982010-04-15 20:44:53 +0000182TInfoSinkBase &OutputHLSL::getBodyStream()
183{
184 return mBody;
185}
186
daniel@transgaming.com043da132012-12-20 21:12:22 +0000187const ActiveUniforms &OutputHLSL::getUniforms()
188{
189 return mActiveUniforms;
190}
191
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000192const ActiveInterfaceBlocks &OutputHLSL::getInterfaceBlocks() const
193{
194 return mActiveInterfaceBlocks;
195}
196
Jamie Madill46131a32013-06-20 11:55:50 -0400197const ActiveShaderVariables &OutputHLSL::getOutputVariables() const
198{
199 return mActiveOutputVariables;
200}
201
Jamie Madilldefb6742013-06-20 11:55:51 -0400202const ActiveShaderVariables &OutputHLSL::getAttributes() const
203{
204 return mActiveAttributes;
205}
206
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000207int OutputHLSL::vectorSize(const TType &type) const
208{
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000209 int elementSize = type.isMatrix() ? type.getCols() : 1;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000210 int arraySize = type.isArray() ? type.getArraySize() : 1;
211
212 return elementSize * arraySize;
213}
214
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000215TString OutputHLSL::interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType)
216{
217 if (interfaceBlockType.hasInstanceName())
218 {
219 return interfaceBlockType.getTypeName() + "." + uniformType.getFieldName();
220 }
221 else
222 {
223 return uniformType.getFieldName();
224 }
225}
226
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000227TString OutputHLSL::decoratePrivate(const TString &privateText)
228{
229 return "dx_" + privateText;
230}
231
232TString OutputHLSL::interfaceBlockStructName(const TType &interfaceBlockType)
233{
234 return decoratePrivate(interfaceBlockType.getTypeName()) + "_type";
235}
236
237TString OutputHLSL::interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex)
238{
239 if (!interfaceBlockType.hasInstanceName())
240 {
241 return "";
242 }
243 else if (interfaceBlockType.isArray())
244 {
245 return decoratePrivate(interfaceBlockType.getInstanceName()) + "_" + str(arrayIndex);
246 }
247 else
248 {
249 return decorate(interfaceBlockType.getInstanceName());
250 }
251}
252
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000253TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType)
254{
Jamie Madill529077d2013-06-20 11:55:54 -0400255 const TLayoutMatrixPacking matrixPacking = memberType.getLayoutQualifier().matrixPacking;
256 ASSERT(matrixPacking != EmpUnspecified);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000257
258 if (memberType.isMatrix())
259 {
Jamie Madill9cf6c072013-06-20 11:55:53 -0400260 // Use HLSL row-major packing for GLSL column-major matrices
Jamie Madill529077d2013-06-20 11:55:54 -0400261 const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
262 return matrixPackString + " " + typeString(memberType);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000263 }
264 else if (memberType.getBasicType() == EbtStruct)
265 {
Jamie Madill9cf6c072013-06-20 11:55:53 -0400266 // Use HLSL row-major packing for GLSL column-major matrices
Jamie Madill529077d2013-06-20 11:55:54 -0400267 return structureTypeName(memberType, matrixPacking == EmpColumnMajor);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000268 }
269 else
270 {
271 return typeString(memberType);
272 }
273}
274
Jamie Madill574d9dd2013-06-20 11:55:56 -0400275TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex)
276{
277 if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
278 {
279 // no padding needed, HLSL will align the field to a new register
280 *elementIndex = 0;
281 return "";
282 }
283
284 const GLenum glType = glVariableType(type);
285 const int numComponents = gl::UniformComponentCount(glType);
286
287 if (numComponents >= 4)
288 {
289 // no padding needed, HLSL will align the field to a new register
290 *elementIndex = 0;
291 return "";
292 }
293
294 if (*elementIndex + numComponents > 4)
295 {
296 // no padding needed, HLSL will align the field to a new register
297 *elementIndex = numComponents;
298 return "";
299 }
300
301 TString padding;
302
303 const int alignment = numComponents == 3 ? 4 : numComponents;
304 const int paddingOffset = (*elementIndex % alignment);
305
306 if (paddingOffset != 0)
307 {
308 // padding is neccessary
309 for (int paddingIndex = paddingOffset; paddingIndex < alignment; paddingIndex++)
310 {
311 padding += " float pad_" + str(mPaddingCounter++) + ";\n";
312 }
313
314 *elementIndex += (alignment - paddingOffset);
315 }
316
317 *elementIndex += numComponents;
318 *elementIndex %= 4;
319
320 return padding;
321}
322
323TString OutputHLSL::std140PostPaddingString(const TType &type)
324{
325 if (!type.isMatrix() && !type.isArray())
326 {
327 return "";
328 }
329
330 const GLenum glType = glVariableType(type);
331 int numComponents = 0;
332
333 if (type.isMatrix())
334 {
335 const bool isRowMajorMatrix = (type.getLayoutQualifier().matrixPacking == EmpRowMajor);
336 numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
337 }
338 else
339 {
340 numComponents = gl::UniformComponentCount(glType);
341 }
342
343 TString padding;
344 for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
345 {
346 padding += " float pad_" + str(mPaddingCounter++) + ";\n";
347 }
348 return padding;
349}
350
351TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage)
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000352{
353 TString hlsl;
354
Jamie Madill574d9dd2013-06-20 11:55:56 -0400355 int elementIndex = 0;
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000356
357 for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
358 {
359 const TType &memberType = *typeList[typeIndex].type;
Jamie Madill574d9dd2013-06-20 11:55:56 -0400360
361 if (blockStorage == EbsStd140)
362 {
363 if (memberType.getBasicType() == EbtStruct)
364 {
365 UNIMPLEMENTED();
366 }
367 else
368 {
369 // 2 and 3 component vector types in some cases need pre-padding
370 hlsl += std140PrePaddingString(memberType, &elementIndex);
371 }
372 }
373
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000374 hlsl += " " + interfaceBlockMemberTypeString(memberType) +
375 " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
Jamie Madill574d9dd2013-06-20 11:55:56 -0400376
377 // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
378 if (blockStorage == EbsStd140)
379 {
380 hlsl += std140PostPaddingString(memberType);
381 }
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000382 }
383
384 return hlsl;
385}
386
387TString OutputHLSL::interfaceBlockStructString(const TType &interfaceBlockType)
388{
389 const TTypeList &typeList = *interfaceBlockType.getStruct();
Jamie Madill574d9dd2013-06-20 11:55:56 -0400390 const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000391
392 return "struct " + interfaceBlockStructName(interfaceBlockType) + "\n"
393 "{\n" +
Jamie Madill574d9dd2013-06-20 11:55:56 -0400394 interfaceBlockMemberString(typeList, blockStorage) +
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000395 "};\n\n";
396}
397
398TString OutputHLSL::interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex)
399{
400 const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : "");
401 const TString &blockName = interfaceBlockType.getTypeName() + arrayIndexString;
402 TString hlsl;
403
404 hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
405 "{\n";
406
407 if (interfaceBlockType.hasInstanceName())
408 {
409 hlsl += " " + interfaceBlockStructName(interfaceBlockType) + " " + interfaceBlockInstanceString(interfaceBlockType, arrayIndex) + ";\n";
410 }
411 else
412 {
413 const TTypeList &typeList = *interfaceBlockType.getStruct();
Jamie Madill574d9dd2013-06-20 11:55:56 -0400414 const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
415 hlsl += interfaceBlockMemberString(typeList, blockStorage);
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000416 }
417
418 hlsl += "};\n\n";
419
420 return hlsl;
421}
422
Jamie Madill440dc742013-06-20 11:55:55 -0400423// Use the same layout for packed and shared
424void setBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLayout)
425{
426 interfaceBlock->layout = newLayout;
427 interfaceBlock->blockInfo.clear();
428
429 switch (newLayout)
430 {
431 case BLOCKLAYOUT_SHARED:
432 case BLOCKLAYOUT_PACKED:
433 {
434 HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo);
435 hlslEncoder.encodeFields(interfaceBlock->activeUniforms);
436 interfaceBlock->dataSize = hlslEncoder.getBlockSize();
437 }
438 break;
439
440 case BLOCKLAYOUT_STANDARD:
441 {
442 Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo);
443 stdEncoder.encodeFields(interfaceBlock->activeUniforms);
444 interfaceBlock->dataSize = stdEncoder.getBlockSize();
445 }
446 break;
447
448 default:
449 UNREACHABLE();
450 break;
451 }
452}
453
Jamie Madill574d9dd2013-06-20 11:55:56 -0400454BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage)
455{
456 switch (blockStorage)
457 {
458 case EbsPacked: return BLOCKLAYOUT_PACKED;
459 case EbsShared: return BLOCKLAYOUT_SHARED;
460 case EbsStd140: return BLOCKLAYOUT_STANDARD;
461 default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
462 }
463}
464
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465void OutputHLSL::header()
466{
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000467 TInfoSinkBase &out = mHeader;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000468
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000469 TString uniforms;
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000470 TString interfaceBlocks;
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000471 TString varyings;
472 TString attributes;
473
474 for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++)
475 {
476 const TType &type = uniform->second->getType();
477 const TString &name = uniform->second->getSymbol();
478
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000479 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture
480 {
481 int index = samplerRegister(mReferencedUniforms[name]);
482
483 uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) +
484 " : register(s" + str(index) + ");\n";
485
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000486 uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000487 " : register(t" + str(index) + ");\n";
488 }
489 else
490 {
491 uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) +
492 " : register(" + registerString(mReferencedUniforms[name]) + ");\n";
493 }
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000494 }
495
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000496 for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
497 {
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000498 const TType &nodeType = interfaceBlockIt->second->getType();
499 const TType &interfaceBlockType = nodeType.isInterfaceBlockMember() ? *nodeType.getInterfaceBlockType() : nodeType;
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000500 const TString &blockName = interfaceBlockType.getTypeName();
501 const TTypeList &typeList = *interfaceBlockType.getStruct();
502
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000503 const unsigned int arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getArraySize() : 0;
504 sh::InterfaceBlock interfaceBlock(blockName.c_str(), arraySize, mInterfaceBlockRegister);
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000505 for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
506 {
507 const TType &memberType = *typeList[typeIndex].type;
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000508 const TString &fullUniformName = interfaceBlockUniformName(interfaceBlockType, memberType);
509 declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms);
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000510 }
511
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000512 mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
513
Jamie Madill574d9dd2013-06-20 11:55:56 -0400514 BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlockType.getLayoutQualifier().blockStorage);
515 setBlockLayout(&interfaceBlock, blockLayoutType);
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000516 mActiveInterfaceBlocks.push_back(interfaceBlock);
517
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000518 if (interfaceBlockType.hasInstanceName())
519 {
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000520 interfaceBlocks += interfaceBlockStructString(interfaceBlockType);
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000521 }
522
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000523 if (arraySize > 0)
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000524 {
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000525 for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
526 {
527 interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex + arrayIndex, arrayIndex);
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000528 }
529 }
530 else
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000531 {
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000532 interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex, GL_INVALID_INDEX);
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000533 }
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +0000534 }
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +0000535
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000536 for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
537 {
538 const TType &type = varying->second->getType();
539 const TString &name = varying->second->getSymbol();
540
541 // Program linking depends on this exact format
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000542 varyings += "static " + interpolationString(type.getQualifier()) + " " + typeString(type) + " " +
543 decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000544 }
545
546 for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
547 {
548 const TType &type = attribute->second->getType();
549 const TString &name = attribute->second->getSymbol();
550
551 attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
Jamie Madilldefb6742013-06-20 11:55:51 -0400552
553 ShaderVariable shaderVar(glVariableType(type), glVariablePrecision(type), name.c_str(),
554 (unsigned int)type.getArraySize(), type.getLayoutQualifier().location);
555 mActiveAttributes.push_back(shaderVar);
daniel@transgaming.com8803b852012-12-20 21:11:47 +0000556 }
557
Jamie Madill529077d2013-06-20 11:55:54 -0400558 for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
559 {
560 out << *structDeclaration;
561 }
562
563 for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
564 {
565 out << *constructor;
566 }
567
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400568 if (mContext.shaderType == SH_FRAGMENT_SHADER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000569 {
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000570 TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
shannon.woods%transgaming.com@gtempaccount.com99ab6eb2013-04-13 03:42:00 +0000571 const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000572
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000573 out << "// Varyings\n";
574 out << varyings;
Jamie Madill46131a32013-06-20 11:55:50 -0400575 out << "\n";
576
577 if (mContext.getShaderVersion() >= 300)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000578 {
Jamie Madill46131a32013-06-20 11:55:50 -0400579 for (auto outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000580 {
Jamie Madill46131a32013-06-20 11:55:50 -0400581 const TString &variableName = outputVariableIt->first;
582 const TType &variableType = outputVariableIt->second->getType();
583 const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier();
584
585 out << "static " + typeString(variableType) + " out_" + variableName + arrayString(variableType) +
586 " = " + initializer(variableType) + ";\n";
587
588 ShaderVariable outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(),
589 (unsigned int)variableType.getArraySize(), layoutQualifier.location);
590 mActiveOutputVariables.push_back(outputVar);
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000591 }
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +0000592 }
Jamie Madill46131a32013-06-20 11:55:50 -0400593 else
594 {
595 const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
596
597 out << "static float4 gl_Color[" << numColorValues << "] =\n"
598 "{\n";
599 for (unsigned int i = 0; i < numColorValues; i++)
600 {
601 out << " float4(0, 0, 0, 0)";
602 if (i + 1 != numColorValues)
603 {
604 out << ",";
605 }
606 out << "\n";
607 }
608
609 out << "};\n";
610 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000611
612 if (mUsesFragCoord)
613 {
614 out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
615 }
616
617 if (mUsesPointCoord)
618 {
619 out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
620 }
621
622 if (mUsesFrontFacing)
623 {
624 out << "static bool gl_FrontFacing = false;\n";
625 }
626
627 out << "\n";
628
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000629 if (mUsesDepthRange)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000630 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000631 out << "struct gl_DepthRangeParameters\n"
632 "{\n"
633 " float near;\n"
634 " float far;\n"
635 " float diff;\n"
636 "};\n"
637 "\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000638 }
639
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000640 if (mOutputType == SH_HLSL11_OUTPUT)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000641 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000642 out << "cbuffer DriverConstants : register(b1)\n"
643 "{\n";
644
645 if (mUsesDepthRange)
646 {
647 out << " float3 dx_DepthRange : packoffset(c0);\n";
648 }
649
650 if (mUsesFragCoord)
651 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000652 out << " float4 dx_ViewCoords : packoffset(c1);\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000653 }
654
655 if (mUsesFragCoord || mUsesFrontFacing)
656 {
657 out << " float3 dx_DepthFront : packoffset(c2);\n";
658 }
659
660 out << "};\n";
661 }
662 else
663 {
664 if (mUsesDepthRange)
665 {
666 out << "uniform float3 dx_DepthRange : register(c0);";
667 }
668
669 if (mUsesFragCoord)
670 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000671 out << "uniform float4 dx_ViewCoords : register(c1);\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000672 }
673
674 if (mUsesFragCoord || mUsesFrontFacing)
675 {
676 out << "uniform float3 dx_DepthFront : register(c2);\n";
677 }
678 }
679
680 out << "\n";
681
682 if (mUsesDepthRange)
683 {
684 out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
685 "\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000686 }
687
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000688 out << uniforms;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000689 out << "\n";
daniel@transgaming.com5024cc42010-04-20 18:52:04 +0000690
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000691 if (!interfaceBlocks.empty())
692 {
693 out << interfaceBlocks;
694 out << "\n";
695 }
696
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000697 if (usingMRTExtension && mNumRenderTargets > 1)
698 {
699 out << "#define GL_USES_MRT\n";
700 }
701
702 if (mUsesFragColor)
703 {
704 out << "#define GL_USES_FRAG_COLOR\n";
705 }
706
707 if (mUsesFragData)
708 {
709 out << "#define GL_USES_FRAG_DATA\n";
710 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000711 }
daniel@transgaming.comd25ab252010-03-30 03:36:26 +0000712 else // Vertex shader
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000713 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000714 out << "// Attributes\n";
715 out << attributes;
716 out << "\n"
717 "static float4 gl_Position = float4(0, 0, 0, 0);\n";
718
719 if (mUsesPointSize)
720 {
721 out << "static float gl_PointSize = float(1);\n";
722 }
723
724 out << "\n"
725 "// Varyings\n";
726 out << varyings;
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000727 out << "\n";
728
729 if (mUsesDepthRange)
730 {
731 out << "struct gl_DepthRangeParameters\n"
732 "{\n"
733 " float near;\n"
734 " float far;\n"
735 " float diff;\n"
736 "};\n"
737 "\n";
738 }
739
740 if (mOutputType == SH_HLSL11_OUTPUT)
741 {
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000742 if (mUsesDepthRange)
743 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000744 out << "cbuffer DriverConstants : register(b1)\n"
745 "{\n"
746 " float3 dx_DepthRange : packoffset(c0);\n"
747 "};\n"
748 "\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000749 }
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000750 }
751 else
752 {
753 if (mUsesDepthRange)
754 {
755 out << "uniform float3 dx_DepthRange : register(c0);\n";
756 }
757
shannon.woods@transgaming.com42832a62013-02-28 23:18:38 +0000758 out << "uniform float4 dx_ViewAdjust : register(c1);\n"
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +0000759 "\n";
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000760 }
761
shannon.woods@transgaming.com46a5b872013-01-25 21:52:57 +0000762 if (mUsesDepthRange)
763 {
764 out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
765 "\n";
766 }
767
768 out << uniforms;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000769 out << "\n";
daniel@transgaming.com15795192011-05-11 15:36:20 +0000770
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000771 if (!interfaceBlocks.empty())
772 {
773 out << interfaceBlocks;
774 out << "\n";
775 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400776 }
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +0000777
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400778 for (TextureFunctionSet::const_iterator textureFunction = mUsesTexture.begin(); textureFunction != mUsesTexture.end(); textureFunction++)
779 {
780 // Return type
781 switch(textureFunction->sampler)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000782 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400783 case EbtSampler2D: out << "float4 "; break;
784 case EbtSampler3D: out << "float4 "; break;
785 case EbtSamplerCube: out << "float4 "; break;
786 case EbtISampler2D: out << "int4 "; break;
787 case EbtISampler3D: out << "int4 "; break;
788 case EbtISamplerCube: out << "int4 "; break;
789 case EbtUSampler2D: out << "uint4 "; break;
790 case EbtUSampler3D: out << "uint4 "; break;
791 case EbtUSamplerCube: out << "uint4 "; break;
792 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000793 }
794
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400795 // Function name
796 out << textureFunction->name();
797
798 // Argument list
799 int hlslCoords = 4;
800
801 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000802 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400803 switch(textureFunction->sampler)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000804 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400805 case EbtSampler2D: out << "sampler2D s"; hlslCoords = 2; break;
806 case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break;
807 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000808 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400809
810 switch(textureFunction->mipmap)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000811 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400812 case TextureFunction::IMPLICIT: break;
813 case TextureFunction::BIAS: hlslCoords = 4; break;
814 case TextureFunction::LOD: hlslCoords = 4; break;
815 case TextureFunction::LOD0: hlslCoords = 4; break;
816 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000817 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400818 }
819 else if (mOutputType == SH_HLSL11_OUTPUT)
820 {
821 switch(textureFunction->sampler)
822 {
823 case EbtSampler2D: out << "Texture2D x, SamplerState s"; hlslCoords = 2; break;
824 case EbtSampler3D: out << "Texture3D x, SamplerState s"; hlslCoords = 3; break;
825 case EbtSamplerCube: out << "TextureCube x, SamplerState s"; hlslCoords = 3; break;
826 case EbtISampler2D: out << "Texture2D<int4> x, SamplerState s"; hlslCoords = 2; break;
827 case EbtISampler3D: out << "Texture3D<int4> x, SamplerState s"; hlslCoords = 3; break;
828 case EbtISamplerCube: out << "TextureCube<int4> x, SamplerState s"; hlslCoords = 3; break;
829 case EbtUSampler2D: out << "Texture2D<uint4> x, SamplerState s"; hlslCoords = 2; break;
830 case EbtUSampler3D: out << "Texture3D<uint4> x, SamplerState s"; hlslCoords = 3; break;
831 case EbtUSamplerCube: out << "TextureCube<uint4> x, SamplerState s"; hlslCoords = 3; break;
832 default: UNREACHABLE();
833 }
834 }
835 else UNREACHABLE();
836
837 switch(textureFunction->coords)
838 {
839 case 2: out << ", float2 t"; break;
840 case 3: out << ", float3 t"; break;
841 case 4: out << ", float4 t"; break;
842 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000843 }
844
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400845 switch(textureFunction->mipmap)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000846 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400847 case TextureFunction::IMPLICIT: break;
848 case TextureFunction::BIAS: out << ", float bias"; break;
849 case TextureFunction::LOD: out << ", float lod"; break;
850 case TextureFunction::LOD0: break;
851 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000852 }
853
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400854 out << ")\n"
855 "{\n"
856 " return ";
857
858 // HLSL intrinsic
859 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.com15795192011-05-11 15:36:20 +0000860 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400861 switch(textureFunction->sampler)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000862 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400863 case EbtSampler2D: out << "tex2D"; break;
864 case EbtSamplerCube: out << "texCUBE"; break;
865 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000866 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400867 }
868 else if (mOutputType == SH_HLSL11_OUTPUT)
869 {
870 out << "x.Sample";
871 }
872 else UNREACHABLE();
873
874 if (mOutputType == SH_HLSL9_OUTPUT)
875 {
876 switch(textureFunction->mipmap)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000877 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400878 case TextureFunction::IMPLICIT: out << "(s, "; break;
879 case TextureFunction::BIAS: out << "bias(s, "; break;
880 case TextureFunction::LOD: out << "lod(s, "; break;
881 case TextureFunction::LOD0: out << "lod(s, "; break;
882 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000883 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400884 }
885 else if (mOutputType == SH_HLSL11_OUTPUT)
886 {
887 switch(textureFunction->mipmap)
888 {
889 case TextureFunction::IMPLICIT: out << "(s, "; break;
890 case TextureFunction::BIAS: out << "Bias(s, "; break;
891 case TextureFunction::LOD: out << "Level(s, "; break;
892 case TextureFunction::LOD0: out << "Level(s, "; break;
893 default: UNREACHABLE();
894 }
895 }
896 else UNREACHABLE();
897
898 switch(hlslCoords)
899 {
900 case 2: out << "float2("; break;
901 case 3: out << "float3("; break;
902 case 4: out << "float4("; break;
903 default: UNREACHABLE();
daniel@transgaming.com15795192011-05-11 15:36:20 +0000904 }
905
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400906 TString proj = "";
907
908 if (textureFunction->proj)
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400909 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400910 switch(textureFunction->coords)
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400911 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400912 case 3: proj = " / t.z"; break;
913 case 4: proj = " / t.w"; break;
914 default: UNREACHABLE();
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400915 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400916 }
917
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400918 out << "t.x" + proj + ", t.y" + proj;
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400919
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400920 if (mOutputType == SH_HLSL9_OUTPUT)
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400921 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400922 if (hlslCoords >= 3)
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400923 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400924 if (textureFunction->coords < 3)
925 {
926 out << ", 0";
927 }
928 else
929 {
930 out << ", t.z" + proj;
931 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400932 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400933
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400934 if (hlslCoords == 4)
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400935 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400936 switch(textureFunction->mipmap)
937 {
938 case TextureFunction::BIAS: out << ", bias"; break;
939 case TextureFunction::LOD: out << ", lod"; break;
940 case TextureFunction::LOD0: out << ", 0"; break;
941 default: UNREACHABLE();
942 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400943 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -0400944
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400945 out << "));\n";
daniel@transgaming.com15795192011-05-11 15:36:20 +0000946 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400947 else if (mOutputType == SH_HLSL11_OUTPUT)
948 {
949 if (hlslCoords >= 3)
950 {
951 out << ", t.z" + proj;
952 }
daniel@transgaming.com15795192011-05-11 15:36:20 +0000953
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400954 switch(textureFunction->mipmap)
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000955 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400956 case TextureFunction::IMPLICIT: out << "));"; break;
957 case TextureFunction::BIAS: out << "), bias);"; break;
958 case TextureFunction::LOD: out << "), lod);"; break;
959 case TextureFunction::LOD0: out << "), 0);"; break;
960 default: UNREACHABLE();
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +0000961 }
daniel@transgaming.com15795192011-05-11 15:36:20 +0000962 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -0400963 else UNREACHABLE();
964
965 out << "}\n"
966 "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000967 }
968
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000969 if (mUsesFragCoord)
970 {
971 out << "#define GL_USES_FRAG_COORD\n";
972 }
973
974 if (mUsesPointCoord)
975 {
976 out << "#define GL_USES_POINT_COORD\n";
977 }
978
979 if (mUsesFrontFacing)
980 {
981 out << "#define GL_USES_FRONT_FACING\n";
982 }
983
984 if (mUsesPointSize)
985 {
986 out << "#define GL_USES_POINT_SIZE\n";
987 }
988
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000989 if (mUsesDepthRange)
990 {
991 out << "#define GL_USES_DEPTH_RANGE\n";
992 }
993
daniel@transgaming.comd7c98102010-05-14 17:30:48 +0000994 if (mUsesXor)
995 {
996 out << "bool xor(bool p, bool q)\n"
997 "{\n"
998 " return (p || q) && !(p && q);\n"
999 "}\n"
1000 "\n";
1001 }
1002
1003 if (mUsesMod1)
1004 {
1005 out << "float mod(float x, float y)\n"
1006 "{\n"
1007 " return x - y * floor(x / y);\n"
1008 "}\n"
1009 "\n";
1010 }
daniel@transgaming.com4229f592011-11-24 22:34:04 +00001011
1012 if (mUsesMod2v)
1013 {
1014 out << "float2 mod(float2 x, float2 y)\n"
1015 "{\n"
1016 " return x - y * floor(x / y);\n"
1017 "}\n"
1018 "\n";
1019 }
1020
1021 if (mUsesMod2f)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001022 {
1023 out << "float2 mod(float2 x, float y)\n"
1024 "{\n"
1025 " return x - y * floor(x / y);\n"
1026 "}\n"
1027 "\n";
1028 }
1029
daniel@transgaming.com4229f592011-11-24 22:34:04 +00001030 if (mUsesMod3v)
1031 {
1032 out << "float3 mod(float3 x, float3 y)\n"
1033 "{\n"
1034 " return x - y * floor(x / y);\n"
1035 "}\n"
1036 "\n";
1037 }
1038
1039 if (mUsesMod3f)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001040 {
1041 out << "float3 mod(float3 x, float y)\n"
1042 "{\n"
1043 " return x - y * floor(x / y);\n"
1044 "}\n"
1045 "\n";
1046 }
1047
daniel@transgaming.com4229f592011-11-24 22:34:04 +00001048 if (mUsesMod4v)
1049 {
1050 out << "float4 mod(float4 x, float4 y)\n"
1051 "{\n"
1052 " return x - y * floor(x / y);\n"
1053 "}\n"
1054 "\n";
1055 }
1056
1057 if (mUsesMod4f)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001058 {
1059 out << "float4 mod(float4 x, float y)\n"
1060 "{\n"
1061 " return x - y * floor(x / y);\n"
1062 "}\n"
1063 "\n";
1064 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001065
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001066 if (mUsesFaceforward1)
1067 {
1068 out << "float faceforward(float N, float I, float Nref)\n"
1069 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001070 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001071 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001072 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001073 " }\n"
1074 " else\n"
1075 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001076 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001077 " }\n"
1078 "}\n"
1079 "\n";
1080 }
1081
1082 if (mUsesFaceforward2)
1083 {
1084 out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
1085 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001086 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001087 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001088 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001089 " }\n"
1090 " else\n"
1091 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001092 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001093 " }\n"
1094 "}\n"
1095 "\n";
1096 }
1097
1098 if (mUsesFaceforward3)
1099 {
1100 out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
1101 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001102 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001103 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001104 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001105 " }\n"
1106 " else\n"
1107 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001108 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001109 " }\n"
1110 "}\n"
1111 "\n";
1112 }
1113
1114 if (mUsesFaceforward4)
1115 {
1116 out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
1117 "{\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001118 " if(dot(Nref, I) >= 0)\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001119 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001120 " return -N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001121 " }\n"
1122 " else\n"
1123 " {\n"
daniel@transgaming.com3debd2b2010-05-13 02:07:34 +00001124 " return N;\n"
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001125 " }\n"
1126 "}\n"
1127 "\n";
1128 }
1129
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001130 for (unsigned int cols = 2; cols <= 4; cols++)
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001131 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001132 for (unsigned int rows = 2; rows <= 4; rows++)
1133 {
1134 if (mUsesEqualMat[cols][rows])
1135 {
1136 TString matrixType = "float" + str(cols) + "x" + str(rows);
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001137
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001138 out << "bool equal(" + matrixType + " m, " + matrixType + " n)\n"
1139 "{\n";
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001140
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001141 for (unsigned int row = 0; row < rows; row++)
1142 {
1143 if (row == 0)
1144 {
1145 out << " return ";
1146 }
1147 else
1148 {
1149 out << " ";
1150 }
1151
1152 for (unsigned int col = 0; col < cols; col++)
1153 {
1154 TString index = "[" + str(col) + "][" + str(row) + "]";
1155 out << "m" + index + " == n" + index;
1156
1157 if (col == cols-1 && row == rows-1)
1158 {
1159 out << ";\n";
1160 }
1161 else if (col == cols-1)
1162 {
1163 out << " &&\n";
1164 }
1165 else
1166 {
1167 out << " && ";
1168 }
1169 }
1170 }
1171
1172 out << "}\n";
1173 }
1174 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001175 }
1176
1177 if (mUsesEqualVec2)
1178 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001179 out << "bool equal(float2 v, float2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001180 "{\n"
1181 " return v.x == u.x && v.y == u.y;\n"
1182 "}\n";
1183 }
1184
1185 if (mUsesEqualVec3)
1186 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001187 out << "bool equal(float3 v, float3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001188 "{\n"
1189 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1190 "}\n";
1191 }
1192
1193 if (mUsesEqualVec4)
1194 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001195 out << "bool equal(float4 v, float4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001196 "{\n"
1197 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1198 "}\n";
1199 }
1200
1201 if (mUsesEqualIVec2)
1202 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001203 out << "bool equal(int2 v, int2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001204 "{\n"
1205 " return v.x == u.x && v.y == u.y;\n"
1206 "}\n";
1207 }
1208
1209 if (mUsesEqualIVec3)
1210 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001211 out << "bool equal(int3 v, int3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001212 "{\n"
1213 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1214 "}\n";
1215 }
1216
1217 if (mUsesEqualIVec4)
1218 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001219 out << "bool equal(int4 v, int4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001220 "{\n"
1221 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1222 "}\n";
1223 }
1224
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00001225 if (mUsesEqualUVec2)
1226 {
1227 out << "bool equal(uint2 v, uint2 u)\n"
1228 "{\n"
1229 " return v.x == u.x && v.y == u.y;\n"
1230 "}\n";
1231 }
1232
1233 if (mUsesEqualUVec3)
1234 {
1235 out << "bool equal(uint3 v, uint3 u)\n"
1236 "{\n"
1237 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1238 "}\n";
1239 }
1240
1241 if (mUsesEqualUVec4)
1242 {
1243 out << "bool equal(uint4 v, uint4 u)\n"
1244 "{\n"
1245 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1246 "}\n";
1247 }
1248
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001249 if (mUsesEqualBVec2)
1250 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001251 out << "bool equal(bool2 v, bool2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001252 "{\n"
1253 " return v.x == u.x && v.y == u.y;\n"
1254 "}\n";
1255 }
1256
1257 if (mUsesEqualBVec3)
1258 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001259 out << "bool equal(bool3 v, bool3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001260 "{\n"
1261 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
1262 "}\n";
1263 }
1264
1265 if (mUsesEqualBVec4)
1266 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001267 out << "bool equal(bool4 v, bool4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001268 "{\n"
1269 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
1270 "}\n";
1271 }
daniel@transgaming.com0f189612010-05-07 13:03:36 +00001272
daniel@transgaming.com35342dc2012-02-28 02:01:22 +00001273 if (mUsesAtan2_1)
daniel@transgaming.com0f189612010-05-07 13:03:36 +00001274 {
1275 out << "float atanyx(float y, float x)\n"
1276 "{\n"
1277 " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
1278 " return atan2(y, x);\n"
1279 "}\n";
1280 }
daniel@transgaming.com35342dc2012-02-28 02:01:22 +00001281
1282 if (mUsesAtan2_2)
1283 {
1284 out << "float2 atanyx(float2 y, float2 x)\n"
1285 "{\n"
1286 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1287 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1288 " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
1289 "}\n";
1290 }
1291
1292 if (mUsesAtan2_3)
1293 {
1294 out << "float3 atanyx(float3 y, float3 x)\n"
1295 "{\n"
1296 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1297 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1298 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
1299 " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
1300 "}\n";
1301 }
1302
1303 if (mUsesAtan2_4)
1304 {
1305 out << "float4 atanyx(float4 y, float4 x)\n"
1306 "{\n"
1307 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
1308 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
1309 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
1310 " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
1311 " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
1312 "}\n";
1313 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001314}
1315
1316void OutputHLSL::visitSymbol(TIntermSymbol *node)
1317{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001318 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001319
1320 TString name = node->getSymbol();
1321
shannon.woods%transgaming.com@gtempaccount.come7d4a242013-04-13 03:38:33 +00001322 if (name == "gl_DepthRange")
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001323 {
1324 mUsesDepthRange = true;
1325 out << name;
1326 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001327 else
1328 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001329 TQualifier qualifier = node->getQualifier();
1330
1331 if (qualifier == EvqUniform)
1332 {
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +00001333 if (node->getType().isInterfaceBlockMember())
1334 {
1335 const TString& interfaceBlockTypeName = node->getType().getInterfaceBlockType()->getTypeName();
1336 mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
1337 out << decorateUniform(name, node->getType());
1338 }
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +00001339 else if (node->getBasicType() == EbtInterfaceBlock)
1340 {
1341 const TString& interfaceBlockTypeName = node->getType().getTypeName();
1342 mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
1343 out << decorateUniform(name, node->getType());
1344 }
shannonwoods@chromium.org4a643ae2013-05-30 00:12:27 +00001345 else
1346 {
1347 mReferencedUniforms[name] = node;
1348 out << decorateUniform(name, node->getType());
1349 }
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001350 }
Jamie Madillb120eac2013-06-12 14:08:13 -04001351 else if (qualifier == EvqAttribute || qualifier == EvqVertexInput)
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001352 {
daniel@transgaming.com8803b852012-12-20 21:11:47 +00001353 mReferencedAttributes[name] = node;
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001354 out << decorate(name);
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001355 }
shannon.woods%transgaming.com@gtempaccount.com6f273e32013-04-13 03:41:15 +00001356 else if (isVarying(qualifier))
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001357 {
daniel@transgaming.com8803b852012-12-20 21:11:47 +00001358 mReferencedVaryings[name] = node;
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001359 out << decorate(name);
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +00001360 }
Jamie Madill46131a32013-06-20 11:55:50 -04001361 else if (qualifier == EvqFragmentOutput)
1362 {
1363 mReferencedOutputVariables[name] = node;
1364 out << "out_" << name;
1365 }
1366 else if (qualifier == EvqFragColor)
shannon.woods%transgaming.com@gtempaccount.come7d4a242013-04-13 03:38:33 +00001367 {
1368 out << "gl_Color[0]";
1369 mUsesFragColor = true;
1370 }
1371 else if (qualifier == EvqFragData)
1372 {
1373 out << "gl_Color";
1374 mUsesFragData = true;
1375 }
1376 else if (qualifier == EvqFragCoord)
1377 {
1378 mUsesFragCoord = true;
1379 out << name;
1380 }
1381 else if (qualifier == EvqPointCoord)
1382 {
1383 mUsesPointCoord = true;
1384 out << name;
1385 }
1386 else if (qualifier == EvqFrontFacing)
1387 {
1388 mUsesFrontFacing = true;
1389 out << name;
1390 }
1391 else if (qualifier == EvqPointSize)
1392 {
1393 mUsesPointSize = true;
1394 out << name;
1395 }
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001396 else
1397 {
1398 out << decorate(name);
1399 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001400 }
1401}
1402
1403bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
1404{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001405 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001406
1407 switch (node->getOp())
1408 {
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001409 case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001410 case EOpInitialize:
1411 if (visit == PreVisit)
1412 {
1413 // GLSL allows to write things like "float x = x;" where a new variable x is defined
1414 // and the value of an existing variable x is assigned. HLSL uses C semantics (the
1415 // new variable is created before the assignment is evaluated), so we need to convert
1416 // this to "float t = x, x = t;".
1417
daniel@transgaming.combdfb2e52010-11-15 16:41:20 +00001418 TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
1419 TIntermTyped *expression = node->getRight();
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001420
daniel@transgaming.combdfb2e52010-11-15 16:41:20 +00001421 sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
1422 expression->traverse(&searchSymbol);
1423 bool sameSymbol = searchSymbol.foundMatch();
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001424
daniel@transgaming.combdfb2e52010-11-15 16:41:20 +00001425 if (sameSymbol)
1426 {
1427 // Type already printed
1428 out << "t" + str(mUniqueIndex) + " = ";
1429 expression->traverse(this);
1430 out << ", ";
1431 symbolNode->traverse(this);
1432 out << " = t" + str(mUniqueIndex);
1433
1434 mUniqueIndex++;
1435 return false;
1436 }
1437 }
1438 else if (visit == InVisit)
1439 {
1440 out << " = ";
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00001441 }
1442 break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001443 case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break;
1444 case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break;
1445 case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break;
1446 case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
1447 case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
1448 case EOpVectorTimesMatrixAssign:
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001449 if (visit == PreVisit)
1450 {
1451 out << "(";
1452 }
1453 else if (visit == InVisit)
1454 {
1455 out << " = mul(";
1456 node->getLeft()->traverse(this);
1457 out << ", transpose(";
1458 }
1459 else
1460 {
daniel@transgaming.com3aa74202010-04-29 03:39:04 +00001461 out << ")))";
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001462 }
1463 break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001464 case EOpMatrixTimesMatrixAssign:
1465 if (visit == PreVisit)
1466 {
1467 out << "(";
1468 }
1469 else if (visit == InVisit)
1470 {
1471 out << " = mul(";
1472 node->getLeft()->traverse(this);
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001473 out << ", ";
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001474 }
1475 else
1476 {
daniel@transgaming.com3aa74202010-04-29 03:39:04 +00001477 out << "))";
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001478 }
1479 break;
1480 case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
Jamie Madillb4e664b2013-06-20 11:55:54 -04001481 case EOpIndexDirect:
1482 if (node->getLeft()->getBasicType() == EbtInterfaceBlock)
1483 {
1484 if (visit == PreVisit)
1485 {
1486 const TType &interfaceBlockType = node->getLeft()->getType();
1487 mReferencedInterfaceBlocks[interfaceBlockType.getInstanceName()] = node->getLeft()->getAsSymbolNode();
1488 out << interfaceBlockInstanceString(interfaceBlockType, node->getRight()->getAsConstantUnion()->getIConst(0));
1489 return false;
1490 }
1491 }
1492 else
1493 {
1494 outputTriplet(visit, "", "[", "]");
1495 }
1496 break;
1497 case EOpIndexIndirect:
1498 // We do not currently support indirect references to interface blocks
1499 ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
1500 outputTriplet(visit, "", "[", "]");
1501 break;
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00001502 case EOpIndexDirectStruct:
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +00001503 case EOpIndexDirectInterfaceBlock:
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00001504 if (visit == InVisit)
1505 {
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00001506 out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00001507
1508 return false;
1509 }
1510 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001511 case EOpVectorSwizzle:
1512 if (visit == InVisit)
1513 {
1514 out << ".";
1515
1516 TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
1517
1518 if (swizzle)
1519 {
1520 TIntermSequence &sequence = swizzle->getSequence();
1521
1522 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
1523 {
1524 TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
1525
1526 if (element)
1527 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00001528 int i = element->getIConst(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001529
1530 switch (i)
1531 {
1532 case 0: out << "x"; break;
1533 case 1: out << "y"; break;
1534 case 2: out << "z"; break;
1535 case 3: out << "w"; break;
1536 default: UNREACHABLE();
1537 }
1538 }
1539 else UNREACHABLE();
1540 }
1541 }
1542 else UNREACHABLE();
1543
1544 return false; // Fully processed
1545 }
1546 break;
1547 case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break;
1548 case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
1549 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
1550 case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001551 case EOpEqual:
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001552 case EOpNotEqual:
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001553 if (node->getLeft()->isScalar())
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001554 {
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001555 if (node->getOp() == EOpEqual)
1556 {
1557 outputTriplet(visit, "(", " == ", ")");
1558 }
1559 else
1560 {
1561 outputTriplet(visit, "(", " != ", ")");
1562 }
1563 }
1564 else if (node->getLeft()->getBasicType() == EbtStruct)
1565 {
1566 if (node->getOp() == EOpEqual)
1567 {
1568 out << "(";
1569 }
1570 else
1571 {
1572 out << "!(";
1573 }
1574
1575 const TTypeList *fields = node->getLeft()->getType().getStruct();
1576
1577 for (size_t i = 0; i < fields->size(); i++)
1578 {
1579 const TType *fieldType = (*fields)[i].type;
1580
1581 node->getLeft()->traverse(this);
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00001582 out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001583 node->getRight()->traverse(this);
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00001584 out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001585
1586 if (i < fields->size() - 1)
1587 {
1588 out << " && ";
1589 }
1590 }
1591
1592 out << ")";
1593
1594 return false;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001595 }
1596 else
1597 {
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001598 if (node->getLeft()->isMatrix())
1599 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001600 mUsesEqualMat[node->getLeft()->getCols()][node->getLeft()->getRows()] = true;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001601 }
1602 else if (node->getLeft()->isVector())
1603 {
1604 switch (node->getLeft()->getBasicType())
1605 {
1606 case EbtFloat:
alokp@chromium.org58e54292010-08-24 21:40:03 +00001607 switch (node->getLeft()->getNominalSize())
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001608 {
1609 case 2: mUsesEqualVec2 = true; break;
1610 case 3: mUsesEqualVec3 = true; break;
1611 case 4: mUsesEqualVec4 = true; break;
1612 default: UNREACHABLE();
1613 }
1614 break;
1615 case EbtInt:
alokp@chromium.org58e54292010-08-24 21:40:03 +00001616 switch (node->getLeft()->getNominalSize())
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001617 {
1618 case 2: mUsesEqualIVec2 = true; break;
1619 case 3: mUsesEqualIVec3 = true; break;
1620 case 4: mUsesEqualIVec4 = true; break;
1621 default: UNREACHABLE();
1622 }
1623 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001624 case EbtUInt:
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00001625 switch (node->getLeft()->getNominalSize())
1626 {
1627 case 2: mUsesEqualUVec2 = true; break;
1628 case 3: mUsesEqualUVec3 = true; break;
1629 case 4: mUsesEqualUVec4 = true; break;
1630 default: UNREACHABLE();
1631 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001632 break;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001633 case EbtBool:
alokp@chromium.org58e54292010-08-24 21:40:03 +00001634 switch (node->getLeft()->getNominalSize())
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001635 {
1636 case 2: mUsesEqualBVec2 = true; break;
1637 case 3: mUsesEqualBVec3 = true; break;
1638 case 4: mUsesEqualBVec4 = true; break;
1639 default: UNREACHABLE();
1640 }
1641 break;
1642 default: UNREACHABLE();
1643 }
1644 }
1645 else UNREACHABLE();
1646
1647 if (node->getOp() == EOpEqual)
1648 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001649 outputTriplet(visit, "equal(", ", ", ")");
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001650 }
1651 else
1652 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001653 outputTriplet(visit, "!equal(", ", ", ")");
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001654 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +00001655 }
1656 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001657 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
1658 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
1659 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
1660 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
1661 case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +00001662 case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +00001663 case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
1664 case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
daniel@transgaming.com69f084b2010-04-23 18:34:46 +00001665 case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001666 case EOpLogicalOr:
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00001667 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001668 return false;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00001669 case EOpLogicalXor:
1670 mUsesXor = true;
1671 outputTriplet(visit, "xor(", ", ", ")");
1672 break;
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001673 case EOpLogicalAnd:
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00001674 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
daniel@transgaming.com8915eba2012-04-28 00:34:44 +00001675 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001676 default: UNREACHABLE();
1677 }
1678
1679 return true;
1680}
1681
1682bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
1683{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684 switch (node->getOp())
1685 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001686 case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
1687 case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
1688 case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
1689 case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
1690 case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
1691 case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
1692 case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001693 case EOpConvIntToBool:
Nicolas Capensab60b932013-06-05 10:31:21 -04001694 case EOpConvUIntToBool:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001695 case EOpConvFloatToBool:
1696 switch (node->getOperand()->getType().getNominalSize())
1697 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001698 case 1: outputTriplet(visit, "bool(", "", ")"); break;
1699 case 2: outputTriplet(visit, "bool2(", "", ")"); break;
1700 case 3: outputTriplet(visit, "bool3(", "", ")"); break;
1701 case 4: outputTriplet(visit, "bool4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001702 default: UNREACHABLE();
1703 }
1704 break;
1705 case EOpConvBoolToFloat:
1706 case EOpConvIntToFloat:
Nicolas Capensab60b932013-06-05 10:31:21 -04001707 case EOpConvUIntToFloat:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001708 switch (node->getOperand()->getType().getNominalSize())
1709 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001710 case 1: outputTriplet(visit, "float(", "", ")"); break;
1711 case 2: outputTriplet(visit, "float2(", "", ")"); break;
1712 case 3: outputTriplet(visit, "float3(", "", ")"); break;
1713 case 4: outputTriplet(visit, "float4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001714 default: UNREACHABLE();
1715 }
1716 break;
1717 case EOpConvFloatToInt:
1718 case EOpConvBoolToInt:
Nicolas Capensab60b932013-06-05 10:31:21 -04001719 case EOpConvUIntToInt:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001720 switch (node->getOperand()->getType().getNominalSize())
1721 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001722 case 1: outputTriplet(visit, "int(", "", ")"); break;
1723 case 2: outputTriplet(visit, "int2(", "", ")"); break;
1724 case 3: outputTriplet(visit, "int3(", "", ")"); break;
1725 case 4: outputTriplet(visit, "int4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001726 default: UNREACHABLE();
1727 }
1728 break;
Nicolas Capensab60b932013-06-05 10:31:21 -04001729 case EOpConvFloatToUInt:
1730 case EOpConvBoolToUInt:
1731 case EOpConvIntToUInt:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001732 switch (node->getOperand()->getType().getCols())
1733 {
1734 case 1: outputTriplet(visit, "uint(", "", ")"); break;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00001735 case 2: outputTriplet(visit, "uint2(", "", ")"); break;
1736 case 3: outputTriplet(visit, "uint3(", "", ")"); break;
1737 case 4: outputTriplet(visit, "uint4(", "", ")"); break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001738 default: UNREACHABLE();
1739 }
1740 break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001741 case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break;
1742 case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break;
1743 case EOpSin: outputTriplet(visit, "sin(", "", ")"); break;
1744 case EOpCos: outputTriplet(visit, "cos(", "", ")"); break;
1745 case EOpTan: outputTriplet(visit, "tan(", "", ")"); break;
1746 case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
1747 case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
1748 case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
1749 case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
1750 case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
1751 case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
1752 case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break;
1753 case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break;
1754 case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break;
1755 case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break;
1756 case EOpSign: outputTriplet(visit, "sign(", "", ")"); break;
1757 case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break;
1758 case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
1759 case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
1760 case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
1761 case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
daniel@transgaming.comddbb45d2012-05-31 01:21:41 +00001762 case EOpDFdx:
1763 if(mInsideDiscontinuousLoop || mOutputLod0Function)
1764 {
1765 outputTriplet(visit, "(", "", ", 0.0)");
1766 }
1767 else
1768 {
1769 outputTriplet(visit, "ddx(", "", ")");
1770 }
1771 break;
1772 case EOpDFdy:
1773 if(mInsideDiscontinuousLoop || mOutputLod0Function)
1774 {
1775 outputTriplet(visit, "(", "", ", 0.0)");
1776 }
1777 else
1778 {
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001779 outputTriplet(visit, "ddy(", "", ")");
daniel@transgaming.comddbb45d2012-05-31 01:21:41 +00001780 }
1781 break;
1782 case EOpFwidth:
1783 if(mInsideDiscontinuousLoop || mOutputLod0Function)
1784 {
1785 outputTriplet(visit, "(", "", ", 0.0)");
1786 }
1787 else
1788 {
1789 outputTriplet(visit, "fwidth(", "", ")");
1790 }
1791 break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001792 case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
1793 case EOpAll: outputTriplet(visit, "all(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001794 default: UNREACHABLE();
1795 }
1796
1797 return true;
1798}
1799
1800bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
1801{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001802 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001803
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001804 switch (node->getOp())
1805 {
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001806 case EOpSequence:
1807 {
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001808 if (mInsideFunction)
1809 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001810 outputLineDirective(node->getLine());
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001811 out << "{\n";
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00001812
1813 mScopeDepth++;
1814
1815 if (mScopeBracket.size() < mScopeDepth)
1816 {
1817 mScopeBracket.push_back(0); // New scope level
1818 }
1819 else
1820 {
1821 mScopeBracket[mScopeDepth - 1]++; // New scope at existing level
1822 }
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001823 }
1824
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001825 for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
1826 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001827 outputLineDirective((*sit)->getLine());
1828
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00001829 traverseStatements(*sit);
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001830
1831 out << ";\n";
1832 }
1833
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001834 if (mInsideFunction)
1835 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001836 outputLineDirective(node->getEndLine());
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001837 out << "}\n";
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00001838
1839 mScopeDepth--;
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001840 }
1841
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001842 return false;
1843 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001844 case EOpDeclaration:
1845 if (visit == PreVisit)
1846 {
1847 TIntermSequence &sequence = node->getSequence();
1848 TIntermTyped *variable = sequence[0]->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001849
daniel@transgaming.comd25ab252010-03-30 03:36:26 +00001850 if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001851 {
daniel@transgaming.comead23042010-04-29 03:35:36 +00001852 if (variable->getType().getStruct())
1853 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00001854 addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
daniel@transgaming.comead23042010-04-29 03:35:36 +00001855 }
1856
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001857 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001858 {
daniel@transgaming.comd2cf25d2010-04-22 16:27:35 +00001859 if (!mInsideFunction)
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001860 {
1861 out << "static ";
1862 }
1863
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001864 out << typeString(variable->getType()) + " ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001865
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001866 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001867 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001868 TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001869
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001870 if (symbol)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001871 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001872 symbol->traverse(this);
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001873 out << arrayString(symbol->getType());
daniel@transgaming.com7127f202010-04-15 20:45:22 +00001874 out << " = " + initializer(variable->getType());
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001875 }
1876 else
1877 {
1878 (*sit)->traverse(this);
1879 }
1880
shannon.woods@transgaming.comcb332ab2013-02-28 23:12:18 +00001881 if (*sit != sequence.back())
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001882 {
shannon.woods@transgaming.comcb332ab2013-02-28 23:12:18 +00001883 out << ", ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001884 }
1885 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001886 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001887 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
1888 {
daniel@transgaming.comead23042010-04-29 03:35:36 +00001889 // Already added to constructor map
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001890 }
1891 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001892 }
shannon.woods%transgaming.com@gtempaccount.com6f273e32013-04-13 03:41:15 +00001893 else if (variable && isVaryingOut(variable->getQualifier()))
shannon.woods@transgaming.comcb332ab2013-02-28 23:12:18 +00001894 {
1895 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
1896 {
1897 TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
1898
1899 if (symbol)
1900 {
1901 // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
1902 mReferencedVaryings[symbol->getSymbol()] = symbol;
1903 }
1904 else
1905 {
1906 (*sit)->traverse(this);
1907 }
1908 }
1909 }
1910
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001911 return false;
1912 }
1913 else if (visit == InVisit)
1914 {
1915 out << ", ";
1916 }
1917 break;
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001918 case EOpPrototype:
1919 if (visit == PreVisit)
1920 {
daniel@transgaming.com0e5bb402012-10-17 18:24:53 +00001921 out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001922
1923 TIntermSequence &arguments = node->getSequence();
1924
1925 for (unsigned int i = 0; i < arguments.size(); i++)
1926 {
1927 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
1928
1929 if (symbol)
1930 {
1931 out << argumentString(symbol);
1932
1933 if (i < arguments.size() - 1)
1934 {
1935 out << ", ";
1936 }
1937 }
1938 else UNREACHABLE();
1939 }
1940
1941 out << ");\n";
1942
daniel@transgaming.com0e5bb402012-10-17 18:24:53 +00001943 // Also prototype the Lod0 variant if needed
1944 if (mContainsLoopDiscontinuity && !mOutputLod0Function)
1945 {
1946 mOutputLod0Function = true;
1947 node->traverse(this);
1948 mOutputLod0Function = false;
1949 }
1950
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001951 return false;
1952 }
1953 break;
daniel@transgaming.comed2180d2012-03-26 17:08:54 +00001954 case EOpComma: outputTriplet(visit, "(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001955 case EOpFunction:
1956 {
alokp@chromium.org43884872010-03-30 00:08:52 +00001957 TString name = TFunction::unmangleName(node->getName());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001958
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00001959 out << typeString(node->getType()) << " ";
1960
1961 if (name == "main")
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001962 {
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00001963 out << "gl_main(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001964 }
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00001965 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001966 {
daniel@transgaming.com89431aa2012-05-31 01:20:29 +00001967 out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00001968 }
daniel@transgaming.com63691862010-04-29 03:32:42 +00001969
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00001970 TIntermSequence &sequence = node->getSequence();
1971 TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
1972
1973 for (unsigned int i = 0; i < arguments.size(); i++)
1974 {
1975 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
1976
1977 if (symbol)
1978 {
1979 if (symbol->getType().getStruct())
1980 {
1981 addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
1982 }
1983
1984 out << argumentString(symbol);
1985
1986 if (i < arguments.size() - 1)
1987 {
1988 out << ", ";
1989 }
1990 }
1991 else UNREACHABLE();
1992 }
1993
1994 out << ")\n"
1995 "{\n";
1996
1997 if (sequence.size() > 1)
1998 {
1999 mInsideFunction = true;
2000 sequence[1]->traverse(this);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00002001 mInsideFunction = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002002 }
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002003
2004 out << "}\n";
2005
daniel@transgaming.com89431aa2012-05-31 01:20:29 +00002006 if (mContainsLoopDiscontinuity && !mOutputLod0Function)
2007 {
daniel@transgaming.comecdf44a2012-06-01 01:45:15 +00002008 if (name != "main")
daniel@transgaming.com89431aa2012-05-31 01:20:29 +00002009 {
2010 mOutputLod0Function = true;
2011 node->traverse(this);
2012 mOutputLod0Function = false;
2013 }
2014 }
2015
daniel@transgaming.com0e9704b2012-05-31 01:20:13 +00002016 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002017 }
2018 break;
2019 case EOpFunctionCall:
2020 {
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002021 TString name = TFunction::unmangleName(node->getName());
2022 bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
shannonwoods@chromium.orgc6ac65f2013-05-30 00:02:50 +00002023 TIntermSequence &arguments = node->getSequence();
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002024
2025 if (node->isUserDefined())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002026 {
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002027 out << decorate(name) << (lod0 ? "Lod0(" : "(");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002028 }
2029 else
2030 {
shannonwoods@chromium.orgc6ac65f2013-05-30 00:02:50 +00002031 TBasicType samplerType = arguments[0]->getAsTyped()->getType().getBasicType();
2032
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002033 TextureFunction textureFunction;
2034 textureFunction.sampler = samplerType;
2035 textureFunction.coords = arguments[1]->getAsTyped()->getNominalSize();
2036 textureFunction.mipmap = TextureFunction::IMPLICIT;
2037
2038 if (name == "texture2D" || name == "textureCube" || name == "texture")
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002039 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002040 textureFunction.mipmap = TextureFunction::IMPLICIT;
2041 textureFunction.proj = false;
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002042 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002043 else if (name == "texture2DProj" || name == "textureProj")
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002044 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002045 textureFunction.mipmap = TextureFunction::IMPLICIT;
2046 textureFunction.proj = true;
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002047 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002048 else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod")
Nicolas Capens9fe6f982013-06-24 16:05:25 -04002049 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002050 textureFunction.mipmap = TextureFunction::LOD;
2051 textureFunction.proj = false;
Nicolas Capens9fe6f982013-06-24 16:05:25 -04002052 }
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002053 else if (name == "texture2DProjLod" || name == "textureProjLod")
Nicolas Capens9fe6f982013-06-24 16:05:25 -04002054 {
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002055 textureFunction.mipmap = TextureFunction::LOD;
2056 textureFunction.proj = true;
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002057 }
2058 else UNREACHABLE();
Nicolas Capense0ba27a2013-06-24 16:10:52 -04002059
2060 if (textureFunction.mipmap != TextureFunction::LOD)
2061 {
2062 if (lod0 || mContext.shaderType == SH_VERTEX_SHADER)
2063 {
2064 textureFunction.mipmap = TextureFunction::LOD0;
2065 }
2066 else if (arguments.size() == 3)
2067 {
2068 textureFunction.mipmap = TextureFunction::BIAS;
2069 }
2070 }
2071
2072 mUsesTexture.insert(textureFunction);
2073
2074 out << textureFunction.name();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002075 }
shannonwoods@chromium.orgc6ac65f2013-05-30 00:02:50 +00002076
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002077 for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++)
2078 {
2079 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
2080 {
2081 out << "texture_";
2082 (*arg)->traverse(this);
2083 out << ", sampler_";
2084 }
2085
2086 (*arg)->traverse(this);
2087
2088 if (arg < arguments.end() - 1)
2089 {
2090 out << ", ";
2091 }
2092 }
2093
2094 out << ")";
2095
2096 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002097 }
2098 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002099 case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002100 case EOpConstructFloat:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002101 addConstructor(node->getType(), "vec1", &node->getSequence());
2102 outputTriplet(visit, "vec1(", "", ")");
2103 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002104 case EOpConstructVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002105 addConstructor(node->getType(), "vec2", &node->getSequence());
2106 outputTriplet(visit, "vec2(", ", ", ")");
2107 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002108 case EOpConstructVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002109 addConstructor(node->getType(), "vec3", &node->getSequence());
2110 outputTriplet(visit, "vec3(", ", ", ")");
2111 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002112 case EOpConstructVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002113 addConstructor(node->getType(), "vec4", &node->getSequence());
2114 outputTriplet(visit, "vec4(", ", ", ")");
2115 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002116 case EOpConstructBool:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002117 addConstructor(node->getType(), "bvec1", &node->getSequence());
2118 outputTriplet(visit, "bvec1(", "", ")");
2119 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002120 case EOpConstructBVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002121 addConstructor(node->getType(), "bvec2", &node->getSequence());
2122 outputTriplet(visit, "bvec2(", ", ", ")");
2123 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002124 case EOpConstructBVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002125 addConstructor(node->getType(), "bvec3", &node->getSequence());
2126 outputTriplet(visit, "bvec3(", ", ", ")");
2127 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002128 case EOpConstructBVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002129 addConstructor(node->getType(), "bvec4", &node->getSequence());
2130 outputTriplet(visit, "bvec4(", ", ", ")");
2131 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002132 case EOpConstructInt:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002133 addConstructor(node->getType(), "ivec1", &node->getSequence());
2134 outputTriplet(visit, "ivec1(", "", ")");
2135 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002136 case EOpConstructIVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002137 addConstructor(node->getType(), "ivec2", &node->getSequence());
2138 outputTriplet(visit, "ivec2(", ", ", ")");
2139 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002140 case EOpConstructIVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002141 addConstructor(node->getType(), "ivec3", &node->getSequence());
2142 outputTriplet(visit, "ivec3(", ", ", ")");
2143 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002144 case EOpConstructIVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002145 addConstructor(node->getType(), "ivec4", &node->getSequence());
2146 outputTriplet(visit, "ivec4(", ", ", ")");
2147 break;
Nicolas Capensab60b932013-06-05 10:31:21 -04002148 case EOpConstructUInt:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002149 addConstructor(node->getType(), "uvec1", &node->getSequence());
2150 outputTriplet(visit, "uvec1(", "", ")");
2151 break;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00002152 case EOpConstructUVec2:
2153 addConstructor(node->getType(), "uvec2", &node->getSequence());
2154 outputTriplet(visit, "uvec2(", ", ", ")");
2155 break;
2156 case EOpConstructUVec3:
2157 addConstructor(node->getType(), "uvec3", &node->getSequence());
2158 outputTriplet(visit, "uvec3(", ", ", ")");
2159 break;
2160 case EOpConstructUVec4:
2161 addConstructor(node->getType(), "uvec4", &node->getSequence());
2162 outputTriplet(visit, "uvec4(", ", ", ")");
2163 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002164 case EOpConstructMat2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002165 addConstructor(node->getType(), "mat2", &node->getSequence());
2166 outputTriplet(visit, "mat2(", ", ", ")");
2167 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002168 case EOpConstructMat3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002169 addConstructor(node->getType(), "mat3", &node->getSequence());
2170 outputTriplet(visit, "mat3(", ", ", ")");
2171 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002172 case EOpConstructMat4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002173 addConstructor(node->getType(), "mat4", &node->getSequence());
2174 outputTriplet(visit, "mat4(", ", ", ")");
2175 break;
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002176 case EOpConstructStruct:
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002177 addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
2178 outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002179 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002180 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
2181 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
2182 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
2183 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
2184 case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
2185 case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00002186 case EOpMod:
2187 {
daniel@transgaming.com4229f592011-11-24 22:34:04 +00002188 // We need to look at the number of components in both arguments
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002189 const int modValue = node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
2190 + node->getSequence()[1]->getAsTyped()->getNominalSize();
2191 switch (modValue)
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00002192 {
daniel@transgaming.com4229f592011-11-24 22:34:04 +00002193 case 11: mUsesMod1 = true; break;
2194 case 22: mUsesMod2v = true; break;
2195 case 21: mUsesMod2f = true; break;
2196 case 33: mUsesMod3v = true; break;
2197 case 31: mUsesMod3f = true; break;
2198 case 44: mUsesMod4v = true; break;
2199 case 41: mUsesMod4f = true; break;
daniel@transgaming.comd7c98102010-05-14 17:30:48 +00002200 default: UNREACHABLE();
2201 }
2202
2203 outputTriplet(visit, "mod(", ", ", ")");
2204 }
2205 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002206 case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002207 case EOpAtan:
daniel@transgaming.com0f189612010-05-07 13:03:36 +00002208 ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator
daniel@transgaming.com35342dc2012-02-28 02:01:22 +00002209 switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
2210 {
2211 case 1: mUsesAtan2_1 = true; break;
2212 case 2: mUsesAtan2_2 = true; break;
2213 case 3: mUsesAtan2_3 = true; break;
2214 case 4: mUsesAtan2_4 = true; break;
2215 default: UNREACHABLE();
2216 }
daniel@transgaming.com0f189612010-05-07 13:03:36 +00002217 outputTriplet(visit, "atanyx(", ", ", ")");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002218 break;
2219 case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
2220 case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
2221 case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break;
2222 case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break;
2223 case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break;
2224 case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break;
2225 case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break;
2226 case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
2227 case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00002228 case EOpFaceForward:
2229 {
alokp@chromium.org58e54292010-08-24 21:40:03 +00002230 switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00002231 {
2232 case 1: mUsesFaceforward1 = true; break;
2233 case 2: mUsesFaceforward2 = true; break;
2234 case 3: mUsesFaceforward3 = true; break;
2235 case 4: mUsesFaceforward4 = true; break;
2236 default: UNREACHABLE();
2237 }
2238
2239 outputTriplet(visit, "faceforward(", ", ", ")");
2240 }
2241 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002242 case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
2243 case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
2244 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002245 default: UNREACHABLE();
2246 }
2247
2248 return true;
2249}
2250
2251bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
2252{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002253 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002254
alokp@chromium.org60fe4072010-03-29 20:58:29 +00002255 if (node->usesTernaryOperator())
2256 {
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00002257 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
alokp@chromium.org60fe4072010-03-29 20:58:29 +00002258 }
2259 else // if/else statement
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002260 {
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00002261 mUnfoldShortCircuit->traverse(node->getCondition());
daniel@transgaming.comb5875982010-04-15 20:44:53 +00002262
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002263 out << "if(";
2264
2265 node->getCondition()->traverse(this);
2266
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002267 out << ")\n";
2268
2269 outputLineDirective(node->getLine());
2270 out << "{\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002271
daniel@transgaming.combb885322010-04-15 20:45:24 +00002272 if (node->getTrueBlock())
2273 {
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002274 traverseStatements(node->getTrueBlock());
daniel@transgaming.combb885322010-04-15 20:45:24 +00002275 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002276
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002277 outputLineDirective(node->getLine());
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002278 out << ";\n}\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002279
2280 if (node->getFalseBlock())
2281 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002282 out << "else\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002283
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002284 outputLineDirective(node->getFalseBlock()->getLine());
2285 out << "{\n";
2286
2287 outputLineDirective(node->getFalseBlock()->getLine());
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002288 traverseStatements(node->getFalseBlock());
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002289
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002290 outputLineDirective(node->getFalseBlock()->getLine());
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002291 out << ";\n}\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00002292 }
2293 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002294
2295 return false;
2296}
2297
2298void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
2299{
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00002300 writeConstantUnion(node->getType(), node->getUnionArrayPointer());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002301}
2302
2303bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
2304{
daniel@transgaming.come11100c2012-05-31 01:20:32 +00002305 bool wasDiscontinuous = mInsideDiscontinuousLoop;
2306
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +00002307 if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop)
daniel@transgaming.come11100c2012-05-31 01:20:32 +00002308 {
2309 mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
2310 }
2311
shannon.woods@transgaming.com9cbce922013-02-28 23:14:24 +00002312 if (mOutputType == SH_HLSL9_OUTPUT)
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002313 {
shannon.woods@transgaming.com9cbce922013-02-28 23:14:24 +00002314 if (handleExcessiveLoop(node))
2315 {
2316 return false;
2317 }
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002318 }
2319
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002320 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002321
alokp@chromium.org52813552010-11-16 18:36:09 +00002322 if (node->getType() == ELoopDoWhile)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002323 {
daniel@transgaming.com2a073de2012-03-09 21:56:43 +00002324 out << "{do\n";
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002325
2326 outputLineDirective(node->getLine());
2327 out << "{\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002328 }
2329 else
2330 {
daniel@transgaming.com2a073de2012-03-09 21:56:43 +00002331 out << "{for(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002332
2333 if (node->getInit())
2334 {
2335 node->getInit()->traverse(this);
2336 }
2337
2338 out << "; ";
2339
alokp@chromium.org52813552010-11-16 18:36:09 +00002340 if (node->getCondition())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002342 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002343 }
2344
2345 out << "; ";
2346
alokp@chromium.org52813552010-11-16 18:36:09 +00002347 if (node->getExpression())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002348 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002349 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002350 }
2351
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002352 out << ")\n";
2353
2354 outputLineDirective(node->getLine());
2355 out << "{\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002356 }
2357
2358 if (node->getBody())
2359 {
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002360 traverseStatements(node->getBody());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002361 }
2362
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002363 outputLineDirective(node->getLine());
daniel@transgaming.com7fb81e82011-09-23 18:20:46 +00002364 out << ";}\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002365
alokp@chromium.org52813552010-11-16 18:36:09 +00002366 if (node->getType() == ELoopDoWhile)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002367 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002368 outputLineDirective(node->getCondition()->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002369 out << "while(\n";
2370
alokp@chromium.org52813552010-11-16 18:36:09 +00002371 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002372
daniel@transgaming.com73536982012-03-21 20:45:49 +00002373 out << ");";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002374 }
2375
daniel@transgaming.com73536982012-03-21 20:45:49 +00002376 out << "}\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002377
daniel@transgaming.come11100c2012-05-31 01:20:32 +00002378 mInsideDiscontinuousLoop = wasDiscontinuous;
2379
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002380 return false;
2381}
2382
2383bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
2384{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002385 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002386
2387 switch (node->getFlowOp())
2388 {
apatrick@chromium.org05a5d8e2011-02-16 19:07:20 +00002389 case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break;
daniel@transgaming.com8c77f852012-07-11 20:37:35 +00002390 case EOpBreak:
2391 if (visit == PreVisit)
2392 {
2393 if (mExcessiveLoopIndex)
2394 {
2395 out << "{Break";
2396 mExcessiveLoopIndex->traverse(this);
2397 out << " = true; break;}\n";
2398 }
2399 else
2400 {
2401 out << "break;\n";
2402 }
2403 }
2404 break;
apatrick@chromium.org05a5d8e2011-02-16 19:07:20 +00002405 case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002406 case EOpReturn:
2407 if (visit == PreVisit)
2408 {
2409 if (node->getExpression())
2410 {
2411 out << "return ";
2412 }
2413 else
2414 {
2415 out << "return;\n";
2416 }
2417 }
2418 else if (visit == PostVisit)
2419 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002420 if (node->getExpression())
2421 {
2422 out << ";\n";
2423 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002424 }
2425 break;
2426 default: UNREACHABLE();
2427 }
2428
2429 return true;
2430}
2431
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002432void OutputHLSL::traverseStatements(TIntermNode *node)
2433{
2434 if (isSingleStatement(node))
2435 {
daniel@transgaming.comf8f8f362012-04-28 00:35:00 +00002436 mUnfoldShortCircuit->traverse(node);
daniel@transgaming.com44fffee2012-04-28 00:34:20 +00002437 }
2438
2439 node->traverse(this);
2440}
2441
daniel@transgaming.comb5875982010-04-15 20:44:53 +00002442bool OutputHLSL::isSingleStatement(TIntermNode *node)
2443{
2444 TIntermAggregate *aggregate = node->getAsAggregate();
2445
2446 if (aggregate)
2447 {
2448 if (aggregate->getOp() == EOpSequence)
2449 {
2450 return false;
2451 }
2452 else
2453 {
2454 for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
2455 {
2456 if (!isSingleStatement(*sit))
2457 {
2458 return false;
2459 }
2460 }
2461
2462 return true;
2463 }
2464 }
2465
2466 return true;
2467}
2468
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002469// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
2470// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002471bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
2472{
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002473 const int MAX_LOOP_ITERATIONS = 254;
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002474 TInfoSinkBase &out = mBody;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002475
2476 // Parse loops of the form:
2477 // for(int index = initial; index [comparator] limit; index += increment)
2478 TIntermSymbol *index = NULL;
2479 TOperator comparator = EOpNull;
2480 int initial = 0;
2481 int limit = 0;
2482 int increment = 0;
2483
2484 // Parse index name and intial value
2485 if (node->getInit())
2486 {
2487 TIntermAggregate *init = node->getInit()->getAsAggregate();
2488
2489 if (init)
2490 {
2491 TIntermSequence &sequence = init->getSequence();
2492 TIntermTyped *variable = sequence[0]->getAsTyped();
2493
2494 if (variable && variable->getQualifier() == EvqTemporary)
2495 {
2496 TIntermBinary *assign = variable->getAsBinaryNode();
2497
2498 if (assign->getOp() == EOpInitialize)
2499 {
2500 TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
2501 TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
2502
2503 if (symbol && constant)
2504 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002505 if (constant->getBasicType() == EbtInt && constant->isScalar())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002506 {
2507 index = symbol;
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002508 initial = constant->getIConst(0);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002509 }
2510 }
2511 }
2512 }
2513 }
2514 }
2515
2516 // Parse comparator and limit value
alokp@chromium.org52813552010-11-16 18:36:09 +00002517 if (index != NULL && node->getCondition())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002518 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002519 TIntermBinary *test = node->getCondition()->getAsBinaryNode();
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002520
2521 if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
2522 {
2523 TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
2524
2525 if (constant)
2526 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002527 if (constant->getBasicType() == EbtInt && constant->isScalar())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002528 {
2529 comparator = test->getOp();
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002530 limit = constant->getIConst(0);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002531 }
2532 }
2533 }
2534 }
2535
2536 // Parse increment
alokp@chromium.org52813552010-11-16 18:36:09 +00002537 if (index != NULL && comparator != EOpNull && node->getExpression())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002538 {
alokp@chromium.org52813552010-11-16 18:36:09 +00002539 TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
2540 TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002541
2542 if (binaryTerminal)
2543 {
2544 TOperator op = binaryTerminal->getOp();
2545 TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
2546
2547 if (constant)
2548 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002549 if (constant->getBasicType() == EbtInt && constant->isScalar())
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002550 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002551 int value = constant->getIConst(0);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002552
2553 switch (op)
2554 {
2555 case EOpAddAssign: increment = value; break;
2556 case EOpSubAssign: increment = -value; break;
2557 default: UNIMPLEMENTED();
2558 }
2559 }
2560 }
2561 }
2562 else if (unaryTerminal)
2563 {
2564 TOperator op = unaryTerminal->getOp();
2565
2566 switch (op)
2567 {
2568 case EOpPostIncrement: increment = 1; break;
2569 case EOpPostDecrement: increment = -1; break;
2570 case EOpPreIncrement: increment = 1; break;
2571 case EOpPreDecrement: increment = -1; break;
2572 default: UNIMPLEMENTED();
2573 }
2574 }
2575 }
2576
2577 if (index != NULL && comparator != EOpNull && increment != 0)
2578 {
2579 if (comparator == EOpLessThanEqual)
2580 {
2581 comparator = EOpLessThan;
2582 limit += 1;
2583 }
2584
2585 if (comparator == EOpLessThan)
2586 {
daniel@transgaming.comf1f538e2011-02-09 16:30:01 +00002587 int iterations = (limit - initial) / increment;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002588
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002589 if (iterations <= MAX_LOOP_ITERATIONS)
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002590 {
2591 return false; // Not an excessive loop
2592 }
2593
daniel@transgaming.come9b3f602012-07-11 20:37:31 +00002594 TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
2595 mExcessiveLoopIndex = index;
2596
daniel@transgaming.com0933b0c2012-07-11 20:37:28 +00002597 out << "{int ";
2598 index->traverse(this);
daniel@transgaming.com8c77f852012-07-11 20:37:35 +00002599 out << ";\n"
2600 "bool Break";
2601 index->traverse(this);
2602 out << " = false;\n";
daniel@transgaming.comc264de42012-07-11 20:37:25 +00002603
daniel@transgaming.com5b60f5e2012-07-11 20:37:38 +00002604 bool firstLoopFragment = true;
2605
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002606 while (iterations > 0)
2607 {
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002608 int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002609
daniel@transgaming.com5b60f5e2012-07-11 20:37:38 +00002610 if (!firstLoopFragment)
2611 {
2612 out << "if(!Break";
2613 index->traverse(this);
2614 out << ") {\n";
2615 }
daniel@transgaming.com2fe20a82012-07-11 20:37:41 +00002616
2617 if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment
2618 {
2619 mExcessiveLoopIndex = NULL; // Stops setting the Break flag
2620 }
daniel@transgaming.com8c77f852012-07-11 20:37:35 +00002621
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002622 // for(int index = initial; index < clampedLimit; index += increment)
2623
daniel@transgaming.com0933b0c2012-07-11 20:37:28 +00002624 out << "for(";
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002625 index->traverse(this);
2626 out << " = ";
2627 out << initial;
2628
2629 out << "; ";
2630 index->traverse(this);
2631 out << " < ";
2632 out << clampedLimit;
2633
2634 out << "; ";
2635 index->traverse(this);
2636 out << " += ";
2637 out << increment;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002638 out << ")\n";
2639
2640 outputLineDirective(node->getLine());
2641 out << "{\n";
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002642
2643 if (node->getBody())
2644 {
2645 node->getBody()->traverse(this);
2646 }
2647
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002648 outputLineDirective(node->getLine());
daniel@transgaming.com5b60f5e2012-07-11 20:37:38 +00002649 out << ";}\n";
2650
2651 if (!firstLoopFragment)
2652 {
2653 out << "}\n";
2654 }
2655
2656 firstLoopFragment = false;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002657
daniel@transgaming.com06eb0d42012-05-31 01:17:14 +00002658 initial += MAX_LOOP_ITERATIONS * increment;
2659 iterations -= MAX_LOOP_ITERATIONS;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002660 }
daniel@transgaming.comc264de42012-07-11 20:37:25 +00002661
2662 out << "}";
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002663
daniel@transgaming.come9b3f602012-07-11 20:37:31 +00002664 mExcessiveLoopIndex = restoreIndex;
2665
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00002666 return true;
2667 }
2668 else UNIMPLEMENTED();
2669 }
2670
2671 return false; // Not handled as an excessive loop
2672}
2673
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002674void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002675{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00002676 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002677
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002678 if (visit == PreVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002679 {
2680 out << preString;
2681 }
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002682 else if (visit == InVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002683 {
2684 out << inString;
2685 }
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002686 else if (visit == PostVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002687 {
2688 out << postString;
2689 }
2690}
2691
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002692void OutputHLSL::outputLineDirective(int line)
2693{
2694 if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
2695 {
baustin@google.com8ab69842011-06-02 21:53:45 +00002696 mBody << "\n";
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00002697 mBody << "#line " << line;
2698
2699 if (mContext.sourcePath)
2700 {
2701 mBody << " \"" << mContext.sourcePath << "\"";
2702 }
2703
2704 mBody << "\n";
2705 }
2706}
2707
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002708TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
2709{
2710 TQualifier qualifier = symbol->getQualifier();
2711 const TType &type = symbol->getType();
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002712 TString name = symbol->getSymbol();
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002713
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002714 if (name.empty()) // HLSL demands named arguments, also for prototypes
2715 {
daniel@transgaming.comb6ef8f12010-11-15 16:41:14 +00002716 name = "x" + str(mUniqueIndex++);
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002717 }
2718 else
2719 {
2720 name = decorate(name);
2721 }
2722
shannon.woods@transgaming.com01a5cf92013-02-28 23:13:51 +00002723 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
2724 {
2725 return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
2726 qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type);
2727 }
2728
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002729 return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002730}
2731
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +00002732TString OutputHLSL::interpolationString(TQualifier qualifier)
2733{
2734 switch(qualifier)
2735 {
2736 case EvqVaryingIn: return "";
2737 case EvqInvariantVaryingIn: return "";
2738 case EvqSmoothIn: return "linear";
2739 case EvqFlatIn: return "nointerpolation";
2740 case EvqCentroidIn: return "centroid";
2741 case EvqVaryingOut: return "";
2742 case EvqInvariantVaryingOut: return "";
2743 case EvqSmoothOut: return "linear";
2744 case EvqFlatOut: return "nointerpolation";
2745 case EvqCentroidOut: return "centroid";
2746 default: UNREACHABLE();
2747 }
2748
2749 return "";
2750}
2751
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00002752TString OutputHLSL::qualifierString(TQualifier qualifier)
2753{
2754 switch(qualifier)
2755 {
2756 case EvqIn: return "in";
2757 case EvqOut: return "out";
2758 case EvqInOut: return "inout";
2759 case EvqConstReadOnly: return "const";
2760 default: UNREACHABLE();
2761 }
2762
2763 return "";
2764}
2765
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002766TString OutputHLSL::typeString(const TType &type)
2767{
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002768 if (type.getBasicType() == EbtStruct)
2769 {
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002770 if (type.getTypeName() != "")
2771 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002772 return structLookup(type.getTypeName());
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002773 }
daniel@transgaming.com6b998402010-05-04 03:35:07 +00002774 else // Nameless structure, define in place
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002775 {
Jamie Madill9cf6c072013-06-20 11:55:53 -04002776 return structureString(type, false);
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002777 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00002778 }
2779 else if (type.isMatrix())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002780 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00002781 int cols = type.getCols();
2782 int rows = type.getRows();
2783 return "float" + str(cols) + "x" + str(rows);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002784 }
2785 else
2786 {
2787 switch (type.getBasicType())
2788 {
2789 case EbtFloat:
2790 switch (type.getNominalSize())
2791 {
2792 case 1: return "float";
2793 case 2: return "float2";
2794 case 3: return "float3";
2795 case 4: return "float4";
2796 }
2797 case EbtInt:
2798 switch (type.getNominalSize())
2799 {
2800 case 1: return "int";
2801 case 2: return "int2";
2802 case 3: return "int3";
2803 case 4: return "int4";
2804 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002805 case EbtUInt:
Jamie Madill22d63da2013-06-07 12:45:12 -04002806 switch (type.getNominalSize())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002807 {
2808 case 1: return "uint";
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00002809 case 2: return "uint2";
2810 case 3: return "uint3";
2811 case 4: return "uint4";
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00002812 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002813 case EbtBool:
2814 switch (type.getNominalSize())
2815 {
2816 case 1: return "bool";
2817 case 2: return "bool2";
2818 case 3: return "bool3";
2819 case 4: return "bool4";
2820 }
2821 case EbtVoid:
2822 return "void";
2823 case EbtSampler2D:
Nicolas Capens1f1a8332013-06-24 15:42:27 -04002824 case EbtISampler2D:
Nicolas Capens075368e2013-06-24 15:58:30 -04002825 case EbtUSampler2D:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002826 return "sampler2D";
2827 case EbtSamplerCube:
Nicolas Capens1f1a8332013-06-24 15:42:27 -04002828 case EbtISamplerCube:
Nicolas Capens075368e2013-06-24 15:58:30 -04002829 case EbtUSamplerCube:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002830 return "samplerCUBE";
apatrick@chromium.org65756022012-01-17 21:45:38 +00002831 case EbtSamplerExternalOES:
2832 return "sampler2D";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002833 default:
2834 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002835 }
2836 }
2837
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00002838 UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002839 return "<unknown type>";
2840}
2841
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00002842TString OutputHLSL::textureString(const TType &type)
2843{
2844 switch (type.getBasicType())
2845 {
2846 case EbtSampler2D:
2847 return "Texture2D";
2848 case EbtSamplerCube:
2849 return "TextureCube";
2850 case EbtSamplerExternalOES:
2851 return "Texture2D";
Nicolas Capens1f1a8332013-06-24 15:42:27 -04002852 case EbtISampler2D:
2853 return "Texture2D<int4>";
2854 case EbtISamplerCube:
2855 return "TextureCube<int4>";
Nicolas Capens075368e2013-06-24 15:58:30 -04002856 case EbtUSampler2D:
2857 return "Texture2D<uint4>";
2858 case EbtUSamplerCube:
2859 return "TextureCube<uint4>";
shannon.woods@transgaming.comfb256be2013-01-25 21:49:25 +00002860 default:
2861 break;
2862 }
2863
2864 UNREACHABLE();
2865 return "<unknown texture type>";
2866}
2867
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002868TString OutputHLSL::arrayString(const TType &type)
2869{
2870 if (!type.isArray())
2871 {
2872 return "";
2873 }
2874
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002875 return "[" + str(type.getArraySize()) + "]";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002876}
2877
2878TString OutputHLSL::initializer(const TType &type)
2879{
2880 TString string;
2881
daniel@transgaming.comead23042010-04-29 03:35:36 +00002882 for (int component = 0; component < type.getObjectSize(); component++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002883 {
daniel@transgaming.comead23042010-04-29 03:35:36 +00002884 string += "0";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002885
daniel@transgaming.comead23042010-04-29 03:35:36 +00002886 if (component < type.getObjectSize() - 1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002887 {
2888 string += ", ";
2889 }
2890 }
2891
daniel@transgaming.comead23042010-04-29 03:35:36 +00002892 return "{" + string + "}";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002893}
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002894
Jamie Madill9cf6c072013-06-20 11:55:53 -04002895TString OutputHLSL::structureString(const TType &structType, bool useHLSLRowMajorPacking)
2896{
2897 ASSERT(structType.getStruct());
2898
2899 const TTypeList &fields = *structType.getStruct();
2900 const bool isNameless = (structType.getTypeName() == "");
2901 const TString &structName = structureTypeName(structType, useHLSLRowMajorPacking);
2902
2903 const TString declareString = (isNameless ? "struct" : "struct " + structName);
2904
2905 TString structure;
2906 structure += declareString + "\n"
2907 "{\n";
2908
2909 for (unsigned int i = 0; i < fields.size(); i++)
2910 {
2911 const TType &field = *fields[i].type;
2912
2913 structure += " " + structureTypeName(field, useHLSLRowMajorPacking) + " " +
2914 decorateField(field.getFieldName(), structType) + arrayString(field) + ";\n";
2915 }
2916
2917 // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
2918 structure += (isNameless ? "} " : "};\n");
2919
2920 return structure;
2921}
2922
2923TString OutputHLSL::structureTypeName(const TType &structType, bool useHLSLRowMajorPacking)
2924{
2925 if (structType.getBasicType() != EbtStruct)
2926 {
2927 return typeString(structType);
2928 }
2929
2930 if (structType.getTypeName() == "")
2931 {
2932 return "";
2933 }
2934
2935 TString prefix = "";
2936
2937 // Structs packed with row-major matrices in HLSL are prefixed with "rm"
2938 // GLSL column-major maps to HLSL row-major, and the converse is true
2939 if (useHLSLRowMajorPacking)
2940 {
2941 prefix += "rm";
2942 }
2943
2944 return prefix + typeString(structType);
2945}
2946
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002947void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
daniel@transgaming.com63691862010-04-29 03:32:42 +00002948{
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002949 if (name == "")
2950 {
daniel@transgaming.com6b998402010-05-04 03:35:07 +00002951 return; // Nameless structures don't have constructors
daniel@transgaming.coma637e552010-04-29 03:39:08 +00002952 }
2953
daniel@transgaming.com43eecdc2012-03-20 20:10:33 +00002954 if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end())
2955 {
2956 return; // Already added
2957 }
2958
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002959 TType ctorType = type;
2960 ctorType.clearArrayness();
alokp@chromium.org58e54292010-08-24 21:40:03 +00002961 ctorType.setPrecision(EbpHigh);
2962 ctorType.setQualifier(EvqTemporary);
daniel@transgaming.com63691862010-04-29 03:32:42 +00002963
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002964 TString ctorName = type.getStruct() ? decorate(name) : name;
2965
2966 typedef std::vector<TType> ParameterArray;
2967 ParameterArray ctorParameters;
daniel@transgaming.com63691862010-04-29 03:32:42 +00002968
daniel@transgaming.com55d48c72011-09-26 18:24:36 +00002969 if (type.getStruct())
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002970 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002971 mStructNames.insert(decorate(name));
2972
Jamie Madill9cf6c072013-06-20 11:55:53 -04002973 const TString &structure = structureString(type, false);
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002974
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002975 if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002976 {
Jamie Madill9cf6c072013-06-20 11:55:53 -04002977 // Add row-major packed struct for interface blocks
2978 TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
2979 structureString(type, true) +
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002980 "#pragma pack_matrix(column_major)\n";
2981
Jamie Madill9cf6c072013-06-20 11:55:53 -04002982 mStructDeclarations.push_back(structure);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002983 mStructDeclarations.push_back(rowMajorString);
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002984 }
2985
Jamie Madill9cf6c072013-06-20 11:55:53 -04002986 const TTypeList &fields = *type.getStruct();
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00002987 for (unsigned int i = 0; i < fields.size(); i++)
2988 {
2989 ctorParameters.push_back(*fields[i].type);
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002990 }
2991 }
daniel@transgaming.com55d48c72011-09-26 18:24:36 +00002992 else if (parameters)
2993 {
2994 for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
2995 {
2996 ctorParameters.push_back((*parameter)->getAsTyped()->getType());
2997 }
2998 }
daniel@transgaming.com7a7003c2010-04-29 03:35:33 +00002999 else UNREACHABLE();
daniel@transgaming.com63691862010-04-29 03:32:42 +00003000
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003001 TString constructor;
3002
3003 if (ctorType.getStruct())
3004 {
3005 constructor += ctorName + " " + ctorName + "_ctor(";
3006 }
3007 else // Built-in type
3008 {
3009 constructor += typeString(ctorType) + " " + ctorName + "(";
3010 }
3011
3012 for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
3013 {
3014 const TType &type = ctorParameters[parameter];
3015
3016 constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
3017
3018 if (parameter < ctorParameters.size() - 1)
3019 {
3020 constructor += ", ";
3021 }
3022 }
3023
3024 constructor += ")\n"
3025 "{\n";
3026
3027 if (ctorType.getStruct())
3028 {
3029 constructor += " " + ctorName + " structure = {";
3030 }
3031 else
3032 {
3033 constructor += " return " + typeString(ctorType) + "(";
3034 }
3035
3036 if (ctorType.isMatrix() && ctorParameters.size() == 1)
3037 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003038 int rows = ctorType.getRows();
3039 int cols = ctorType.getCols();
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003040 const TType &parameter = ctorParameters[0];
3041
3042 if (parameter.isScalar())
3043 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003044 for (int row = 0; row < rows; row++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003045 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003046 for (int col = 0; col < cols; col++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003047 {
3048 constructor += TString((row == col) ? "x0" : "0.0");
3049
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003050 if (row < rows - 1 || col < cols - 1)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003051 {
3052 constructor += ", ";
3053 }
3054 }
3055 }
3056 }
3057 else if (parameter.isMatrix())
3058 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003059 for (int row = 0; row < rows; row++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003060 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003061 for (int col = 0; col < cols; col++)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003062 {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003063 if (row < parameter.getRows() && col < parameter.getCols())
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003064 {
3065 constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
3066 }
3067 else
3068 {
3069 constructor += TString((row == col) ? "1.0" : "0.0");
3070 }
3071
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003072 if (row < rows - 1 || col < cols - 1)
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003073 {
3074 constructor += ", ";
3075 }
3076 }
3077 }
3078 }
3079 else UNREACHABLE();
3080 }
3081 else
3082 {
3083 int remainingComponents = ctorType.getObjectSize();
3084 int parameterIndex = 0;
3085
3086 while (remainingComponents > 0)
3087 {
3088 const TType &parameter = ctorParameters[parameterIndex];
3089 bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
3090
3091 constructor += "x" + str(parameterIndex);
3092
3093 if (parameter.isScalar())
3094 {
3095 remainingComponents -= parameter.getObjectSize();
3096 }
3097 else if (parameter.isVector())
3098 {
3099 if (remainingComponents == parameter.getObjectSize() || moreParameters)
3100 {
3101 remainingComponents -= parameter.getObjectSize();
3102 }
Jamie Madilla9f52472013-06-06 11:56:43 -04003103 else if (remainingComponents < parameter.getNominalSize())
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003104 {
3105 switch (remainingComponents)
3106 {
3107 case 1: constructor += ".x"; break;
3108 case 2: constructor += ".xy"; break;
3109 case 3: constructor += ".xyz"; break;
3110 case 4: constructor += ".xyzw"; break;
3111 default: UNREACHABLE();
3112 }
3113
3114 remainingComponents = 0;
3115 }
3116 else UNREACHABLE();
3117 }
3118 else if (parameter.isMatrix() || parameter.getStruct())
3119 {
3120 ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
3121
3122 remainingComponents -= parameter.getObjectSize();
3123 }
3124 else UNREACHABLE();
3125
3126 if (moreParameters)
3127 {
3128 parameterIndex++;
3129 }
3130
3131 if (remainingComponents)
3132 {
3133 constructor += ", ";
3134 }
3135 }
3136 }
3137
3138 if (ctorType.getStruct())
3139 {
3140 constructor += "};\n"
3141 " return structure;\n"
3142 "}\n";
3143 }
3144 else
3145 {
3146 constructor += ");\n"
3147 "}\n";
3148 }
3149
daniel@transgaming.com63691862010-04-29 03:32:42 +00003150 mConstructors.insert(constructor);
3151}
3152
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003153const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
3154{
3155 TInfoSinkBase &out = mBody;
3156
3157 if (type.getBasicType() == EbtStruct)
3158 {
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003159 out << structLookup(type.getTypeName()) + "_ctor(";
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003160
3161 const TTypeList *structure = type.getStruct();
3162
3163 for (size_t i = 0; i < structure->size(); i++)
3164 {
3165 const TType *fieldType = (*structure)[i].type;
3166
3167 constUnion = writeConstantUnion(*fieldType, constUnion);
3168
3169 if (i != structure->size() - 1)
3170 {
3171 out << ", ";
3172 }
3173 }
3174
3175 out << ")";
3176 }
3177 else
3178 {
3179 int size = type.getObjectSize();
3180 bool writeType = size > 1;
3181
3182 if (writeType)
3183 {
3184 out << typeString(type) << "(";
3185 }
3186
3187 for (int i = 0; i < size; i++, constUnion++)
3188 {
3189 switch (constUnion->getType())
3190 {
daniel@transgaming.com6c1203f2013-01-11 04:12:43 +00003191 case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break;
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003192 case EbtInt: out << constUnion->getIConst(); break;
Nicolas Capensc0f7c612013-06-05 11:46:09 -04003193 case EbtUInt: out << constUnion->getUConst(); break;
alokp@chromium.org4e4facd2010-06-02 15:21:22 +00003194 case EbtBool: out << constUnion->getBConst(); break;
daniel@transgaming.coma54da4e2010-05-07 13:03:28 +00003195 default: UNREACHABLE();
3196 }
3197
3198 if (i != size - 1)
3199 {
3200 out << ", ";
3201 }
3202 }
3203
3204 if (writeType)
3205 {
3206 out << ")";
3207 }
3208 }
3209
3210 return constUnion;
3211}
3212
daniel@transgaming.coma2a95e72010-05-20 19:17:55 +00003213TString OutputHLSL::scopeString(unsigned int depthLimit)
3214{
3215 TString string;
3216
3217 for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
3218 {
3219 string += "_" + str(i);
3220 }
3221
3222 return string;
3223}
3224
3225TString OutputHLSL::scopedStruct(const TString &typeName)
3226{
3227 if (typeName == "")
3228 {
3229 return typeName;
3230 }
3231
3232 return typeName + scopeString(mScopeDepth);
3233}
3234
3235TString OutputHLSL::structLookup(const TString &typeName)
3236{
3237 for (int depth = mScopeDepth; depth >= 0; depth--)
3238 {
3239 TString scopedName = decorate(typeName + scopeString(depth));
3240
3241 for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
3242 {
3243 if (*structName == scopedName)
3244 {
3245 return scopedName;
3246 }
3247 }
3248 }
3249
3250 UNREACHABLE(); // Should have found a matching constructor
3251
3252 return typeName;
3253}
3254
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003255TString OutputHLSL::decorate(const TString &string)
3256{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00003257 if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003258 {
3259 return "_" + string;
3260 }
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00003261
3262 return string;
3263}
3264
apatrick@chromium.org65756022012-01-17 21:45:38 +00003265TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00003266{
daniel@transgaming.comdb019952012-12-20 21:13:32 +00003267 if (type.getBasicType() == EbtSamplerExternalOES)
apatrick@chromium.org65756022012-01-17 21:45:38 +00003268 {
3269 return "ex_" + string;
3270 }
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00003271
3272 return decorate(string);
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00003273}
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00003274
3275TString OutputHLSL::decorateField(const TString &string, const TType &structure)
3276{
3277 if (structure.getTypeName().compare(0, 3, "gl_") != 0)
3278 {
3279 return decorate(string);
3280 }
3281
3282 return string;
3283}
daniel@transgaming.com652468c2012-12-20 21:11:57 +00003284
3285TString OutputHLSL::registerString(TIntermSymbol *operand)
3286{
3287 ASSERT(operand->getQualifier() == EvqUniform);
3288
3289 if (IsSampler(operand->getBasicType()))
3290 {
3291 return "s" + str(samplerRegister(operand));
3292 }
3293
3294 return "c" + str(uniformRegister(operand));
3295}
3296
3297int OutputHLSL::samplerRegister(TIntermSymbol *sampler)
3298{
3299 const TType &type = sampler->getType();
3300 ASSERT(IsSampler(type.getBasicType()));
3301
3302 int index = mSamplerRegister;
3303 mSamplerRegister += sampler->totalRegisterCount();
3304
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003305 declareUniform(type, sampler->getSymbol(), index);
3306
daniel@transgaming.com652468c2012-12-20 21:11:57 +00003307 return index;
3308}
3309
3310int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
3311{
3312 const TType &type = uniform->getType();
3313 ASSERT(!IsSampler(type.getBasicType()));
3314
3315 int index = mUniformRegister;
3316 mUniformRegister += uniform->totalRegisterCount();
3317
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003318 declareUniform(type, uniform->getSymbol(), index);
3319
daniel@transgaming.com652468c2012-12-20 21:11:57 +00003320 return index;
3321}
3322
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003323void OutputHLSL::declareUniformToList(const TType &type, const TString &name, int index, ActiveUniforms& output)
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003324{
3325 const TTypeList *structure = type.getStruct();
3326
3327 if (!structure)
3328 {
Jamie Madill010fffa2013-06-20 11:55:53 -04003329 const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
3330 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 +00003331 }
3332 else
3333 {
Jamie Madill010fffa2013-06-20 11:55:53 -04003334 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 +00003335
3336 int fieldIndex = index;
3337
3338 for (size_t i = 0; i < structure->size(); i++)
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003339 {
Jamie Madill010fffa2013-06-20 11:55:53 -04003340 TType fieldType = *(*structure)[i].type;
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003341 const TString &fieldName = fieldType.getFieldName();
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003342
Jamie Madill010fffa2013-06-20 11:55:53 -04003343 // make sure to copy matrix packing information
3344 fieldType.setLayoutQualifier(type.getLayoutQualifier());
3345
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003346 declareUniformToList(fieldType, fieldName, fieldIndex, structUniform.fields);
3347 fieldIndex += fieldType.totalRegisterCount();
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003348 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003349
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003350 output.push_back(structUniform);
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003351 }
3352}
3353
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00003354void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
3355{
3356 declareUniformToList(type, name, index, mActiveUniforms);
3357}
3358
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003359GLenum OutputHLSL::glVariableType(const TType &type)
3360{
3361 if (type.getBasicType() == EbtFloat)
3362 {
3363 if (type.isScalar())
3364 {
3365 return GL_FLOAT;
3366 }
3367 else if (type.isVector())
3368 {
3369 switch(type.getNominalSize())
3370 {
3371 case 2: return GL_FLOAT_VEC2;
3372 case 3: return GL_FLOAT_VEC3;
3373 case 4: return GL_FLOAT_VEC4;
3374 default: UNREACHABLE();
3375 }
3376 }
3377 else if (type.isMatrix())
3378 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00003379 switch (type.getCols())
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003380 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00003381 case 2:
3382 switch(type.getRows())
3383 {
3384 case 2: return GL_FLOAT_MAT2;
3385 case 3: return GL_FLOAT_MAT2x3;
3386 case 4: return GL_FLOAT_MAT2x4;
3387 default: UNREACHABLE();
3388 }
3389
3390 case 3:
3391 switch(type.getRows())
3392 {
3393 case 2: return GL_FLOAT_MAT3x2;
3394 case 3: return GL_FLOAT_MAT3;
3395 case 4: return GL_FLOAT_MAT3x4;
3396 default: UNREACHABLE();
3397 }
3398
3399 case 4:
3400 switch(type.getRows())
3401 {
3402 case 2: return GL_FLOAT_MAT4x2;
3403 case 3: return GL_FLOAT_MAT4x3;
3404 case 4: return GL_FLOAT_MAT4;
3405 default: UNREACHABLE();
3406 }
3407
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003408 default: UNREACHABLE();
3409 }
3410 }
3411 else UNREACHABLE();
3412 }
3413 else if (type.getBasicType() == EbtInt)
3414 {
3415 if (type.isScalar())
3416 {
3417 return GL_INT;
3418 }
3419 else if (type.isVector())
3420 {
3421 switch(type.getNominalSize())
3422 {
3423 case 2: return GL_INT_VEC2;
3424 case 3: return GL_INT_VEC3;
3425 case 4: return GL_INT_VEC4;
3426 default: UNREACHABLE();
3427 }
3428 }
3429 else UNREACHABLE();
3430 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00003431 else if (type.getBasicType() == EbtUInt)
3432 {
3433 if (type.isScalar())
3434 {
3435 return GL_UNSIGNED_INT;
3436 }
3437 else if (type.isVector())
3438 {
Jamie Madill22d63da2013-06-07 12:45:12 -04003439 switch(type.getNominalSize())
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +00003440 {
3441 case 2: return GL_UNSIGNED_INT_VEC2;
3442 case 3: return GL_UNSIGNED_INT_VEC3;
3443 case 4: return GL_UNSIGNED_INT_VEC4;
3444 default: UNREACHABLE();
3445 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00003446 }
3447 else UNREACHABLE();
3448 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003449 else if (type.getBasicType() == EbtBool)
3450 {
3451 if (type.isScalar())
3452 {
3453 return GL_BOOL;
3454 }
3455 else if (type.isVector())
3456 {
3457 switch(type.getNominalSize())
3458 {
3459 case 2: return GL_BOOL_VEC2;
3460 case 3: return GL_BOOL_VEC3;
3461 case 4: return GL_BOOL_VEC4;
3462 default: UNREACHABLE();
3463 }
3464 }
3465 else UNREACHABLE();
3466 }
3467 else if (type.getBasicType() == EbtSampler2D)
3468 {
3469 return GL_SAMPLER_2D;
3470 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04003471 else if (type.getBasicType() == EbtSampler3D)
3472 {
3473 return GL_SAMPLER_3D;
3474 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003475 else if (type.getBasicType() == EbtSamplerCube)
3476 {
3477 return GL_SAMPLER_CUBE;
3478 }
Nicolas Capens1f1a8332013-06-24 15:42:27 -04003479 else if (type.getBasicType() == EbtISampler2D)
3480 {
3481 return GL_INT_SAMPLER_2D;
3482 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04003483 else if (type.getBasicType() == EbtISampler3D)
3484 {
3485 return GL_INT_SAMPLER_3D;
3486 }
Nicolas Capens1f1a8332013-06-24 15:42:27 -04003487 else if (type.getBasicType() == EbtISamplerCube)
3488 {
3489 return GL_INT_SAMPLER_CUBE;
3490 }
Nicolas Capens075368e2013-06-24 15:58:30 -04003491 else if (type.getBasicType() == EbtUSampler2D)
3492 {
3493 return GL_UNSIGNED_INT_SAMPLER_2D;
3494 }
Nicolas Capens9fe6f982013-06-24 16:05:25 -04003495 else if (type.getBasicType() == EbtUSampler3D)
3496 {
3497 return GL_UNSIGNED_INT_SAMPLER_3D;
3498 }
Nicolas Capens075368e2013-06-24 15:58:30 -04003499 else if (type.getBasicType() == EbtUSamplerCube)
3500 {
3501 return GL_UNSIGNED_INT_SAMPLER_CUBE;
3502 }
daniel@transgaming.comf4d9fef2012-12-20 21:12:13 +00003503 else UNREACHABLE();
3504
3505 return GL_NONE;
3506}
3507
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003508GLenum OutputHLSL::glVariablePrecision(const TType &type)
3509{
3510 if (type.getBasicType() == EbtFloat)
3511 {
3512 switch (type.getPrecision())
3513 {
3514 case EbpHigh: return GL_HIGH_FLOAT;
3515 case EbpMedium: return GL_MEDIUM_FLOAT;
3516 case EbpLow: return GL_LOW_FLOAT;
3517 case EbpUndefined:
3518 // Should be defined as the default precision by the parser
3519 default: UNREACHABLE();
3520 }
3521 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00003522 else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003523 {
3524 switch (type.getPrecision())
3525 {
3526 case EbpHigh: return GL_HIGH_INT;
3527 case EbpMedium: return GL_MEDIUM_INT;
3528 case EbpLow: return GL_LOW_INT;
3529 case EbpUndefined:
3530 // Should be defined as the default precision by the parser
3531 default: UNREACHABLE();
3532 }
3533 }
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003534
shannon.woods@transgaming.com10aadb22013-02-28 23:17:52 +00003535 // Other types (boolean, sampler) don't have a precision
shannon.woods@transgaming.comfe3c0ef2013-02-28 23:17:22 +00003536 return GL_NONE;
3537}
3538
shannon.woods%transgaming.com@gtempaccount.com6f273e32013-04-13 03:41:15 +00003539bool OutputHLSL::isVaryingOut(TQualifier qualifier)
3540{
3541 switch(qualifier)
3542 {
3543 case EvqVaryingOut:
3544 case EvqInvariantVaryingOut:
3545 case EvqSmoothOut:
3546 case EvqFlatOut:
3547 case EvqCentroidOut:
3548 return true;
3549 }
3550
3551 return false;
3552}
3553
3554bool OutputHLSL::isVaryingIn(TQualifier qualifier)
3555{
3556 switch(qualifier)
3557 {
3558 case EvqVaryingIn:
3559 case EvqInvariantVaryingIn:
3560 case EvqSmoothIn:
3561 case EvqFlatIn:
3562 case EvqCentroidIn:
3563 return true;
3564 }
3565
3566 return false;
3567}
3568
3569bool OutputHLSL::isVarying(TQualifier qualifier)
3570{
3571 return isVaryingIn(qualifier) || isVaryingOut(qualifier);
3572}
3573
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003574}