blob: e292c2e89a564b399e376f5cbe6f6501d1968e90 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00007#include "compiler/OutputHLSL.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00008
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +00009#include "common/debug.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010
11#include "compiler/InfoSink.h"
12#include "compiler/UnfoldSelect.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
14namespace sh
15{
daniel@transgaming.com005c7392010-04-15 20:45:27 +000016// Integer to TString conversion
17TString str(int i)
18{
19 char buffer[20];
20 sprintf(buffer, "%d", i);
21 return buffer;
22}
23
daniel@transgaming.com950f9932010-04-13 03:26:14 +000024OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025{
daniel@transgaming.comb5875982010-04-15 20:44:53 +000026 mUnfoldSelect = new UnfoldSelect(context, this);
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +000027 mInsideFunction = false;
daniel@transgaming.comb5875982010-04-15 20:44:53 +000028
daniel@transgaming.com5024cc42010-04-20 18:52:04 +000029 mUsesTexture2D = false;
30 mUsesTexture2D_bias = false;
31 mUsesTexture2DProj = false;
32 mUsesTexture2DProj_bias = false;
33 mUsesTextureCube = false;
34 mUsesTextureCube_bias = false;
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +000035 mUsesFaceforward1 = false;
36 mUsesFaceforward2 = false;
37 mUsesFaceforward3 = false;
38 mUsesFaceforward4 = false;
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +000039 mUsesEqualMat2 = false;
40 mUsesEqualMat3 = false;
41 mUsesEqualMat4 = false;
42 mUsesEqualVec2 = false;
43 mUsesEqualVec3 = false;
44 mUsesEqualVec4 = false;
45 mUsesEqualIVec2 = false;
46 mUsesEqualIVec3 = false;
47 mUsesEqualIVec4 = false;
48 mUsesEqualBVec2 = false;
49 mUsesEqualBVec3 = false;
50 mUsesEqualBVec4 = false;
daniel@transgaming.com005c7392010-04-15 20:45:27 +000051
52 mArgumentIndex = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000053}
54
daniel@transgaming.comb5875982010-04-15 20:44:53 +000055OutputHLSL::~OutputHLSL()
56{
57 delete mUnfoldSelect;
58}
59
daniel@transgaming.com950f9932010-04-13 03:26:14 +000060void OutputHLSL::output()
61{
62 mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header and footer
63 header();
64 footer();
65
66 mContext.infoSink.obj << mHeader.c_str();
67 mContext.infoSink.obj << mBody.c_str();
68 mContext.infoSink.obj << mFooter.c_str();
69}
70
daniel@transgaming.comb5875982010-04-15 20:44:53 +000071TInfoSinkBase &OutputHLSL::getBodyStream()
72{
73 return mBody;
74}
75
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +000076int OutputHLSL::vectorSize(const TType &type) const
77{
78 int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
79 int arraySize = type.isArray() ? type.getArraySize() : 1;
80
81 return elementSize * arraySize;
82}
83
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084void OutputHLSL::header()
85{
daniel@transgaming.com950f9932010-04-13 03:26:14 +000086 EShLanguage language = mContext.language;
87 TInfoSinkBase &out = mHeader;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088
89 if (language == EShLangFragment)
90 {
91 TString uniforms;
92 TString varyingInput;
93 TString varyingGlobals;
94
daniel@transgaming.com950f9932010-04-13 03:26:14 +000095 TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096 int semanticIndex = 0;
97
98 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
99 {
100 const TSymbol *symbol = (*namedSymbol).second;
101 const TString &name = symbol->getName();
102
103 if (symbol->isVariable())
104 {
105 const TVariable *variable = static_cast<const TVariable*>(symbol);
106 const TType &type = variable->getType();
107 TQualifier qualifier = type.getQualifier();
108
109 if (qualifier == EvqUniform)
110 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000111 if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end())
112 {
113 uniforms += "uniform " + typeString(type) + " " + decorate(name) + arrayString(type) + ";\n";
114 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115 }
116 else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
117 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000118 if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
119 {
120 // Program linking depends on this exact format
121 varyingInput += " " + typeString(type) + " " + decorate(name) + arrayString(type) + " : TEXCOORD" + str(semanticIndex) + ";\n";
122 varyingGlobals += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
daniel@transgaming.com005c7392010-04-15 20:45:27 +0000123
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000124 semanticIndex += type.isArray() ? type.getArraySize() : 1;
125 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000127 else if (qualifier == EvqGlobal || qualifier == EvqTemporary)
daniel@transgaming.comd25ab252010-03-30 03:36:26 +0000128 {
129 // Globals are declared and intialized as an aggregate node
130 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000131 else if (qualifier == EvqConst)
132 {
133 // Constants are repeated as literals where used
134 }
135 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136 }
137 }
138
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000139 out << "uniform float4 dx_Window;\n"
140 "uniform float2 dx_Depth;\n"
141 "uniform bool dx_PointsOrLines;\n"
142 "uniform bool dx_FrontCCW;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000143 "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 out << uniforms;
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000145 out << "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000146 "struct PS_INPUT\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147 "{\n";
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000148 out << varyingInput;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +0000149 out << " float4 gl_FragCoord : TEXCOORD" << semanticIndex << ";\n";
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000150 out << " float vFace : VFACE;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000151 "};\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152 "\n";
153 out << varyingGlobals;
154 out << "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000155 "struct PS_OUTPUT\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156 "{\n"
157 " float4 gl_Color[1] : COLOR;\n"
158 "};\n"
159 "\n"
160 "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000161 "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"
daniel@transgaming.comccad59f2010-03-26 04:08:39 +0000162 "static float2 gl_PointCoord = float2(0.5, 0.5);\n"
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000163 "static bool gl_FrontFacing = false;\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164 "\n";
daniel@transgaming.com5024cc42010-04-20 18:52:04 +0000165
166 if (mUsesTexture2D)
167 {
168 out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
169 "{\n"
170 " return tex2D(s, t);\n"
171 "}\n"
172 "\n";
173 }
174
175 if (mUsesTexture2D_bias)
176 {
177 out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
178 "{\n"
179 " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
180 "}\n"
181 "\n";
182 }
183
184 if (mUsesTexture2DProj)
185 {
186 out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
187 "{\n"
188 " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
189 "}\n"
190 "\n"
191 "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
192 "{\n"
193 " return tex2Dproj(s, t);\n"
194 "}\n"
195 "\n";
196 }
197
198 if (mUsesTexture2DProj_bias)
199 {
200 out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
201 "{\n"
202 " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
203 "}\n"
204 "\n"
205 "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
206 "{\n"
207 " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
208 "}\n"
209 "\n";
210 }
211
212 if (mUsesTextureCube)
213 {
214 out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
215 "{\n"
216 " return texCUBE(s, t);\n"
217 "}\n"
218 "\n";
219 }
220
221 if (mUsesTextureCube_bias)
222 {
223 out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
224 "{\n"
225 " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
226 "}\n"
227 "\n";
228 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229 }
daniel@transgaming.comd25ab252010-03-30 03:36:26 +0000230 else // Vertex shader
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231 {
232 TString uniforms;
233 TString attributeInput;
234 TString attributeGlobals;
235 TString varyingOutput;
236 TString varyingGlobals;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000238 TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239 int semanticIndex = 0;
240
241 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
242 {
243 const TSymbol *symbol = (*namedSymbol).second;
244 const TString &name = symbol->getName();
245
246 if (symbol->isVariable())
247 {
248 const TVariable *variable = static_cast<const TVariable*>(symbol);
249 const TType &type = variable->getType();
250 TQualifier qualifier = type.getQualifier();
251
252 if (qualifier == EvqUniform)
253 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000254 if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end())
255 {
256 uniforms += "uniform " + typeString(type) + " " + decorate(name) + arrayString(type) + ";\n";
257 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258 }
259 else if (qualifier == EvqAttribute)
260 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000261 if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end())
262 {
263 attributeInput += " " + typeString(type) + " " + decorate(name) + arrayString(type) + " : TEXCOORD" + str(semanticIndex) + ";\n";
264 attributeGlobals += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
daniel@transgaming.com005c7392010-04-15 20:45:27 +0000265
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000266 semanticIndex += vectorSize(type);
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000267 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268 }
269 else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
270 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000271 if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
272 {
273 // Program linking depends on this exact format
274 varyingOutput += " " + typeString(type) + " " + decorate(name) + arrayString(type) + " : TEXCOORD0;\n"; // Actual semantic index assigned during link
275 varyingGlobals += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
276 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000278 else if (qualifier == EvqGlobal || qualifier == EvqTemporary)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279 {
daniel@transgaming.comd25ab252010-03-30 03:36:26 +0000280 // Globals are declared and intialized as an aggregate node
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000282 else if (qualifier == EvqConst)
283 {
284 // Constants are repeated as literals where used
285 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286 else UNREACHABLE();
287 }
288 }
289
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000290 out << "uniform float2 dx_HalfPixelSize;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000291 "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292 out << uniforms;
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000293 out << "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000294 "struct VS_INPUT\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295 "{\n";
296 out << attributeInput;
297 out << "};\n"
298 "\n";
299 out << attributeGlobals;
300 out << "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000301 "struct VS_OUTPUT\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302 "{\n"
303 " float4 gl_Position : POSITION;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000304 " float gl_PointSize : PSIZE;\n"
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +0000305 " float4 gl_FragCoord : TEXCOORD0;\n"; // Actual semantic index assigned during link
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000306 out << varyingOutput;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307 out << "};\n"
308 "\n"
309 "static float4 gl_Position = float4(0, 0, 0, 0);\n"
daniel@transgaming.comccad59f2010-03-26 04:08:39 +0000310 "static float gl_PointSize = float(1);\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311 out << varyingGlobals;
312 out << "\n";
313 }
314
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000315 out << "struct gl_DepthRangeParameters\n"
316 "{\n"
317 " float near;\n"
318 " float far;\n"
319 " float diff;\n"
320 "};\n"
321 "\n"
322 "uniform gl_DepthRangeParameters gl_DepthRange;\n"
323 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000324 "bool xor(bool p, bool q)\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325 "{\n"
326 " return (p || q) && !(p && q);\n"
327 "}\n"
328 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000329 "float mod(float x, float y)\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330 "{\n"
331 " return x - y * floor(x / y);\n"
332 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000333 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000334 "float2 mod(float2 x, float y)\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335 "{\n"
336 " return x - y * floor(x / y);\n"
337 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000338 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000339 "float3 mod(float3 x, float y)\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340 "{\n"
341 " return x - y * floor(x / y);\n"
342 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000343 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000344 "float4 mod(float4 x, float y)\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345 "{\n"
346 " return x - y * floor(x / y);\n"
347 "}\n"
348 "\n";
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000349
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +0000350 if (mUsesFaceforward1)
351 {
352 out << "float faceforward(float N, float I, float Nref)\n"
353 "{\n"
354 " if(dot(Nref, I) < 0)\n"
355 " {\n"
356 " return N;\n"
357 " }\n"
358 " else\n"
359 " {\n"
360 " return -N;\n"
361 " }\n"
362 "}\n"
363 "\n";
364 }
365
366 if (mUsesFaceforward2)
367 {
368 out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
369 "{\n"
370 " if(dot(Nref, I) < 0)\n"
371 " {\n"
372 " return N;\n"
373 " }\n"
374 " else\n"
375 " {\n"
376 " return -N;\n"
377 " }\n"
378 "}\n"
379 "\n";
380 }
381
382 if (mUsesFaceforward3)
383 {
384 out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
385 "{\n"
386 " if(dot(Nref, I) < 0)\n"
387 " {\n"
388 " return N;\n"
389 " }\n"
390 " else\n"
391 " {\n"
392 " return -N;\n"
393 " }\n"
394 "}\n"
395 "\n";
396 }
397
398 if (mUsesFaceforward4)
399 {
400 out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
401 "{\n"
402 " if(dot(Nref, I) < 0)\n"
403 " {\n"
404 " return N;\n"
405 " }\n"
406 " else\n"
407 " {\n"
408 " return -N;\n"
409 " }\n"
410 "}\n"
411 "\n";
412 }
413
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000414 if (mUsesEqualMat2)
415 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000416 out << "bool equal(float2x2 m, float2x2 n)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000417 "{\n"
418 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
419 " m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
420 "}\n";
421 }
422
423 if (mUsesEqualMat3)
424 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000425 out << "bool equal(float3x3 m, float3x3 n)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000426 "{\n"
427 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
428 " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
429 " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
430 "}\n";
431 }
432
433 if (mUsesEqualMat4)
434 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000435 out << "bool equal(float4x4 m, float4x4 n)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000436 "{\n"
437 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
438 " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
439 " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
440 " m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
441 "}\n";
442 }
443
444 if (mUsesEqualVec2)
445 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000446 out << "bool equal(float2 v, float2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000447 "{\n"
448 " return v.x == u.x && v.y == u.y;\n"
449 "}\n";
450 }
451
452 if (mUsesEqualVec3)
453 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000454 out << "bool equal(float3 v, float3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000455 "{\n"
456 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
457 "}\n";
458 }
459
460 if (mUsesEqualVec4)
461 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000462 out << "bool equal(float4 v, float4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000463 "{\n"
464 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
465 "}\n";
466 }
467
468 if (mUsesEqualIVec2)
469 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000470 out << "bool equal(int2 v, int2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000471 "{\n"
472 " return v.x == u.x && v.y == u.y;\n"
473 "}\n";
474 }
475
476 if (mUsesEqualIVec3)
477 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000478 out << "bool equal(int3 v, int3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000479 "{\n"
480 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
481 "}\n";
482 }
483
484 if (mUsesEqualIVec4)
485 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000486 out << "bool equal(int4 v, int4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000487 "{\n"
488 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
489 "}\n";
490 }
491
492 if (mUsesEqualBVec2)
493 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000494 out << "bool equal(bool2 v, bool2 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000495 "{\n"
496 " return v.x == u.x && v.y == u.y;\n"
497 "}\n";
498 }
499
500 if (mUsesEqualBVec3)
501 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000502 out << "bool equal(bool3 v, bool3 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000503 "{\n"
504 " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
505 "}\n";
506 }
507
508 if (mUsesEqualBVec4)
509 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000510 out << "bool equal(bool4 v, bool4 u)\n"
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000511 "{\n"
512 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
513 "}\n";
514 }
daniel@transgaming.com63691862010-04-29 03:32:42 +0000515
516 for (ConstructorSet::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
517 {
518 out << typeString(constructor->type) + " " + constructor->name + "(";
519
520 for (unsigned int parameter = 0; parameter < constructor->parameters.size(); parameter++)
521 {
522 const TType &type = constructor->parameters[parameter];
523
524 out << typeString(type) + " x" + str(parameter);
525
526 if (parameter < constructor->parameters.size() - 1)
527 {
528 out << ", ";
529 }
530 }
531
532 out << ")\n"
533 "{\n";
534
535 out << " return " + typeString(constructor->type) + "(";
536
537 if (constructor->type.isMatrix() && constructor->parameters.size() == 1)
538 {
539 int dim = constructor->type.getNominalSize();
540 const TType &parameter = constructor->parameters[0];
541
542 if (parameter.isScalar())
543 {
544 for (int row = 0; row < dim; row++)
545 {
546 for (int col = 0; col < dim; col++)
547 {
548 out << TString((row == col) ? "x0" : "0.0");
549
550 if (row < dim - 1 || col < dim - 1)
551 {
552 out << ", ";
553 }
554 }
555 }
556 }
557 else if (parameter.isMatrix())
558 {
559 for (int row = 0; row < dim; row++)
560 {
561 for (int col = 0; col < dim; col++)
562 {
563 if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
564 {
565 out << TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
566 }
567 else
568 {
569 out << TString((row == col) ? "1.0" : "0.0");
570 }
571
572 if (row < dim - 1 || col < dim - 1)
573 {
574 out << ", ";
575 }
576 }
577 }
578 }
579 else UNREACHABLE();
580 }
581 else
582 {
583 int remainingComponents = constructor->type.getObjectSize();
584 int parameterIndex = 0;
585
586 while (remainingComponents > 0)
587 {
588 const TType &parameter = constructor->parameters[parameterIndex];
589 bool moreParameters = parameterIndex < (int)constructor->parameters.size() - 1;
590
591 out << "x" + str(parameterIndex);
592
593 if (parameter.isScalar())
594 {
595 remainingComponents -= 1;
596 }
597 else if (parameter.isVector())
598 {
599 if (remainingComponents == parameter.getInstanceSize() || moreParameters)
600 {
601 remainingComponents -= parameter.getInstanceSize();
602 }
603 else if (remainingComponents < parameter.getNominalSize())
604 {
605 switch (remainingComponents)
606 {
607 case 1: out << ".x"; break;
608 case 2: out << ".xy"; break;
609 case 3: out << ".xyz"; break;
610 case 4: out << ".xyzw"; break;
611 default: UNREACHABLE();
612 }
613
614 remainingComponents = 0;
615 }
616 else UNREACHABLE();
617 }
618 else if (parameter.isMatrix() || parameter.getStruct())
619 {
620 ASSERT(remainingComponents == parameter.getInstanceSize() || moreParameters);
621
622 remainingComponents -= parameter.getInstanceSize();
623 }
624 else UNREACHABLE();
625
626 if (moreParameters)
627 {
628 parameterIndex++;
629 }
630
631 if (remainingComponents)
632 {
633 out << ", ";
634 }
635 }
636 }
637
638 out << ");\n"
639 "}\n";
640 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641}
642
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000643void OutputHLSL::footer()
644{
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000645 EShLanguage language = mContext.language;
646 TInfoSinkBase &out = mFooter;
647 TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel();
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000648
649 if (language == EShLangFragment)
650 {
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000651 out << "PS_OUTPUT main(PS_INPUT input)\n"
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000652 "{\n"
653 " float rhw = 1.0 / input.gl_FragCoord.w;\n"
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000654 " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Window.x + dx_Window.z;\n"
655 " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Window.y + dx_Window.w;\n"
656 " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000657 " gl_FragCoord.w = rhw;\n"
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000658 " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000659
660 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
661 {
662 const TSymbol *symbol = (*namedSymbol).second;
663 const TString &name = symbol->getName();
664
665 if (symbol->isVariable())
666 {
667 const TVariable *variable = static_cast<const TVariable*>(symbol);
668 const TType &type = variable->getType();
669 TQualifier qualifier = type.getQualifier();
670
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000671 if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000672 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000673 if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
674 {
675 out << " " + decorate(name) + " = input." + decorate(name) + ";\n";
676 }
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000677 }
678 }
679 }
680
681 out << "\n"
682 " gl_main();\n"
683 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000684 " PS_OUTPUT output;\n"
685 " output.gl_Color[0] = gl_Color[0];\n";
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000686 }
daniel@transgaming.comd25ab252010-03-30 03:36:26 +0000687 else // Vertex shader
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000688 {
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000689 out << "VS_OUTPUT main(VS_INPUT input)\n"
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000690 "{\n";
691
692 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
693 {
694 const TSymbol *symbol = (*namedSymbol).second;
695 const TString &name = symbol->getName();
696
697 if (symbol->isVariable())
698 {
699 const TVariable *variable = static_cast<const TVariable*>(symbol);
700 const TType &type = variable->getType();
701 TQualifier qualifier = type.getQualifier();
702
703 if (qualifier == EvqAttribute)
704 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000705 if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end())
706 {
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000707 const char *transpose = type.isMatrix() ? "transpose" : "";
708
709 out << " " + decorate(name) + " = " + transpose + "(input." + decorate(name) + ");\n";
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000710 }
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000711 }
712 }
713 }
714
715 out << "\n"
716 " gl_main();\n"
717 "\n"
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000718 " VS_OUTPUT output;\n"
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000719 " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
720 " output.gl_Position.y = -(gl_Position.y - dx_HalfPixelSize.y * gl_Position.w);\n"
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000721 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
722 " output.gl_Position.w = gl_Position.w;\n"
723 " output.gl_PointSize = gl_PointSize;\n"
724 " output.gl_FragCoord = gl_Position;\n";
725
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000726 TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel();
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000727
728 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
729 {
730 const TSymbol *symbol = (*namedSymbol).second;
731 const TString &name = symbol->getName();
732
733 if (symbol->isVariable())
734 {
735 const TVariable *variable = static_cast<const TVariable*>(symbol);
736 TQualifier qualifier = variable->getType().getQualifier();
737
738 if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
739 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000740 if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
741 {
742 // Program linking depends on this exact format
743 out << " output." + decorate(name) + " = " + decorate(name) + ";\n";
744 }
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000745 }
746 }
747 }
748 }
749
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000750 out << " return output;\n"
daniel@transgaming.come78c0c92010-03-28 19:36:06 +0000751 "}\n";
752}
753
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754void OutputHLSL::visitSymbol(TIntermSymbol *node)
755{
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000756 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757
758 TString name = node->getSymbol();
759
760 if (name == "gl_FragColor")
761 {
762 out << "gl_Color[0]";
763 }
764 else if (name == "gl_FragData")
765 {
766 out << "gl_Color";
767 }
768 else
769 {
daniel@transgaming.com86f7c9d2010-04-20 18:52:06 +0000770 TQualifier qualifier = node->getQualifier();
771
772 if (qualifier == EvqUniform)
773 {
774 mReferencedUniforms.insert(name.c_str());
775 }
776 else if (qualifier == EvqAttribute)
777 {
778 mReferencedAttributes.insert(name.c_str());
779 }
780 else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
781 {
782 mReferencedVaryings.insert(name.c_str());
783 }
784
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000785 out << decorate(name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786 }
787}
788
789bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
790{
daniel@transgaming.com950f9932010-04-13 03:26:14 +0000791 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792
793 switch (node->getOp())
794 {
daniel@transgaming.com93a96c32010-03-28 19:36:13 +0000795 case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +0000796 case EOpInitialize: outputTriplet(visit, "", " = ", ""); break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +0000797 case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break;
798 case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break;
799 case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break;
800 case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
801 case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
802 case EOpVectorTimesMatrixAssign:
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +0000803 if (visit == PreVisit)
804 {
805 out << "(";
806 }
807 else if (visit == InVisit)
808 {
809 out << " = mul(";
810 node->getLeft()->traverse(this);
811 out << ", transpose(";
812 }
813 else
814 {
815 out << "))";
816 }
817 break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +0000818 case EOpMatrixTimesMatrixAssign:
819 if (visit == PreVisit)
820 {
821 out << "(";
822 }
823 else if (visit == InVisit)
824 {
825 out << " = mul(";
826 node->getLeft()->traverse(this);
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +0000827 out << ", ";
daniel@transgaming.com93a96c32010-03-28 19:36:13 +0000828 }
829 else
830 {
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +0000831 out << ")";
daniel@transgaming.com93a96c32010-03-28 19:36:13 +0000832 }
833 break;
834 case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +0000835 case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break;
836 case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break;
837 case EOpIndexDirectStruct: outputTriplet(visit, "", ".", ""); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000838 case EOpVectorSwizzle:
839 if (visit == InVisit)
840 {
841 out << ".";
842
843 TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
844
845 if (swizzle)
846 {
847 TIntermSequence &sequence = swizzle->getSequence();
848
849 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
850 {
851 TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
852
853 if (element)
854 {
855 int i = element->getUnionArrayPointer()[0].getIConst();
856
857 switch (i)
858 {
859 case 0: out << "x"; break;
860 case 1: out << "y"; break;
861 case 2: out << "z"; break;
862 case 3: out << "w"; break;
863 default: UNREACHABLE();
864 }
865 }
866 else UNREACHABLE();
867 }
868 }
869 else UNREACHABLE();
870
871 return false; // Fully processed
872 }
873 break;
874 case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break;
875 case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
876 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
877 case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000878 case EOpEqual:
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000879 case EOpNotEqual:
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000880 if (node->getLeft()->isScalar())
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000881 {
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000882 if (node->getOp() == EOpEqual)
883 {
884 outputTriplet(visit, "(", " == ", ")");
885 }
886 else
887 {
888 outputTriplet(visit, "(", " != ", ")");
889 }
890 }
891 else if (node->getLeft()->getBasicType() == EbtStruct)
892 {
893 if (node->getOp() == EOpEqual)
894 {
895 out << "(";
896 }
897 else
898 {
899 out << "!(";
900 }
901
902 const TTypeList *fields = node->getLeft()->getType().getStruct();
903
904 for (size_t i = 0; i < fields->size(); i++)
905 {
906 const TType *fieldType = (*fields)[i].type;
907
908 node->getLeft()->traverse(this);
909 out << "." + fieldType->getFieldName() + " == ";
910 node->getRight()->traverse(this);
911 out << "." + fieldType->getFieldName();
912
913 if (i < fields->size() - 1)
914 {
915 out << " && ";
916 }
917 }
918
919 out << ")";
920
921 return false;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000922 }
923 else
924 {
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000925 if (node->getLeft()->isMatrix())
926 {
927 switch (node->getLeft()->getSize())
928 {
929 case 2 * 2: mUsesEqualMat2 = true; break;
930 case 3 * 3: mUsesEqualMat3 = true; break;
931 case 4 * 4: mUsesEqualMat4 = true; break;
932 default: UNREACHABLE();
933 }
934 }
935 else if (node->getLeft()->isVector())
936 {
937 switch (node->getLeft()->getBasicType())
938 {
939 case EbtFloat:
940 switch (node->getLeft()->getSize())
941 {
942 case 2: mUsesEqualVec2 = true; break;
943 case 3: mUsesEqualVec3 = true; break;
944 case 4: mUsesEqualVec4 = true; break;
945 default: UNREACHABLE();
946 }
947 break;
948 case EbtInt:
949 switch (node->getLeft()->getSize())
950 {
951 case 2: mUsesEqualIVec2 = true; break;
952 case 3: mUsesEqualIVec3 = true; break;
953 case 4: mUsesEqualIVec4 = true; break;
954 default: UNREACHABLE();
955 }
956 break;
957 case EbtBool:
958 switch (node->getLeft()->getSize())
959 {
960 case 2: mUsesEqualBVec2 = true; break;
961 case 3: mUsesEqualBVec3 = true; break;
962 case 4: mUsesEqualBVec4 = true; break;
963 default: UNREACHABLE();
964 }
965 break;
966 default: UNREACHABLE();
967 }
968 }
969 else UNREACHABLE();
970
971 if (node->getOp() == EOpEqual)
972 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000973 outputTriplet(visit, "equal(", ", ", ")");
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000974 }
975 else
976 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +0000977 outputTriplet(visit, "!equal(", ", ", ")");
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +0000978 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000979 }
980 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000981 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
982 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
983 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
984 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
985 case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com93a96c32010-03-28 19:36:13 +0000986 case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com8976c1e2010-04-13 19:53:27 +0000987 case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
988 case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
daniel@transgaming.com69f084b2010-04-23 18:34:46 +0000989 case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990 case EOpLogicalOr: outputTriplet(visit, "(", " || ", ")"); break;
daniel@transgaming.com3c010c02010-04-13 19:53:47 +0000991 case EOpLogicalXor: outputTriplet(visit, "xor(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992 case EOpLogicalAnd: outputTriplet(visit, "(", " && ", ")"); break;
993 default: UNREACHABLE();
994 }
995
996 return true;
997}
998
999bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
1000{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001001 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002
1003 switch (node->getOp())
1004 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001005 case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
1006 case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
1007 case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
1008 case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
1009 case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
1010 case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
1011 case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012 case EOpConvIntToBool:
1013 case EOpConvFloatToBool:
1014 switch (node->getOperand()->getType().getNominalSize())
1015 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001016 case 1: outputTriplet(visit, "bool(", "", ")"); break;
1017 case 2: outputTriplet(visit, "bool2(", "", ")"); break;
1018 case 3: outputTriplet(visit, "bool3(", "", ")"); break;
1019 case 4: outputTriplet(visit, "bool4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001020 default: UNREACHABLE();
1021 }
1022 break;
1023 case EOpConvBoolToFloat:
1024 case EOpConvIntToFloat:
1025 switch (node->getOperand()->getType().getNominalSize())
1026 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001027 case 1: outputTriplet(visit, "float(", "", ")"); break;
1028 case 2: outputTriplet(visit, "float2(", "", ")"); break;
1029 case 3: outputTriplet(visit, "float3(", "", ")"); break;
1030 case 4: outputTriplet(visit, "float4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001031 default: UNREACHABLE();
1032 }
1033 break;
1034 case EOpConvFloatToInt:
1035 case EOpConvBoolToInt:
1036 switch (node->getOperand()->getType().getNominalSize())
1037 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001038 case 1: outputTriplet(visit, "int(", "", ")"); break;
1039 case 2: outputTriplet(visit, "int2(", "", ")"); break;
1040 case 3: outputTriplet(visit, "int3(", "", ")"); break;
1041 case 4: outputTriplet(visit, "int4(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001042 default: UNREACHABLE();
1043 }
1044 break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001045 case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break;
1046 case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break;
1047 case EOpSin: outputTriplet(visit, "sin(", "", ")"); break;
1048 case EOpCos: outputTriplet(visit, "cos(", "", ")"); break;
1049 case EOpTan: outputTriplet(visit, "tan(", "", ")"); break;
1050 case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
1051 case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
1052 case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
1053 case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
1054 case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
1055 case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
1056 case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break;
1057 case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break;
1058 case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break;
1059 case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break;
1060 case EOpSign: outputTriplet(visit, "sign(", "", ")"); break;
1061 case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break;
1062 case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
1063 case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
1064 case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
1065 case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
1066// case EOpDPdx: outputTriplet(visit, "ddx(", "", ")"); break;
1067// case EOpDPdy: outputTriplet(visit, "ddy(", "", ")"); break;
1068// case EOpFwidth: outputTriplet(visit, "fwidth(", "", ")"); break;
1069 case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
1070 case EOpAll: outputTriplet(visit, "all(", "", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001071 default: UNREACHABLE();
1072 }
1073
1074 return true;
1075}
1076
1077bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
1078{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001079 EShLanguage language = mContext.language;
1080 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001082 switch (node->getOp())
1083 {
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001084 case EOpSequence:
1085 {
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001086 if (mInsideFunction)
1087 {
1088 out << "{\n";
1089 }
1090
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001091 for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
1092 {
1093 if (isSingleStatement(*sit))
1094 {
1095 mUnfoldSelect->traverse(*sit);
1096 }
1097
1098 (*sit)->traverse(this);
1099
1100 out << ";\n";
1101 }
1102
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001103 if (mInsideFunction)
1104 {
1105 out << "}\n";
1106 }
1107
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001108 return false;
1109 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001110 case EOpDeclaration:
1111 if (visit == PreVisit)
1112 {
1113 TIntermSequence &sequence = node->getSequence();
1114 TIntermTyped *variable = sequence[0]->getAsTyped();
1115 bool visit = true;
1116
daniel@transgaming.comd25ab252010-03-30 03:36:26 +00001117 if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001118 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001119 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001120 {
daniel@transgaming.comd2cf25d2010-04-22 16:27:35 +00001121 if (!mInsideFunction)
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001122 {
1123 out << "static ";
1124 }
1125
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001126 out << typeString(variable->getType()) + " ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001127
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001128 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001129 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001130 TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001131
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001132 if (symbol)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001133 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001134 symbol->traverse(this);
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001135 out << arrayString(symbol->getType());
daniel@transgaming.com7127f202010-04-15 20:45:22 +00001136 out << " = " + initializer(variable->getType());
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001137 }
1138 else
1139 {
1140 (*sit)->traverse(this);
1141 }
1142
1143 if (visit && this->inVisit)
1144 {
1145 if (*sit != sequence.back())
1146 {
1147 visit = this->visitAggregate(InVisit, node);
1148 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001149 }
1150 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001151
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001152 if (visit && this->postVisit)
1153 {
1154 this->visitAggregate(PostVisit, node);
1155 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001156 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001157 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
1158 {
1159 const TType &type = variable->getType();
1160 const TTypeList &fields = *type.getStruct();
1161
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001162 out << "struct " + decorate(type.getTypeName()) + "\n"
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001163 "{\n";
1164
1165 for (unsigned int i = 0; i < fields.size(); i++)
1166 {
1167 const TType &field = *fields[i].type;
1168
1169 out << " " + typeString(field) + " " + field.getFieldName() + ";\n";
1170 }
1171
1172 out << "};\n";
1173 }
1174 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001175 }
1176
1177 return false;
1178 }
1179 else if (visit == InVisit)
1180 {
1181 out << ", ";
1182 }
1183 break;
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001184 case EOpPrototype:
1185 if (visit == PreVisit)
1186 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001187 out << typeString(node->getType()) << " " << decorate(node->getName()) << "(";
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001188
1189 TIntermSequence &arguments = node->getSequence();
1190
1191 for (unsigned int i = 0; i < arguments.size(); i++)
1192 {
1193 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
1194
1195 if (symbol)
1196 {
1197 out << argumentString(symbol);
1198
1199 if (i < arguments.size() - 1)
1200 {
1201 out << ", ";
1202 }
1203 }
1204 else UNREACHABLE();
1205 }
1206
1207 out << ");\n";
1208
1209 return false;
1210 }
1211 break;
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001212 case EOpComma: outputTriplet(visit, "", ", ", ""); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001213 case EOpFunction:
1214 {
alokp@chromium.org43884872010-03-30 00:08:52 +00001215 TString name = TFunction::unmangleName(node->getName());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001216
1217 if (visit == PreVisit)
1218 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001219 out << typeString(node->getType()) << " ";
1220
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001221 if (name == "main")
1222 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001223 out << "gl_main(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001224 }
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001225 else
1226 {
1227 out << decorate(name) << "(";
1228 }
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001229
1230 TIntermSequence &sequence = node->getSequence();
1231 TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
1232
1233 for (unsigned int i = 0; i < arguments.size(); i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001234 {
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001235 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001236
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001237 if (symbol)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001238 {
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001239 out << argumentString(symbol);
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001240
1241 if (i < arguments.size() - 1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001242 {
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001243 out << ", ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001244 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001245 }
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001246 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001247 }
daniel@transgaming.come78c0c92010-03-28 19:36:06 +00001248
1249 sequence.erase(sequence.begin());
1250
daniel@transgaming.com63691862010-04-29 03:32:42 +00001251 out << ")\n"
1252 "{\n";
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001253
1254 mInsideFunction = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001255 }
1256 else if (visit == PostVisit)
1257 {
daniel@transgaming.com63691862010-04-29 03:32:42 +00001258 out << "}\n";
1259
daniel@transgaming.comf9ef1072010-04-22 13:35:16 +00001260 mInsideFunction = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001261 }
1262 }
1263 break;
1264 case EOpFunctionCall:
1265 {
1266 if (visit == PreVisit)
1267 {
alokp@chromium.org43884872010-03-30 00:08:52 +00001268 TString name = TFunction::unmangleName(node->getName());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001269
1270 if (node->isUserDefined())
1271 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001272 out << decorate(name) << "(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001273 }
1274 else
1275 {
1276 if (name == "texture2D")
1277 {
1278 if (node->getSequence().size() == 2)
1279 {
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001280 mUsesTexture2D = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001281 }
1282 else if (node->getSequence().size() == 3)
1283 {
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001284 mUsesTexture2D_bias = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001285 }
1286 else UNREACHABLE();
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001287
1288 out << "gl_texture2D(";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001289 }
1290 else if (name == "texture2DProj")
1291 {
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001292 if (node->getSequence().size() == 2)
1293 {
1294 mUsesTexture2DProj = true;
1295 }
1296 else if (node->getSequence().size() == 3)
1297 {
1298 mUsesTexture2DProj_bias = true;
1299 }
1300 else UNREACHABLE();
1301
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001302 out << "gl_texture2DProj(";
1303 }
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001304 else if (name == "textureCube")
1305 {
1306 if (node->getSequence().size() == 2)
1307 {
1308 mUsesTextureCube = true;
1309 }
1310 else if (node->getSequence().size() == 3)
1311 {
1312 mUsesTextureCube_bias = true;
1313 }
1314 else UNREACHABLE();
1315
1316 out << "gl_textureCube(";
1317 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001318 else if (name == "texture2DLod")
1319 {
daniel@transgaming.comec55d292010-04-15 20:44:49 +00001320 UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001321 }
1322 else if (name == "texture2DProjLod")
1323 {
daniel@transgaming.comec55d292010-04-15 20:44:49 +00001324 UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001325 }
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001326 else if (name == "textureCubeLod")
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001327 {
daniel@transgaming.com5024cc42010-04-20 18:52:04 +00001328 UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001329 }
daniel@transgaming.comec55d292010-04-15 20:44:49 +00001330 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001331 }
1332 }
1333 else if (visit == InVisit)
1334 {
1335 out << ", ";
1336 }
1337 else
1338 {
1339 out << ")";
1340 }
1341 }
1342 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001343 case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001344 case EOpConstructFloat:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001345 addConstructor(node->getType(), "vec1", &node->getSequence());
1346 outputTriplet(visit, "vec1(", "", ")");
1347 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001348 case EOpConstructVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001349 addConstructor(node->getType(), "vec2", &node->getSequence());
1350 outputTriplet(visit, "vec2(", ", ", ")");
1351 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001352 case EOpConstructVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001353 addConstructor(node->getType(), "vec3", &node->getSequence());
1354 outputTriplet(visit, "vec3(", ", ", ")");
1355 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001356 case EOpConstructVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001357 addConstructor(node->getType(), "vec4", &node->getSequence());
1358 outputTriplet(visit, "vec4(", ", ", ")");
1359 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001360 case EOpConstructBool:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001361 addConstructor(node->getType(), "bvec1", &node->getSequence());
1362 outputTriplet(visit, "bvec1(", "", ")");
1363 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001364 case EOpConstructBVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001365 addConstructor(node->getType(), "bvec2", &node->getSequence());
1366 outputTriplet(visit, "bvec2(", ", ", ")");
1367 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001368 case EOpConstructBVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001369 addConstructor(node->getType(), "bvec3", &node->getSequence());
1370 outputTriplet(visit, "bvec3(", ", ", ")");
1371 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001372 case EOpConstructBVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001373 addConstructor(node->getType(), "bvec4", &node->getSequence());
1374 outputTriplet(visit, "bvec4(", ", ", ")");
1375 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001376 case EOpConstructInt:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001377 addConstructor(node->getType(), "ivec1", &node->getSequence());
1378 outputTriplet(visit, "ivec1(", "", ")");
1379 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001380 case EOpConstructIVec2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001381 addConstructor(node->getType(), "ivec2", &node->getSequence());
1382 outputTriplet(visit, "ivec2(", ", ", ")");
1383 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001384 case EOpConstructIVec3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001385 addConstructor(node->getType(), "ivec3", &node->getSequence());
1386 outputTriplet(visit, "ivec3(", ", ", ")");
1387 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001388 case EOpConstructIVec4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001389 addConstructor(node->getType(), "ivec4", &node->getSequence());
1390 outputTriplet(visit, "ivec4(", ", ", ")");
1391 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001392 case EOpConstructMat2:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001393 addConstructor(node->getType(), "mat2", &node->getSequence());
1394 outputTriplet(visit, "mat2(", ", ", ")");
1395 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001396 case EOpConstructMat3:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001397 addConstructor(node->getType(), "mat3", &node->getSequence());
1398 outputTriplet(visit, "mat3(", ", ", ")");
1399 break;
daniel@transgaming.com63691862010-04-29 03:32:42 +00001400 case EOpConstructMat4:
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001401 addConstructor(node->getType(), "mat4", &node->getSequence());
1402 outputTriplet(visit, "mat4(", ", ", ")");
1403 break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001404 case EOpConstructStruct: outputTriplet(visit, "{", ", ", "}"); break;
1405 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
1406 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
1407 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
1408 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
1409 case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
1410 case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
daniel@transgaming.com3c010c02010-04-13 19:53:47 +00001411 case EOpMod: outputTriplet(visit, "mod(", ", ", ")"); break;
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001412 case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001413 case EOpAtan:
1414 if (node->getSequence().size() == 1)
1415 {
1416 outputTriplet(visit, "atan(", ", ", ")");
1417 }
1418 else if (node->getSequence().size() == 2)
1419 {
1420 outputTriplet(visit, "atan2(", ", ", ")");
1421 }
1422 else UNREACHABLE();
1423 break;
1424 case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
1425 case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
1426 case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break;
1427 case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break;
1428 case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break;
1429 case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break;
1430 case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break;
1431 case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
1432 case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
daniel@transgaming.com0bbb0312010-04-26 15:33:39 +00001433 case EOpFaceForward:
1434 {
1435 switch (node->getSequence()[0]->getAsTyped()->getSize()) // Number of components in the first argument
1436 {
1437 case 1: mUsesFaceforward1 = true; break;
1438 case 2: mUsesFaceforward2 = true; break;
1439 case 3: mUsesFaceforward3 = true; break;
1440 case 4: mUsesFaceforward4 = true; break;
1441 default: UNREACHABLE();
1442 }
1443
1444 outputTriplet(visit, "faceforward(", ", ", ")");
1445 }
1446 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001447 case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
1448 case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
1449 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001450 default: UNREACHABLE();
1451 }
1452
1453 return true;
1454}
1455
1456bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
1457{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001458 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001459
alokp@chromium.org60fe4072010-03-29 20:58:29 +00001460 if (node->usesTernaryOperator())
1461 {
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001462 out << "t" << mUnfoldSelect->getTemporaryIndex();
alokp@chromium.org60fe4072010-03-29 20:58:29 +00001463 }
1464 else // if/else statement
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001465 {
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001466 mUnfoldSelect->traverse(node->getCondition());
1467
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00001468 out << "if(";
1469
1470 node->getCondition()->traverse(this);
1471
1472 out << ")\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001473 "{\n";
1474
daniel@transgaming.combb885322010-04-15 20:45:24 +00001475 if (node->getTrueBlock())
1476 {
1477 node->getTrueBlock()->traverse(this);
1478 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001479
1480 out << ";}\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +00001481
1482 if (node->getFalseBlock())
1483 {
1484 out << "else\n"
1485 "{\n";
1486
1487 node->getFalseBlock()->traverse(this);
1488
1489 out << ";}\n";
1490 }
1491 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001492
1493 return false;
1494}
1495
1496void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
1497{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001498 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001499
alokp@chromium.orgdd037b22010-03-30 18:47:20 +00001500 const TType &type = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001501
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001502 if (type.isField())
1503 {
1504 out << type.getFieldName();
1505 }
1506 else
1507 {
1508 int size = type.getObjectSize();
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001509
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001510 if (type.getBasicType() == EbtStruct)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001511 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001512 out << "{";
1513 }
1514 else
1515 {
1516 bool matrix = type.isMatrix();
1517 TBasicType elementType = node->getUnionArrayPointer()[0].getType();
1518
1519 switch (elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001520 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001521 case EbtBool:
1522 if (!matrix)
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001523 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001524 switch (size)
1525 {
1526 case 1: out << "bool("; break;
1527 case 2: out << "bool2("; break;
1528 case 3: out << "bool3("; break;
1529 case 4: out << "bool4("; break;
1530 default: UNREACHABLE();
1531 }
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001532 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001533 else UNREACHABLE();
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001534 break;
1535 case EbtFloat:
1536 if (!matrix)
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001537 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001538 switch (size)
1539 {
1540 case 1: out << "float("; break;
1541 case 2: out << "float2("; break;
1542 case 3: out << "float3("; break;
1543 case 4: out << "float4("; break;
1544 default: UNREACHABLE();
1545 }
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001546 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001547 else
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001548 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001549 switch (size)
1550 {
1551 case 4: out << "float2x2("; break;
1552 case 9: out << "float3x3("; break;
1553 case 16: out << "float4x4("; break;
1554 default: UNREACHABLE();
1555 }
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001556 }
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001557 break;
1558 case EbtInt:
1559 if (!matrix)
1560 {
1561 switch (size)
1562 {
1563 case 1: out << "int("; break;
1564 case 2: out << "int2("; break;
1565 case 3: out << "int3("; break;
1566 case 4: out << "int4("; break;
1567 default: UNREACHABLE();
1568 }
1569 }
daniel@transgaming.comd91cfe72010-04-13 03:26:17 +00001570 else UNREACHABLE();
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001571 break;
1572 default:
1573 UNIMPLEMENTED(); // FIXME
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001574 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001575 }
1576
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001577 for (int i = 0; i < size; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001578 {
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001579 switch (node->getUnionArrayPointer()[i].getType())
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001580 {
1581 case EbtBool:
1582 if (node->getUnionArrayPointer()[i].getBConst())
1583 {
1584 out << "true";
1585 }
1586 else
1587 {
1588 out << "false";
1589 }
1590 break;
1591 case EbtFloat:
1592 out << node->getUnionArrayPointer()[i].getFConst();
1593 break;
1594 case EbtInt:
1595 out << node->getUnionArrayPointer()[i].getIConst();
1596 break;
1597 default:
1598 UNIMPLEMENTED(); // FIXME
1599 }
1600
1601 if (i != size - 1)
1602 {
1603 out << ", ";
1604 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001605 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001606
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001607 if (type.getBasicType() == EbtStruct)
1608 {
1609 out << "}";
1610 }
1611 else
1612 {
1613 out << ")";
1614 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001615 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616}
1617
1618bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
1619{
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00001620 if (handleExcessiveLoop(node))
1621 {
1622 return false;
1623 }
1624
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001625 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001626
1627 if (!node->testFirst())
1628 {
1629 out << "do\n"
1630 "{\n";
1631 }
1632 else
1633 {
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001634 if (node->getInit())
1635 {
1636 mUnfoldSelect->traverse(node->getInit());
1637 }
1638
1639 if (node->getTest())
1640 {
1641 mUnfoldSelect->traverse(node->getTest());
1642 }
1643
1644 if (node->getTerminal())
1645 {
1646 mUnfoldSelect->traverse(node->getTerminal());
1647 }
1648
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001649 out << "for(";
1650
1651 if (node->getInit())
1652 {
1653 node->getInit()->traverse(this);
1654 }
1655
1656 out << "; ";
1657
1658 if (node->getTest())
1659 {
1660 node->getTest()->traverse(this);
1661 }
1662
1663 out << "; ";
1664
1665 if (node->getTerminal())
1666 {
1667 node->getTerminal()->traverse(this);
1668 }
1669
1670 out << ")\n"
1671 "{\n";
1672 }
1673
1674 if (node->getBody())
1675 {
1676 node->getBody()->traverse(this);
1677 }
1678
1679 out << "}\n";
1680
1681 if (!node->testFirst())
1682 {
1683 out << "while(\n";
1684
1685 node->getTest()->traverse(this);
1686
1687 out << ")";
1688 }
1689
1690 out << ";\n";
1691
1692 return false;
1693}
1694
1695bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
1696{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001697 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698
1699 switch (node->getFlowOp())
1700 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001701 case EOpKill: outputTriplet(visit, "discard", "", ""); break;
1702 case EOpBreak: outputTriplet(visit, "break", "", ""); break;
1703 case EOpContinue: outputTriplet(visit, "continue", "", ""); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704 case EOpReturn:
1705 if (visit == PreVisit)
1706 {
1707 if (node->getExpression())
1708 {
1709 out << "return ";
1710 }
1711 else
1712 {
1713 out << "return;\n";
1714 }
1715 }
1716 else if (visit == PostVisit)
1717 {
1718 out << ";\n";
1719 }
1720 break;
1721 default: UNREACHABLE();
1722 }
1723
1724 return true;
1725}
1726
daniel@transgaming.comb5875982010-04-15 20:44:53 +00001727bool OutputHLSL::isSingleStatement(TIntermNode *node)
1728{
1729 TIntermAggregate *aggregate = node->getAsAggregate();
1730
1731 if (aggregate)
1732 {
1733 if (aggregate->getOp() == EOpSequence)
1734 {
1735 return false;
1736 }
1737 else
1738 {
1739 for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
1740 {
1741 if (!isSingleStatement(*sit))
1742 {
1743 return false;
1744 }
1745 }
1746
1747 return true;
1748 }
1749 }
1750
1751 return true;
1752}
1753
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00001754// Handle loops with more than 255 iterations (unsupported by D3D9) by splitting them
1755bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
1756{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001757 TInfoSinkBase &out = mBody;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00001758
1759 // Parse loops of the form:
1760 // for(int index = initial; index [comparator] limit; index += increment)
1761 TIntermSymbol *index = NULL;
1762 TOperator comparator = EOpNull;
1763 int initial = 0;
1764 int limit = 0;
1765 int increment = 0;
1766
1767 // Parse index name and intial value
1768 if (node->getInit())
1769 {
1770 TIntermAggregate *init = node->getInit()->getAsAggregate();
1771
1772 if (init)
1773 {
1774 TIntermSequence &sequence = init->getSequence();
1775 TIntermTyped *variable = sequence[0]->getAsTyped();
1776
1777 if (variable && variable->getQualifier() == EvqTemporary)
1778 {
1779 TIntermBinary *assign = variable->getAsBinaryNode();
1780
1781 if (assign->getOp() == EOpInitialize)
1782 {
1783 TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
1784 TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
1785
1786 if (symbol && constant)
1787 {
1788 if (constant->getBasicType() == EbtInt && constant->getSize() == 1)
1789 {
1790 index = symbol;
1791 initial = constant->getUnionArrayPointer()[0].getIConst();
1792 }
1793 }
1794 }
1795 }
1796 }
1797 }
1798
1799 // Parse comparator and limit value
1800 if (index != NULL && node->getTest())
1801 {
1802 TIntermBinary *test = node->getTest()->getAsBinaryNode();
1803
1804 if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
1805 {
1806 TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
1807
1808 if (constant)
1809 {
1810 if (constant->getBasicType() == EbtInt && constant->getSize() == 1)
1811 {
1812 comparator = test->getOp();
1813 limit = constant->getUnionArrayPointer()[0].getIConst();
1814 }
1815 }
1816 }
1817 }
1818
1819 // Parse increment
1820 if (index != NULL && comparator != EOpNull && node->getTerminal())
1821 {
1822 TIntermBinary *binaryTerminal = node->getTerminal()->getAsBinaryNode();
1823 TIntermUnary *unaryTerminal = node->getTerminal()->getAsUnaryNode();
1824
1825 if (binaryTerminal)
1826 {
1827 TOperator op = binaryTerminal->getOp();
1828 TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
1829
1830 if (constant)
1831 {
1832 if (constant->getBasicType() == EbtInt && constant->getSize() == 1)
1833 {
1834 int value = constant->getUnionArrayPointer()[0].getIConst();
1835
1836 switch (op)
1837 {
1838 case EOpAddAssign: increment = value; break;
1839 case EOpSubAssign: increment = -value; break;
1840 default: UNIMPLEMENTED();
1841 }
1842 }
1843 }
1844 }
1845 else if (unaryTerminal)
1846 {
1847 TOperator op = unaryTerminal->getOp();
1848
1849 switch (op)
1850 {
1851 case EOpPostIncrement: increment = 1; break;
1852 case EOpPostDecrement: increment = -1; break;
1853 case EOpPreIncrement: increment = 1; break;
1854 case EOpPreDecrement: increment = -1; break;
1855 default: UNIMPLEMENTED();
1856 }
1857 }
1858 }
1859
1860 if (index != NULL && comparator != EOpNull && increment != 0)
1861 {
1862 if (comparator == EOpLessThanEqual)
1863 {
1864 comparator = EOpLessThan;
1865 limit += 1;
1866 }
1867
1868 if (comparator == EOpLessThan)
1869 {
1870 int iterations = (limit - initial + 1) / increment;
1871
1872 if (iterations <= 255)
1873 {
1874 return false; // Not an excessive loop
1875 }
1876
1877 while (iterations > 0)
1878 {
1879 int remainder = (limit - initial + 1) % increment;
alokp@chromium.org47c058c2010-04-13 15:30:05 +00001880 int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +00001881
1882 // for(int index = initial; index < clampedLimit; index += increment)
1883
1884 out << "for(int ";
1885 index->traverse(this);
1886 out << " = ";
1887 out << initial;
1888
1889 out << "; ";
1890 index->traverse(this);
1891 out << " < ";
1892 out << clampedLimit;
1893
1894 out << "; ";
1895 index->traverse(this);
1896 out << " += ";
1897 out << increment;
1898 out << ")\n"
1899 "{\n";
1900
1901 if (node->getBody())
1902 {
1903 node->getBody()->traverse(this);
1904 }
1905
1906 out << "}\n";
1907
1908 initial += 255 * increment;
1909 iterations -= 255;
1910 }
1911
1912 return true;
1913 }
1914 else UNIMPLEMENTED();
1915 }
1916
1917 return false; // Not handled as an excessive loop
1918}
1919
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001920void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001921{
daniel@transgaming.com950f9932010-04-13 03:26:14 +00001922 TInfoSinkBase &out = mBody;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001923
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001924 if (visit == PreVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001925 {
1926 out << preString;
1927 }
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001928 else if (visit == InVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001929 {
1930 out << inString;
1931 }
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00001932 else if (visit == PostVisit)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001933 {
1934 out << postString;
1935 }
1936}
1937
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001938TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
1939{
1940 TQualifier qualifier = symbol->getQualifier();
1941 const TType &type = symbol->getType();
daniel@transgaming.com005c7392010-04-15 20:45:27 +00001942 TString name = symbol->getSymbol();
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001943
daniel@transgaming.com005c7392010-04-15 20:45:27 +00001944 if (name.empty()) // HLSL demands named arguments, also for prototypes
1945 {
1946 name = "x" + str(mArgumentIndex++);
1947 }
1948 else
1949 {
1950 name = decorate(name);
1951 }
1952
1953 return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +00001954}
1955
1956TString OutputHLSL::qualifierString(TQualifier qualifier)
1957{
1958 switch(qualifier)
1959 {
1960 case EvqIn: return "in";
1961 case EvqOut: return "out";
1962 case EvqInOut: return "inout";
1963 case EvqConstReadOnly: return "const";
1964 default: UNREACHABLE();
1965 }
1966
1967 return "";
1968}
1969
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001970TString OutputHLSL::typeString(const TType &type)
1971{
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001972 if (type.getBasicType() == EbtStruct)
1973 {
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001974 return decorate(type.getTypeName());
daniel@transgaming.comfe565152010-04-10 05:29:07 +00001975 }
1976 else if (type.isMatrix())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001977 {
1978 switch (type.getNominalSize())
1979 {
1980 case 2: return "float2x2";
1981 case 3: return "float3x3";
1982 case 4: return "float4x4";
1983 }
1984 }
1985 else
1986 {
1987 switch (type.getBasicType())
1988 {
1989 case EbtFloat:
1990 switch (type.getNominalSize())
1991 {
1992 case 1: return "float";
1993 case 2: return "float2";
1994 case 3: return "float3";
1995 case 4: return "float4";
1996 }
1997 case EbtInt:
1998 switch (type.getNominalSize())
1999 {
2000 case 1: return "int";
2001 case 2: return "int2";
2002 case 3: return "int3";
2003 case 4: return "int4";
2004 }
2005 case EbtBool:
2006 switch (type.getNominalSize())
2007 {
2008 case 1: return "bool";
2009 case 2: return "bool2";
2010 case 3: return "bool3";
2011 case 4: return "bool4";
2012 }
2013 case EbtVoid:
2014 return "void";
2015 case EbtSampler2D:
2016 return "sampler2D";
2017 case EbtSamplerCube:
2018 return "samplerCUBE";
2019 }
2020 }
2021
2022 UNIMPLEMENTED(); // FIXME
2023 return "<unknown type>";
2024}
2025
2026TString OutputHLSL::arrayString(const TType &type)
2027{
2028 if (!type.isArray())
2029 {
2030 return "";
2031 }
2032
daniel@transgaming.com005c7392010-04-15 20:45:27 +00002033 return "[" + str(type.getArraySize()) + "]";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002034}
2035
2036TString OutputHLSL::initializer(const TType &type)
2037{
2038 TString string;
2039
2040 int arraySize = type.isArray() ? type.getArraySize() : 1;
2041
2042 if (type.isArray())
2043 {
2044 string += "{";
2045 }
2046
2047 for (int element = 0; element < arraySize; element++)
2048 {
2049 string += typeString(type) + "(";
2050
daniel@transgaming.com7127f202010-04-15 20:45:22 +00002051 for (int component = 0; component < type.getInstanceSize(); component++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002052 {
2053 string += "0";
2054
daniel@transgaming.com7127f202010-04-15 20:45:22 +00002055 if (component < type.getInstanceSize() - 1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002056 {
2057 string += ", ";
2058 }
2059 }
2060
2061 string += ")";
2062
2063 if (element < arraySize - 1)
2064 {
2065 string += ", ";
2066 }
2067 }
2068
2069 if (type.isArray())
2070 {
2071 string += "}";
2072 }
2073
2074 return string;
2075}
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002076
daniel@transgaming.com63691862010-04-29 03:32:42 +00002077bool OutputHLSL::CompareConstructor::operator()(const Constructor &x, const Constructor &y) const
2078{
daniel@transgaming.com63691862010-04-29 03:32:42 +00002079 if (x.name != y.name)
2080 {
2081 return x.name < y.name;
2082 }
2083
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002084 if (x.type != y.type)
2085 {
2086 return memcmp(&x.type, &y.type, sizeof(TType)) < 0;
2087 }
2088
daniel@transgaming.com63691862010-04-29 03:32:42 +00002089 if (x.parameters.size() != y.parameters.size())
2090 {
2091 return x.parameters.size() < y.parameters.size();
2092 }
2093
2094 for (unsigned int i = 0; i < x.parameters.size(); i++)
2095 {
2096 if (x.parameters[i] != y.parameters[i])
2097 {
2098 return memcmp(&x.parameters[i], &y.parameters[i], sizeof(TType)) < 0;
2099 }
2100 }
2101
2102 return false;
2103}
2104
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002105void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
daniel@transgaming.com63691862010-04-29 03:32:42 +00002106{
2107 Constructor constructor;
2108
2109 constructor.type = type;
2110 constructor.name = name;
2111
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002112 if (parameters)
daniel@transgaming.com63691862010-04-29 03:32:42 +00002113 {
daniel@transgaming.com67de6d62010-04-29 03:35:30 +00002114 for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
2115 {
2116 constructor.parameters.push_back((*parameter)->getAsTyped()->getType());
2117 }
daniel@transgaming.com63691862010-04-29 03:32:42 +00002118 }
2119
2120 mConstructors.insert(constructor);
2121}
2122
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002123TString OutputHLSL::decorate(const TString &string)
2124{
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002125 if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002126 {
2127 return "_" + string;
2128 }
2129 else
2130 {
2131 return string;
2132 }
2133}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002134}