blob: 719802b242bb0bc3def73fe52f34125fea006990 [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
7#include "OutputHLSL.h"
8
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +00009#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000010#include "InfoSink.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
12namespace sh
13{
14OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), context(context)
15{
16}
17
18void OutputHLSL::header()
19{
20 EShLanguage language = context.language;
21 TInfoSinkBase &out = context.infoSink.obj;
22
23 if (language == EShLangFragment)
24 {
25 TString uniforms;
26 TString varyingInput;
27 TString varyingGlobals;
28
29 TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
30 int semanticIndex = 0;
31
32 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
33 {
34 const TSymbol *symbol = (*namedSymbol).second;
35 const TString &name = symbol->getName();
36
37 if (symbol->isVariable())
38 {
39 const TVariable *variable = static_cast<const TVariable*>(symbol);
40 const TType &type = variable->getType();
41 TQualifier qualifier = type.getQualifier();
42
43 if (qualifier == EvqUniform)
44 {
45 uniforms += "uniform " + typeString(type) + " " + name + arrayString(type) + ";\n";
46 }
47 else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
48 {
49 char semantic[100];
50 sprintf(semantic, " : TEXCOORD%d", semanticIndex);
51 semanticIndex += type.isArray() ? type.getArraySize() : 1;
52
53 varyingInput += " " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
54 varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
55 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +000056 else if (qualifier == EvqConst)
57 {
58 // Constants are repeated as literals where used
59 }
60 else UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000061 }
62 }
63
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +000064 out << "uniform float4 gl_Window;\n"
65 "uniform float2 gl_Depth;\n"
daniel@transgaming.com79b820b2010-03-16 05:48:57 +000066 "uniform bool __frontCCW;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +000067 "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068 out << uniforms;
daniel@transgaming.com86487c22010-03-11 19:41:43 +000069 out << "\n"
70 "struct PS_INPUT\n" // FIXME: Prevent name clashes
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000071 "{\n";
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +000072 out << varyingInput;
daniel@transgaming.com79b820b2010-03-16 05:48:57 +000073 out << " float4 gl_FragCoord : TEXCOORD" << HLSL_FRAG_COORD_SEMANTIC << ";\n";
74 out << " float __vFace : VFACE;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +000075 "};\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000076 "\n";
77 out << varyingGlobals;
78 out << "\n"
79 "struct PS_OUTPUT\n" // FIXME: Prevent name clashes
80 "{\n"
81 " float4 gl_Color[1] : COLOR;\n"
82 "};\n"
83 "\n"
84 "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +000085 "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"
daniel@transgaming.com79b820b2010-03-16 05:48:57 +000086 "static bool gl_FrontFacing = false;\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087 "\n"
88 "float4 gl_texture2D(sampler2D s, float2 t)\n"
89 "{\n"
90 " return tex2D(s, t);\n"
91 "}\n"
92 "\n"
93 "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
94 "{\n"
95 " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
96 "}\n"
97 "float4 gl_texture2DBias(sampler2D s, float2 t, float bias)\n"
98 "{\n"
99 " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
100 "}\n"
101 "\n"
102 "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
103 "{\n"
104 " return texCUBE(s, t);\n"
105 "}\n"
106 "\n";
107 }
108 else
109 {
110 TString uniforms;
111 TString attributeInput;
112 TString attributeGlobals;
113 TString varyingOutput;
114 TString varyingGlobals;
115 TString globals;
116
117 TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
118 int semanticIndex = 0;
119
120 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
121 {
122 const TSymbol *symbol = (*namedSymbol).second;
123 const TString &name = symbol->getName();
124
125 if (symbol->isVariable())
126 {
127 const TVariable *variable = static_cast<const TVariable*>(symbol);
128 const TType &type = variable->getType();
129 TQualifier qualifier = type.getQualifier();
130
131 if (qualifier == EvqUniform)
132 {
133 uniforms += "uniform " + typeString(type) + " " + name + arrayString(type) + ";\n";
134 }
135 else if (qualifier == EvqAttribute)
136 {
137 char semantic[100];
138 sprintf(semantic, " : TEXCOORD%d", semanticIndex);
139 semanticIndex += type.isArray() ? type.getArraySize() : 1;
140
141 attributeInput += " " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
142 attributeGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
143 }
144 else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
145 {
146 varyingOutput += " " + typeString(type) + " " + name + arrayString(type) + " : TEXCOORD0;\n"; // Actual semantic index assigned during link
147 varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
148 }
149 else if (qualifier == EvqGlobal)
150 {
151 globals += typeString(type) + " " + name + arrayString(type) + ";\n";
152 }
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000153 else if (qualifier == EvqConst)
154 {
155 // Constants are repeated as literals where used
156 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157 else UNREACHABLE();
158 }
159 }
160
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000161 out << "uniform float2 gl_HalfPixelSize;\n"
162 "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163 out << uniforms;
164 out << "\n";
165 out << globals;
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000166 out << "\n"
167 "struct VS_INPUT\n" // FIXME: Prevent name clashes
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168 "{\n";
169 out << attributeInput;
170 out << "};\n"
171 "\n";
172 out << attributeGlobals;
173 out << "\n"
174 "struct VS_OUTPUT\n" // FIXME: Prevent name clashes
175 "{\n"
176 " float4 gl_Position : POSITION;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000177 " float gl_PointSize : PSIZE;\n"
178 " float4 gl_FragCoord : TEXCOORD" << HLSL_FRAG_COORD_SEMANTIC << ";\n";
179 out << varyingOutput;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180 out << "};\n"
181 "\n"
182 "static float4 gl_Position = float4(0, 0, 0, 0);\n"
183 "static float gl_PointSize = float(0);\n";
184 out << varyingGlobals;
185 out << "\n";
186 }
187
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000188 out << "struct gl_DepthRangeParameters\n"
189 "{\n"
190 " float near;\n"
191 " float far;\n"
192 " float diff;\n"
193 "};\n"
194 "\n"
195 "uniform gl_DepthRangeParameters gl_DepthRange;\n"
196 "\n"
197 "float vec1(float x)\n" // FIXME: Prevent name clashes
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198 "{\n"
199 " return x;\n"
200 "}\n"
201 "\n"
202 "float vec1(float2 xy)\n" // FIXME: Prevent name clashes
203 "{\n"
204 " return xy[0];\n"
205 "}\n"
206 "\n"
207 "float vec1(float3 xyz)\n" // FIXME: Prevent name clashes
208 "{\n"
209 " return xyz[0];\n"
210 "}\n"
211 "\n"
212 "float vec1(float4 xyzw)\n" // FIXME: Prevent name clashes
213 "{\n"
214 " return xyzw[0];\n"
215 "}\n"
216 "\n"
217 "float2 vec2(float x)\n" // FIXME: Prevent name clashes
218 "{\n"
219 " return float2(x, x);\n"
220 "}\n"
221 "\n"
222 "float2 vec2(float x, float y)\n" // FIXME: Prevent name clashes
223 "{\n"
224 " return float2(x, y);\n"
225 "}\n"
226 "\n"
227 "float2 vec2(float2 xy)\n" // FIXME: Prevent name clashes
228 "{\n"
229 " return xy;\n"
230 "}\n"
231 "\n"
232 "float2 vec2(float3 xyz)\n" // FIXME: Prevent name clashes
233 "{\n"
234 " return float2(xyz[0], xyz[1]);\n"
235 "}\n"
236 "\n"
237 "float2 vec2(float4 xyzw)\n" // FIXME: Prevent name clashes
238 "{\n"
239 " return float2(xyzw[0], xyzw[1]);\n"
240 "}\n"
241 "\n"
242 "float3 vec3(float x)\n" // FIXME: Prevent name clashes
243 "{\n"
244 " return float3(x, x, x);\n"
245 "}\n"
246 "\n"
247 "float3 vec3(float x, float y, float z)\n" // FIXME: Prevent name clashes
248 "{\n"
249 " return float3(x, y, z);\n"
250 "}\n"
251 "\n"
252 "float3 vec3(float2 xy, float z)\n" // FIXME: Prevent name clashes
253 "{\n"
254 " return float3(xy[0], xy[1], z);\n"
255 "}\n"
256 "\n"
257 "float3 vec3(float x, float2 yz)\n" // FIXME: Prevent name clashes
258 "{\n"
259 " return float3(x, yz[0], yz[1]);\n"
260 "}\n"
261 "\n"
262 "float3 vec3(float3 xyz)\n" // FIXME: Prevent name clashes
263 "{\n"
264 " return xyz;\n"
265 "}\n"
266 "\n"
267 "float3 vec3(float4 xyzw)\n" // FIXME: Prevent name clashes
268 "{\n"
269 " return float3(xyzw[0], xyzw[1], xyzw[2]);\n"
270 "}\n"
271 "\n"
272 "float4 vec4(float x)\n" // FIXME: Prevent name clashes
273 "{\n"
274 " return float4(x, x, x, x);\n"
275 "}\n"
276 "\n"
277 "float4 vec4(float x, float y, float z, float w)\n" // FIXME: Prevent name clashes
278 "{\n"
279 " return float4(x, y, z, w);\n"
280 "}\n"
281 "\n"
282 "float4 vec4(float2 xy, float z, float w)\n" // FIXME: Prevent name clashes
283 "{\n"
284 " return float4(xy[0], xy[1], z, w);\n"
285 "}\n"
286 "\n"
287 "float4 vec4(float x, float2 yz, float w)\n" // FIXME: Prevent name clashes
288 "{\n"
289 " return float4(x, yz[0], yz[1], w);\n"
290 "}\n"
291 "\n"
292 "float4 vec4(float x, float y, float2 zw)\n" // FIXME: Prevent name clashes
293 "{\n"
294 " return float4(x, y, zw[0], zw[1]);\n"
295 "}\n"
296 "\n"
297 "float4 vec4(float2 xy, float2 zw)\n" // FIXME: Prevent name clashes
298 "{\n"
299 " return float4(xy[0], xy[1], zw[0], zw[1]);\n"
300 "}\n"
301 "\n"
302 "float4 vec4(float3 xyz, float w)\n" // FIXME: Prevent name clashes
303 "{\n"
304 " return float4(xyz[0], xyz[1], xyz[2], w);\n"
305 "}\n"
306 "\n"
307 "float4 vec4(float x, float3 yzw)\n" // FIXME: Prevent name clashes
308 "{\n"
309 " return float4(x, yzw[0], yzw[1], yzw[2]);\n"
310 "}\n"
311 "\n"
312 "float4 vec4(float4 xyzw)\n" // FIXME: Prevent name clashes
313 "{\n"
314 " return xyzw;\n"
315 "}\n"
316 "\n"
317 "bool xor(bool p, bool q)\n" // FIXME: Prevent name clashes
318 "{\n"
319 " return (p || q) && !(p && q);\n"
320 "}\n"
321 "\n"
322 "float mod(float x, float y)\n" // FIXME: Prevent name clashes
323 "{\n"
324 " return x - y * floor(x / y);\n"
325 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000326 "\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327 "float2 mod(float2 x, float y)\n" // FIXME: Prevent name clashes
328 "{\n"
329 " return x - y * floor(x / y);\n"
330 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000331 "\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 "float3 mod(float3 x, float y)\n" // FIXME: Prevent name clashes
333 "{\n"
334 " return x - y * floor(x / y);\n"
335 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000336 "\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337 "float4 mod(float4 x, float y)\n" // FIXME: Prevent name clashes
338 "{\n"
339 " return x - y * floor(x / y);\n"
340 "}\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000341 "\n"
342 "float faceforward(float N, float I, float Nref)\n" // FIXME: Prevent name clashes
343 "{\n"
344 " if(dot(Nref, I) < 0)\n"
345 " {\n"
346 " return N;\n"
347 " }\n"
348 " else\n"
349 " {\n"
350 " return -N;\n"
351 " }\n"
352 "}\n"
353 "\n"
354 "float2 faceforward(float2 N, float2 I, float2 Nref)\n" // FIXME: Prevent name clashes
355 "{\n"
356 " if(dot(Nref, I) < 0)\n"
357 " {\n"
358 " return N;\n"
359 " }\n"
360 " else\n"
361 " {\n"
362 " return -N;\n"
363 " }\n"
364 "}\n"
365 "\n"
366 "float3 faceforward(float3 N, float3 I, float3 Nref)\n" // FIXME: Prevent name clashes
367 "{\n"
368 " if(dot(Nref, I) < 0)\n"
369 " {\n"
370 " return N;\n"
371 " }\n"
372 " else\n"
373 " {\n"
374 " return -N;\n"
375 " }\n"
376 "}\n"
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000377 "\n"
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000378 "float4 faceforward(float4 N, float4 I, float4 Nref)\n" // FIXME: Prevent name clashes
379 "{\n"
380 " if(dot(Nref, I) < 0)\n"
381 " {\n"
382 " return N;\n"
383 " }\n"
384 " else\n"
385 " {\n"
386 " return -N;\n"
387 " }\n"
388 "}\n"
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000389 "\n"
390 "bool __equal(float2x2 m, float2x2 n)\n"
391 "{\n"
392 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
393 " m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
394 "}\n"
395 "\n"
396 "bool __equal(float3x3 m, float3x3 n)\n"
397 "{\n"
398 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
399 " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
400 " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
401 "}\n"
402 "\n"
403 "bool __equal(float4x4 m, float4x4 n)\n"
404 "{\n"
405 " 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"
406 " 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"
407 " 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"
408 " 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"
409 "}\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410 "\n";
411}
412
413void OutputHLSL::visitSymbol(TIntermSymbol *node)
414{
415 TInfoSinkBase &out = context.infoSink.obj;
416
417 TString name = node->getSymbol();
418
419 if (name == "gl_FragColor")
420 {
421 out << "gl_Color[0]";
422 }
423 else if (name == "gl_FragData")
424 {
425 out << "gl_Color";
426 }
427 else
428 {
429 out << name;
430 }
431}
432
433bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
434{
435 TInfoSinkBase &out = context.infoSink.obj;
436
437 switch (node->getOp())
438 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000439 case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
440 case EOpInitialize: outputTriplet(visit, NULL, " = ", NULL); break;
441 case EOpAddAssign: outputTriplet(visit, NULL, " += ", NULL); break;
442 case EOpSubAssign: outputTriplet(visit, NULL, " -= ", NULL); break;
daniel@transgaming.com45d03582010-03-11 19:41:29 +0000443 case EOpMulAssign: outputTriplet(visit, NULL, " *= ", NULL); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000444 case EOpVectorTimesMatrixAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix mult second child into first child"; break;
daniel@transgaming.com45d03582010-03-11 19:41:29 +0000445 case EOpVectorTimesScalarAssign: outputTriplet(visit, NULL, " *= ", NULL); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446 case EOpMatrixTimesScalarAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix scale second child into first child"; break;
447 case EOpMatrixTimesMatrixAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix mult second child into first child"; break;
daniel@transgaming.com45d03582010-03-11 19:41:29 +0000448 case EOpDivAssign: outputTriplet(visit, NULL, " /= ", NULL); break;
daniel@transgaming.com45d03582010-03-11 19:41:29 +0000449 case EOpIndexDirect: outputTriplet(visit, NULL, "[", "]"); break;
450 case EOpIndexIndirect: outputTriplet(visit, NULL, "[", "]"); break;
451 case EOpIndexDirectStruct: outputTriplet(visit, NULL, ".", NULL); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000452 case EOpVectorSwizzle:
453 if (visit == InVisit)
454 {
455 out << ".";
456
457 TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
458
459 if (swizzle)
460 {
461 TIntermSequence &sequence = swizzle->getSequence();
462
463 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
464 {
465 TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
466
467 if (element)
468 {
469 int i = element->getUnionArrayPointer()[0].getIConst();
470
471 switch (i)
472 {
473 case 0: out << "x"; break;
474 case 1: out << "y"; break;
475 case 2: out << "z"; break;
476 case 3: out << "w"; break;
477 default: UNREACHABLE();
478 }
479 }
480 else UNREACHABLE();
481 }
482 }
483 else UNREACHABLE();
484
485 return false; // Fully processed
486 }
487 break;
488 case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break;
489 case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
490 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
491 case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000492 case EOpEqual:
493 if (!node->getLeft()->isMatrix())
494 {
495 outputTriplet(visit, "(", " == ", ")");
496 }
497 else
498 {
499 outputTriplet(visit, "__equal(", ", ", ")");
500 }
501 break;
502 case EOpNotEqual:
503 if (!node->getLeft()->isMatrix())
504 {
505 outputTriplet(visit, "(", " != ", ")");
506 }
507 else
508 {
509 outputTriplet(visit, "!__equal(", ", ", ")");
510 }
511 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000512 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
513 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
514 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
515 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
516 case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
517 case EOpVectorTimesMatrix: UNIMPLEMENTED(); /* FIXME */ out << "vector-times-matrix"; break;
518 case EOpMatrixTimesVector: outputTriplet(visit, "mul(", ", ", ")"); break;
519 case EOpMatrixTimesScalar: UNIMPLEMENTED(); /* FIXME */ out << "matrix-scale"; break;
520 case EOpMatrixTimesMatrix: UNIMPLEMENTED(); /* FIXME */ out << "matrix-multiply"; break;
521 case EOpLogicalOr: outputTriplet(visit, "(", " || ", ")"); break;
522 case EOpLogicalXor: outputTriplet(visit, "xor(", ", ", ")"); break; // FIXME: Prevent name clashes
523 case EOpLogicalAnd: outputTriplet(visit, "(", " && ", ")"); break;
524 default: UNREACHABLE();
525 }
526
527 return true;
528}
529
530bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
531{
532 TInfoSinkBase &out = context.infoSink.obj;
533
534 switch (node->getOp())
535 {
536 case EOpNegative: outputTriplet(visit, "(-", NULL, ")"); break;
537 case EOpVectorLogicalNot: outputTriplet(visit, "(!", NULL, ")"); break;
538 case EOpLogicalNot: outputTriplet(visit, "(!", NULL, ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539 case EOpPostIncrement: outputTriplet(visit, "(", NULL, "++)"); break;
540 case EOpPostDecrement: outputTriplet(visit, "(", NULL, "--)"); break;
541 case EOpPreIncrement: outputTriplet(visit, "(++", NULL, ")"); break;
542 case EOpPreDecrement: outputTriplet(visit, "(--", NULL, ")"); break;
543 case EOpConvIntToBool:
544 case EOpConvFloatToBool:
545 switch (node->getOperand()->getType().getNominalSize())
546 {
547 case 1: outputTriplet(visit, "bool(", NULL, ")"); break;
548 case 2: outputTriplet(visit, "bool2(", NULL, ")"); break;
549 case 3: outputTriplet(visit, "bool3(", NULL, ")"); break;
550 case 4: outputTriplet(visit, "bool4(", NULL, ")"); break;
551 default: UNREACHABLE();
552 }
553 break;
554 case EOpConvBoolToFloat:
555 case EOpConvIntToFloat:
556 switch (node->getOperand()->getType().getNominalSize())
557 {
558 case 1: outputTriplet(visit, "float(", NULL, ")"); break;
559 case 2: outputTriplet(visit, "float2(", NULL, ")"); break;
560 case 3: outputTriplet(visit, "float3(", NULL, ")"); break;
561 case 4: outputTriplet(visit, "float4(", NULL, ")"); break;
562 default: UNREACHABLE();
563 }
564 break;
565 case EOpConvFloatToInt:
566 case EOpConvBoolToInt:
567 switch (node->getOperand()->getType().getNominalSize())
568 {
569 case 1: outputTriplet(visit, "int(", NULL, ")"); break;
570 case 2: outputTriplet(visit, "int2(", NULL, ")"); break;
571 case 3: outputTriplet(visit, "int3(", NULL, ")"); break;
572 case 4: outputTriplet(visit, "int4(", NULL, ")"); break;
573 default: UNREACHABLE();
574 }
575 break;
576 case EOpRadians: outputTriplet(visit, "radians(", NULL, ")"); break;
577 case EOpDegrees: outputTriplet(visit, "degrees(", NULL, ")"); break;
578 case EOpSin: outputTriplet(visit, "sin(", NULL, ")"); break;
579 case EOpCos: outputTriplet(visit, "cos(", NULL, ")"); break;
580 case EOpTan: outputTriplet(visit, "tan(", NULL, ")"); break;
581 case EOpAsin: outputTriplet(visit, "asin(", NULL, ")"); break;
582 case EOpAcos: outputTriplet(visit, "acos(", NULL, ")"); break;
583 case EOpAtan: outputTriplet(visit, "atan(", NULL, ")"); break;
584 case EOpExp: outputTriplet(visit, "exp(", NULL, ")"); break;
585 case EOpLog: outputTriplet(visit, "log(", NULL, ")"); break;
586 case EOpExp2: outputTriplet(visit, "exp2(", NULL, ")"); break;
587 case EOpLog2: outputTriplet(visit, "log2(", NULL, ")"); break;
588 case EOpSqrt: outputTriplet(visit, "sqrt(", NULL, ")"); break;
589 case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", NULL, ")"); break;
590 case EOpAbs: outputTriplet(visit, "abs(", NULL, ")"); break;
591 case EOpSign: outputTriplet(visit, "sign(", NULL, ")"); break;
592 case EOpFloor: outputTriplet(visit, "floor(", NULL, ")"); break;
593 case EOpCeil: outputTriplet(visit, "ceil(", NULL, ")"); break;
594 case EOpFract: outputTriplet(visit, "frac(", NULL, ")"); break;
595 case EOpLength: outputTriplet(visit, "length(", NULL, ")"); break;
596 case EOpNormalize: outputTriplet(visit, "normalize(", NULL, ")"); break;
daniel@transgaming.com45d03582010-03-11 19:41:29 +0000597// case EOpDPdx: outputTriplet(visit, "ddx(", NULL, ")"); break;
598// case EOpDPdy: outputTriplet(visit, "ddy(", NULL, ")"); break;
599// case EOpFwidth: outputTriplet(visit, "fwidth(", NULL, ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600 case EOpAny: outputTriplet(visit, "any(", NULL, ")"); break;
601 case EOpAll: outputTriplet(visit, "all(", NULL, ")"); break;
602 default: UNREACHABLE();
603 }
604
605 return true;
606}
607
608bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
609{
610 EShLanguage language = context.language;
611 TInfoSinkBase &out = context.infoSink.obj;
612
613 if (node->getOp() == EOpNull)
614 {
615 out.message(EPrefixError, "node is still EOpNull!");
616 return true;
617 }
618
619 switch (node->getOp())
620 {
621 case EOpSequence: outputTriplet(visit, NULL, ";\n", ";\n"); break;
622 case EOpDeclaration:
623 if (visit == PreVisit)
624 {
625 TIntermSequence &sequence = node->getSequence();
626 TIntermTyped *variable = sequence[0]->getAsTyped();
627 bool visit = true;
628
629 if (variable && variable->getQualifier() == EvqTemporary)
630 {
631 out << typeString(variable->getType()) + " ";
632
633 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
634 {
635 TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
636
637 if (symbol)
638 {
639 symbol->traverse(this);
640
641 out << arrayString(symbol->getType());
642 }
643 else
644 {
645 (*sit)->traverse(this);
646 }
647
648 if (visit && this->inVisit)
649 {
650 if (*sit != sequence.back())
651 {
652 visit = this->visitAggregate(InVisit, node);
653 }
654 }
655 }
656
657 if (visit && this->postVisit)
658 {
659 this->visitAggregate(PostVisit, node);
660 }
661 }
662
663 return false;
664 }
665 else if (visit == InVisit)
666 {
667 out << ", ";
668 }
669 break;
670 case EOpComma: UNIMPLEMENTED(); /* FIXME */ out << "Comma\n"; return true;
671 case EOpFunction:
672 {
673 const TString &mangledName = node->getName();
674 TString name = TString(mangledName.c_str(), mangledName.find_first_of('('));
675
676 if (visit == PreVisit)
677 {
678 if (name == "main")
679 {
680 TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
681
682 if (language == EShLangFragment)
683 {
684 out << "PS_OUTPUT main(PS_INPUT input)\n" // FIXME: Prevent name clashes
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000685 "{\n"
686 " float rhw = 1.0 / input.gl_FragCoord.w;\n"
687 " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * gl_Window.x + gl_Window.z;\n"
688 " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * gl_Window.y + gl_Window.w;\n"
689 " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * gl_Depth.x + gl_Depth.y;\n"
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000690 " gl_FragCoord.w = rhw;\n"
691 " gl_FrontFacing = __frontCCW ? (input.__vFace >= 0.0) : (input.__vFace <= 0.0);\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000692
693 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
694 {
695 const TSymbol *symbol = (*namedSymbol).second;
696 const TString &name = symbol->getName();
697
698 if (symbol->isVariable())
699 {
700 const TVariable *variable = static_cast<const TVariable*>(symbol);
701 const TType &type = variable->getType();
702 TQualifier qualifier = type.getQualifier();
703
704 if(qualifier == EvqVaryingIn)
705 {
706 out << " " + name + " = input." + name + ";\n"; // FIXME: Prevent name clashes
707 }
708 }
709 }
710 }
711 else
712 {
713 out << "VS_OUTPUT main(VS_INPUT input)\n" // FIXME: Prevent name clashes
714 "{\n";
715
716 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
717 {
718 const TSymbol *symbol = (*namedSymbol).second;
719 const TString &name = symbol->getName();
720
721 if (symbol->isVariable())
722 {
723 const TVariable *variable = static_cast<const TVariable*>(symbol);
724 const TType &type = variable->getType();
725 TQualifier qualifier = type.getQualifier();
726
727 if (qualifier == EvqAttribute)
728 {
729 out << " " + name + " = input." + name + ";\n"; // FIXME: Prevent name clashes
730 }
731 }
732 }
733 }
734
735 // Erase the (empty) argument list
736 TIntermSequence &sequence = node->getSequence();
737 sequence.erase(sequence.begin());
738 }
739 else
740 {
741 out << typeString(node->getType()) << " " << name << "(";
742
743 TIntermSequence &sequence = node->getSequence();
744 TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
745
746 for (unsigned int i = 0; i < arguments.size(); i++)
747 {
748 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
749
750 if (symbol)
751 {
752 const TType &type = symbol->getType();
753 const TString &name = symbol->getSymbol();
754
755 out << typeString(type) + " " + name;
756
757 if(i < arguments.size() - 1)
758 {
759 out << ", ";
760 }
761 }
762 else UNREACHABLE();
763 }
764
765 sequence.erase(sequence.begin());
766
767 out << ")\n"
768 "{\n";
769 }
770 }
771 else if (visit == PostVisit)
772 {
773 if (name == "main")
774 {
775 if (language == EShLangFragment)
776 {
777 out << " PS_OUTPUT output;\n" // FIXME: Prevent name clashes
778 " output.gl_Color[0] = gl_Color[0];\n"; // FIXME: Prevent name clashes
779
780 TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
781
782 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
783 {
784 const TSymbol *symbol = (*namedSymbol).second;
785 const TString &name = symbol->getName();
786 }
787 }
788 else
789 {
790 out << " VS_OUTPUT output;\n" // FIXME: Prevent name clashes
791 " output.gl_Position.x = gl_Position.x - gl_HalfPixelSize.x * gl_Position.w;\n"
792 " output.gl_Position.y = -(gl_Position.y - gl_HalfPixelSize.y * gl_Position.w);\n"
793 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
794 " output.gl_Position.w = gl_Position.w;\n"
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000795 " output.gl_PointSize = gl_PointSize;\n"
796 " output.gl_FragCoord = gl_Position;\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797
798 TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
799
800 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
801 {
802 const TSymbol *symbol = (*namedSymbol).second;
803 const TString &name = symbol->getName();
804
805 if (symbol->isVariable())
806 {
807 const TVariable *variable = static_cast<const TVariable*>(symbol);
808 TQualifier qualifier = variable->getType().getQualifier();
809
810 if(qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
811 {
812 out << " output." + name + " = " + name + ";\n"; // FIXME: Prevent name clashes
813 }
814 }
815 }
816 }
817
818 out << " return output;\n" // FIXME: Prevent name clashes
819 "}\n";
820 }
821 else
822 {
823 out << "}\n";
824 }
825 }
826 }
827 break;
828 case EOpFunctionCall:
829 {
830 if (visit == PreVisit)
831 {
832 const TString &mangledName = node->getName();
833 TString name = TString(mangledName.c_str(), mangledName.find_first_of('('));
834
835 if (node->isUserDefined())
836 {
837 out << name << "(";
838 }
839 else
840 {
841 if (name == "texture2D")
842 {
843 if (node->getSequence().size() == 2)
844 {
845 out << "gl_texture2D(";
846 }
847 else if (node->getSequence().size() == 3)
848 {
849 out << "gl_texture2DBias(";
850 }
851 else UNREACHABLE();
852 }
853 else if (name == "texture2DProj")
854 {
855 out << "gl_texture2DProj(";
856 }
857 else if (name == "texture2DLod")
858 {
859 out << "gl_texture2DLod(";
860 UNIMPLEMENTED(); // FIXME: Move lod to last texture coordinate component
861 }
862 else if (name == "texture2DProjLod")
863 {
864 out << "gl_texture2DProjLod(";
865 UNIMPLEMENTED(); // FIXME: Move lod to last texture coordinate component
866 }
867 else if (name == "textureCube")
868 {
869 out << "gl_textureCube("; // FIXME: Incorrect sampling location
870 }
871 else
872 {
873 UNIMPLEMENTED(); // FIXME
874 }
875 }
876 }
877 else if (visit == InVisit)
878 {
879 out << ", ";
880 }
881 else
882 {
883 out << ")";
884 }
885 }
886 break;
887 case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break;
888 case EOpConstructFloat: outputTriplet(visit, "vec1(", NULL, ")"); break;
889 case EOpConstructVec2: outputTriplet(visit, "vec2(", ", ", ")"); break;
890 case EOpConstructVec3: outputTriplet(visit, "vec3(", ", ", ")"); break;
891 case EOpConstructVec4: outputTriplet(visit, "vec4(", ", ", ")"); break;
892 case EOpConstructBool: UNIMPLEMENTED(); /* FIXME */ out << "Construct bool"; break;
893 case EOpConstructBVec2: UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec2"; break;
894 case EOpConstructBVec3: UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec3"; break;
895 case EOpConstructBVec4: UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec4"; break;
896 case EOpConstructInt: UNIMPLEMENTED(); /* FIXME */ out << "Construct int"; break;
897 case EOpConstructIVec2: UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec2"; break;
898 case EOpConstructIVec3: UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec3"; break;
899 case EOpConstructIVec4: UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec4"; break;
900 case EOpConstructMat2: outputTriplet(visit, "float2x2(", ", ", ")"); break;
901 case EOpConstructMat3: outputTriplet(visit, "float3x3(", ", ", ")"); break;
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000902 case EOpConstructMat4: outputTriplet(visit, "float4x4(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000903 case EOpConstructStruct: UNIMPLEMENTED(); /* FIXME */ out << "Construct structure"; break;
904 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
905 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
906 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
907 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
908 case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
909 case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
910 case EOpMod: outputTriplet(visit, "mod(", ", ", ")"); break; // FIXME: Prevent name clashes
911 case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
912 case EOpAtan:
913 if (node->getSequence().size() == 1)
914 {
915 outputTriplet(visit, "atan(", ", ", ")");
916 }
917 else if (node->getSequence().size() == 2)
918 {
919 outputTriplet(visit, "atan2(", ", ", ")");
920 }
921 else UNREACHABLE();
922 break;
923 case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
924 case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
925 case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break;
926 case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break;
927 case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break;
928 case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break;
929 case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break;
930 case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
931 case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
daniel@transgaming.com680553b2010-03-08 21:30:52 +0000932 case EOpFaceForward: outputTriplet(visit, "faceforward(", ", ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933 case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
934 case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
935 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936 default: UNREACHABLE();
937 }
938
939 return true;
940}
941
942bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
943{
944 TInfoSinkBase &out = context.infoSink.obj;
945
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +0000946 if(node->getType().getBasicType() == EbtVoid) // if/else statement
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947 {
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +0000948 out << "if(";
949
950 node->getCondition()->traverse(this);
951
952 out << ")\n"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953 "{\n";
954
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +0000955 node->getTrueBlock()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956
957 out << ";}\n";
daniel@transgaming.com3d53fda2010-03-21 04:30:55 +0000958
959 if (node->getFalseBlock())
960 {
961 out << "else\n"
962 "{\n";
963
964 node->getFalseBlock()->traverse(this);
965
966 out << ";}\n";
967 }
968 }
969 else // Ternary operator expression
970 {
971 out << "(";
972 node->getCondition()->traverse(this);
973 out << ") ? (";
974 node->getTrueBlock()->traverse(this);
975 out << ") : (";
976 node->getFalseBlock()->traverse(this);
977 out << ")\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000978 }
979
980 return false;
981}
982
983void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
984{
985 TInfoSinkBase &out = context.infoSink.obj;
986
daniel@transgaming.com45d03582010-03-11 19:41:29 +0000987 TType &type = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000989 if (type.isField())
990 {
991 out << type.getFieldName();
992 }
993 else
994 {
995 int size = type.getObjectSize();
996 bool matrix = type.isMatrix();
997 TBasicType basicType = node->getUnionArrayPointer()[0].getType();
998
999 switch (basicType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001000 {
1001 case EbtBool:
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001002 if (!matrix)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003 {
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001004 switch (size)
1005 {
1006 case 1: out << "bool("; break;
1007 case 2: out << "bool2("; break;
1008 case 3: out << "bool3("; break;
1009 case 4: out << "bool4("; break;
1010 default: UNREACHABLE();
1011 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012 }
1013 else
1014 {
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001015 UNIMPLEMENTED();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001016 }
1017 break;
1018 case EbtFloat:
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001019 if (!matrix)
1020 {
1021 switch (size)
1022 {
1023 case 1: out << "float("; break;
1024 case 2: out << "float2("; break;
1025 case 3: out << "float3("; break;
1026 case 4: out << "float4("; break;
1027 default: UNREACHABLE();
1028 }
1029 }
1030 else
1031 {
1032 switch (size)
1033 {
1034 case 4: out << "float2x2("; break;
1035 case 9: out << "float3x3("; break;
1036 case 16: out << "float4x4("; break;
1037 default: UNREACHABLE();
1038 }
1039 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001040 break;
1041 case EbtInt:
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001042 if (!matrix)
1043 {
1044 switch (size)
1045 {
1046 case 1: out << "int("; break;
1047 case 2: out << "int2("; break;
1048 case 3: out << "int3("; break;
1049 case 4: out << "int4("; break;
1050 default: UNREACHABLE();
1051 }
1052 }
1053 else
1054 {
1055 UNIMPLEMENTED();
1056 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001057 break;
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001058 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001059 UNIMPLEMENTED(); // FIXME
1060 }
1061
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001062 for (int i = 0; i < size; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001063 {
daniel@transgaming.com45d03582010-03-11 19:41:29 +00001064 switch (basicType)
1065 {
1066 case EbtBool:
1067 if (node->getUnionArrayPointer()[i].getBConst())
1068 {
1069 out << "true";
1070 }
1071 else
1072 {
1073 out << "false";
1074 }
1075 break;
1076 case EbtFloat:
1077 out << node->getUnionArrayPointer()[i].getFConst();
1078 break;
1079 case EbtInt:
1080 out << node->getUnionArrayPointer()[i].getIConst();
1081 break;
1082 default:
1083 UNIMPLEMENTED(); // FIXME
1084 }
1085
1086 if (i != size - 1)
1087 {
1088 out << ", ";
1089 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001090 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001091
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001092 out << ")";
1093 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001094}
1095
1096bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
1097{
1098 TInfoSinkBase &out = context.infoSink.obj;
1099
1100 if (!node->testFirst())
1101 {
1102 out << "do\n"
1103 "{\n";
1104 }
1105 else
1106 {
1107 out << "for(";
1108
1109 if (node->getInit())
1110 {
1111 node->getInit()->traverse(this);
1112 }
1113
1114 out << "; ";
1115
1116 if (node->getTest())
1117 {
1118 node->getTest()->traverse(this);
1119 }
1120
1121 out << "; ";
1122
1123 if (node->getTerminal())
1124 {
1125 node->getTerminal()->traverse(this);
1126 }
1127
1128 out << ")\n"
1129 "{\n";
1130 }
1131
1132 if (node->getBody())
1133 {
1134 node->getBody()->traverse(this);
1135 }
1136
1137 out << "}\n";
1138
1139 if (!node->testFirst())
1140 {
1141 out << "while(\n";
1142
1143 node->getTest()->traverse(this);
1144
1145 out << ")";
1146 }
1147
1148 out << ";\n";
1149
1150 return false;
1151}
1152
1153bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
1154{
1155 TInfoSinkBase &out = context.infoSink.obj;
1156
1157 switch (node->getFlowOp())
1158 {
daniel@transgaming.comf67f82e2010-03-17 03:58:54 +00001159 case EOpKill: outputTriplet(visit, "discard", NULL, NULL); break;
1160 case EOpBreak: outputTriplet(visit, "break", NULL, NULL); break;
1161 case EOpContinue: outputTriplet(visit, "continue", NULL, NULL); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001162 case EOpReturn:
1163 if (visit == PreVisit)
1164 {
1165 if (node->getExpression())
1166 {
1167 out << "return ";
1168 }
1169 else
1170 {
1171 out << "return;\n";
1172 }
1173 }
1174 else if (visit == PostVisit)
1175 {
1176 out << ";\n";
1177 }
1178 break;
1179 default: UNREACHABLE();
1180 }
1181
1182 return true;
1183}
1184
1185void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString)
1186{
1187 TInfoSinkBase &out = context.infoSink.obj;
1188
1189 if (visit == PreVisit && preString)
1190 {
1191 out << preString;
1192 }
1193 else if (visit == InVisit && inString)
1194 {
1195 out << inString;
1196 }
1197 else if (visit == PostVisit && postString)
1198 {
1199 out << postString;
1200 }
1201}
1202
1203TString OutputHLSL::typeString(const TType &type)
1204{
1205 if (type.isMatrix())
1206 {
1207 switch (type.getNominalSize())
1208 {
1209 case 2: return "float2x2";
1210 case 3: return "float3x3";
1211 case 4: return "float4x4";
1212 }
1213 }
1214 else
1215 {
1216 switch (type.getBasicType())
1217 {
1218 case EbtFloat:
1219 switch (type.getNominalSize())
1220 {
1221 case 1: return "float";
1222 case 2: return "float2";
1223 case 3: return "float3";
1224 case 4: return "float4";
1225 }
1226 case EbtInt:
1227 switch (type.getNominalSize())
1228 {
1229 case 1: return "int";
1230 case 2: return "int2";
1231 case 3: return "int3";
1232 case 4: return "int4";
1233 }
1234 case EbtBool:
1235 switch (type.getNominalSize())
1236 {
1237 case 1: return "bool";
1238 case 2: return "bool2";
1239 case 3: return "bool3";
1240 case 4: return "bool4";
1241 }
1242 case EbtVoid:
1243 return "void";
1244 case EbtSampler2D:
1245 return "sampler2D";
1246 case EbtSamplerCube:
1247 return "samplerCUBE";
1248 }
1249 }
1250
1251 UNIMPLEMENTED(); // FIXME
1252 return "<unknown type>";
1253}
1254
1255TString OutputHLSL::arrayString(const TType &type)
1256{
1257 if (!type.isArray())
1258 {
1259 return "";
1260 }
1261
1262 char buffer[100];
1263 sprintf(buffer, "[%d]", type.getArraySize());
1264
1265 return buffer;
1266}
1267
1268TString OutputHLSL::initializer(const TType &type)
1269{
1270 TString string;
1271
1272 int arraySize = type.isArray() ? type.getArraySize() : 1;
1273
1274 if (type.isArray())
1275 {
1276 string += "{";
1277 }
1278
1279 for (int element = 0; element < arraySize; element++)
1280 {
1281 string += typeString(type) + "(";
1282
1283 for (int component = 0; component < type.getNominalSize(); component++)
1284 {
1285 string += "0";
1286
1287 if (component < type.getNominalSize() - 1)
1288 {
1289 string += ", ";
1290 }
1291 }
1292
1293 string += ")";
1294
1295 if (element < arraySize - 1)
1296 {
1297 string += ", ";
1298 }
1299 }
1300
1301 if (type.isArray())
1302 {
1303 string += "}";
1304 }
1305
1306 return string;
1307}
1308}