1 //=============================================================================
2 //
3 // Render/GLSLGenerator.cpp
4 //
5 // Created by Max McGuire (max@unknownworlds.com)
6 // Copyright (c) 2013, Unknown Worlds Entertainment, Inc.
7 //
8 //=============================================================================
9 
10 #include "GLSLGenerator.h"
11 #include "HLSLParser.h"
12 #include "HLSLTree.h"
13 
14 //#include "Engine/String.h"
15 //#include "Engine/Log.h"
16 #include "Engine.h"
17 
18 #include <stdarg.h>
19 #include <string.h>
20 #include <vector>
21 #include <algorithm>
22 #include <string>
23 
24 namespace M4
25 {
26 
27 static const HLSLType kFloatType(HLSLBaseType_Float);
28 static const HLSLType kUintType(HLSLBaseType_Uint);
29 static const HLSLType kIntType(HLSLBaseType_Int);
30 static const HLSLType kBoolType(HLSLBaseType_Bool);
31 
32 // These are reserved words in GLSL that aren't reserved in HLSL.
33 const char* GLSLGenerator::s_reservedWord[] =
34     {
35         "output",
36         "input",
37         "mod",
38         "mix",
39         "fract",
40         "dFdx",
41         "dFdy",
42         "filter",
43 		"main",
44     };
45 
GetTypeName(const HLSLType & type)46 static const char* GetTypeName(const HLSLType& type)
47 {
48     switch (type.baseType)
49     {
50     case HLSLBaseType_Void:         return "void";
51     case HLSLBaseType_Float:        return "float";
52     case HLSLBaseType_Float2:       return "vec2";
53     case HLSLBaseType_Float3:       return "vec3";
54     case HLSLBaseType_Float4:       return "vec4";
55     case HLSLBaseType_Float2x4:     return "mat4x2";
56     case HLSLBaseType_Float2x3:     return "mat3x2";
57     case HLSLBaseType_Float2x2:     return "mat2";
58     case HLSLBaseType_Float3x4:     return "mat4x3";
59     case HLSLBaseType_Float3x3:     return "mat3";
60     case HLSLBaseType_Float3x2:     return "mat2x3";
61     case HLSLBaseType_Float4x4:     return "mat4";
62     case HLSLBaseType_Float4x3:     return "mat3x4";
63     case HLSLBaseType_Float4x2:     return "mat2x4";
64     case HLSLBaseType_Bool:         return "bool";
65 	case HLSLBaseType_Bool2:        return "bvec2";
66 	case HLSLBaseType_Bool3:        return "bvec3";
67 	case HLSLBaseType_Bool4:        return "bvec4";
68     case HLSLBaseType_Int:          return "int";
69     case HLSLBaseType_Int2:         return "ivec2";
70     case HLSLBaseType_Int3:         return "ivec3";
71     case HLSLBaseType_Int4:         return "ivec4";
72     case HLSLBaseType_Uint:         return "uint";
73     case HLSLBaseType_Uint2:        return "uvec2";
74     case HLSLBaseType_Uint3:        return "uvec3";
75     case HLSLBaseType_Uint4:        return "uvec4";
76     case HLSLBaseType_Texture:      return "texture";
77     case HLSLBaseType_Sampler:      return "sampler";
78     case HLSLBaseType_Sampler2D:    return "sampler2D";
79     case HLSLBaseType_Sampler3D:    return "sampler3D";
80     case HLSLBaseType_SamplerCube:  return "samplerCube";
81     case HLSLBaseType_Sampler2DMS:  return "sampler2DMS";
82     case HLSLBaseType_Sampler2DArray:  return "sampler2DArray";
83     case HLSLBaseType_UserDefined:  return type.typeName;
84     default:
85         ASSERT(0);
86         return "?";
87     }
88 }
89 
GetCanImplicitCast(const HLSLType & srcType,const HLSLType & dstType)90 static bool GetCanImplicitCast(const HLSLType& srcType, const HLSLType& dstType)
91 {
92     return srcType.baseType == dstType.baseType;
93 }
94 
GetFunctionArguments(HLSLFunctionCall * functionCall,HLSLExpression * expression[],int maxArguments)95 static int GetFunctionArguments(HLSLFunctionCall* functionCall, HLSLExpression* expression[], int maxArguments)
96 {
97     HLSLExpression* argument = functionCall->argument;
98     int numArguments = 0;
99     while (argument != NULL)
100     {
101         if (numArguments < maxArguments)
102         {
103             expression[numArguments] = argument;
104         }
105         argument = argument->nextExpression;
106         ++numArguments;
107     }
108     return numArguments;
109 }
110 
GLSLGenerator()111 GLSLGenerator::GLSLGenerator() :
112     m_writer(/* writeFileNames= */ false)
113 {
114     m_tree                      = NULL;
115     m_entryName                 = NULL;
116     m_target                    = Target_VertexShader;
117     m_version                   = Version_330;
118     m_versionLegacy             = false;
119     m_inAttribPrefix            = NULL;
120     m_outAttribPrefix           = NULL;
121     m_error                     = false;
122     m_matrixRowFunction[0]      = 0;
123     m_matrixCtorFunction[0]     = 0;
124     m_matrixMulFunction[0]      = 0;
125     m_clipFunction[0]           = 0;
126     m_tex2DlodFunction[0]       = 0;
127     m_tex2DbiasFunction[0]      = 0;
128     m_tex3DlodFunction[0]       = 0;
129     m_texCUBEbiasFunction[0]    = 0;
130 	m_texCUBElodFunction[ 0 ] 	= 0;
131     m_scalarSwizzle2Function[0] = 0;
132     m_scalarSwizzle3Function[0] = 0;
133     m_scalarSwizzle4Function[0] = 0;
134     m_sinCosFunction[0]         = 0;
135 	m_bvecTernary[ 0 ]			= 0;
136     m_modfFunction[0]           = 0;
137     m_outputPosition            = false;
138     m_outputTargets             = 0;
139 }
140 
Generate(HLSLTree * tree,Target target,Version version,const char * entryName,const Options & options)141 bool GLSLGenerator::Generate(HLSLTree* tree, Target target, Version version, const char* entryName, const Options& options)
142 {
143 
144     m_tree      = tree;
145     m_entryName = entryName;
146     m_target    = target;
147     m_version   = version;
148     m_versionLegacy = (version == Version_110 || version == Version_120 || version == Version_100_ES);
149     m_options   = options;
150 
151     globalVarsAssignments.clear();
152 
153     ChooseUniqueName("matrix_row", m_matrixRowFunction, sizeof(m_matrixRowFunction));
154     ChooseUniqueName("matrix_ctor", m_matrixCtorFunction, sizeof(m_matrixCtorFunction));
155     ChooseUniqueName("matrix_mul", m_matrixMulFunction, sizeof(m_matrixMulFunction));
156     ChooseUniqueName("clip", m_clipFunction, sizeof(m_clipFunction));
157     ChooseUniqueName("tex2Dlod", m_tex2DlodFunction, sizeof(m_tex2DlodFunction));
158     ChooseUniqueName("tex2Dbias", m_tex2DbiasFunction, sizeof(m_tex2DbiasFunction));
159     ChooseUniqueName("tex2Dgrad", m_tex2DgradFunction, sizeof(m_tex2DgradFunction));
160     ChooseUniqueName("tex3Dlod", m_tex3DlodFunction, sizeof(m_tex3DlodFunction));
161     ChooseUniqueName("texCUBEbias", m_texCUBEbiasFunction, sizeof(m_texCUBEbiasFunction));
162 	ChooseUniqueName( "texCUBElod", m_texCUBElodFunction, sizeof( m_texCUBElodFunction ) );
163 	ChooseUniqueName( "modf", m_modfFunction, sizeof( m_modfFunction ) );
164 
165     for (int i = 0; i < s_numReservedWords; ++i)
166     {
167         ChooseUniqueName( s_reservedWord[i], m_reservedWord[i], sizeof(m_reservedWord[i]) );
168     }
169 
170     ChooseUniqueName("m_scalar_swizzle2", m_scalarSwizzle2Function, sizeof(m_scalarSwizzle2Function));
171     ChooseUniqueName("m_scalar_swizzle3", m_scalarSwizzle3Function, sizeof(m_scalarSwizzle3Function));
172     ChooseUniqueName("m_scalar_swizzle4", m_scalarSwizzle4Function, sizeof(m_scalarSwizzle4Function));
173 
174     ChooseUniqueName("sincos", m_sinCosFunction, sizeof(m_sinCosFunction));
175 
176 	ChooseUniqueName( "bvecTernary", m_bvecTernary, sizeof( m_bvecTernary ) );
177 
178     if (target == Target_VertexShader)
179     {
180         m_inAttribPrefix  = "";
181         m_outAttribPrefix = "frag_";
182     }
183     else
184     {
185         m_inAttribPrefix  = "frag_";
186         m_outAttribPrefix = "rast_";
187     }
188 
189     m_tree->ReplaceUniformsAssignments();
190 
191     HLSLRoot* root = m_tree->GetRoot();
192     HLSLStatement* statement = root->statement;
193 
194     // Find the entry point function.
195     HLSLFunction* entryFunction = FindFunction(root, m_entryName);
196     if (entryFunction == NULL)
197     {
198         Error("Entry point '%s' doesn't exist", m_entryName);
199         return false;
200     }
201 
202     if (m_version == Version_110)
203     {
204         m_writer.WriteLine(0, "#version 110");
205     }
206     if (m_version == Version_120)
207     {
208         m_writer.WriteLine(0, "#version 120");
209     }
210     else if (m_version == Version_140)
211     {
212         m_writer.WriteLine(0, "#version 140");
213 
214         // Pragmas for NVIDIA.
215         m_writer.WriteLine(0, "#pragma optionNV(fastmath on)");
216         //m_writer.WriteLine(0, "#pragma optionNV(fastprecision on)");
217         m_writer.WriteLine(0, "#pragma optionNV(ifcvt none)");
218         m_writer.WriteLine(0, "#pragma optionNV(inline all)");
219         m_writer.WriteLine(0, "#pragma optionNV(strict on)");
220         m_writer.WriteLine(0, "#pragma optionNV(unroll all)");
221     }
222     else if (m_version == Version_150)
223     {
224         m_writer.WriteLine(0, "#version 150");
225     }
226     else if (m_version == Version_330)
227     {
228         m_writer.WriteLine(0, "#version 330");
229     }
230     else if (m_version == Version_100_ES)
231     {
232         m_writer.WriteLine(0, "#version 100");
233         m_writer.WriteLine(0, "precision highp float;");
234     }
235     else if (m_version == Version_300_ES)
236     {
237         m_writer.WriteLine(0, "#version 300 es");
238         m_writer.WriteLine(0, "precision highp float;");
239         m_writer.WriteLine(0, "precision highp sampler3D;");
240     }
241     else
242     {
243         Error("Unrecognized target version");
244         return false;
245     }
246 
247     // Output the special function used to access rows in a matrix.
248     m_writer.WriteLine(0, "vec2 %s(mat2 m, int i) { return vec2( m[0][i], m[1][i] ); }", m_matrixRowFunction);
249     m_writer.WriteLine(0, "vec3 %s(mat3 m, int i) { return vec3( m[0][i], m[1][i], m[2][i] ); }", m_matrixRowFunction);
250     m_writer.WriteLine(0, "vec4 %s(mat4 m, int i) { return vec4( m[0][i], m[1][i], m[2][i], m[3][i] ); }", m_matrixRowFunction);
251 
252     // Output the special function used to do matrix cast for OpenGL 2.0
253     if (m_versionLegacy)
254     {
255         m_writer.WriteLine(0, "mat3 %s(mat4 m) { return mat3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); }", m_matrixCtorFunction);
256     }
257 
258     // Output the special functions used for matrix multiplication lowering
259     // They make sure glsl-optimizer can fold expressions better
260     if (m_tree->NeedsFunction("mul") && (m_options.flags & Flag_LowerMatrixMultiplication))
261     {
262         m_writer.WriteLine(0, "vec2 %s(mat2 m, vec2 v) { return m[0] * v.x + m[1] * v.y; }", m_matrixMulFunction);
263         m_writer.WriteLine(0, "vec2 %s(vec2 v, mat2 m) { return vec2(dot(m[0], v), dot(m[1], v)); }", m_matrixMulFunction);
264         m_writer.WriteLine(0, "vec3 %s(mat3 m, vec3 v) { return m[0] * v.x + m[1] * v.y + m[2] * v.z; }", m_matrixMulFunction);
265         m_writer.WriteLine(0, "vec3 %s(vec3 v, mat3 m) { return vec3(dot(m[0], v), dot(m[1], v), dot(m[2], v)); }", m_matrixMulFunction);
266         m_writer.WriteLine(0, "vec4 %s(mat4 m, vec4 v) { return m[0] * v.x + m[1] * v.y + m[2] * v.z + m[3] * v.w; }", m_matrixMulFunction);
267         m_writer.WriteLine(0, "vec4 %s(vec4 v, mat4 m) { return vec4(dot(m[0], v), dot(m[1], v), dot(m[2], v), dot(m[3], v)); }", m_matrixMulFunction);
268     }
269 
270     // Output the special function used to emulate HLSL clip.
271     if (m_tree->NeedsFunction("clip"))
272     {
273         const char* discard = m_target == Target_FragmentShader ? "discard" : "";
274         m_writer.WriteLine(0, "void %s(float x) { if (x < 0.0) %s;  }", m_clipFunction, discard);
275         m_writer.WriteLine(0, "void %s(vec2  x) { if (any(lessThan(x, vec2(0.0, 0.0)))) %s;  }", m_clipFunction, discard);
276         m_writer.WriteLine(0, "void %s(vec3  x) { if (any(lessThan(x, vec3(0.0, 0.0, 0.0)))) %s;  }", m_clipFunction, discard);
277         m_writer.WriteLine(0, "void %s(vec4  x) { if (any(lessThan(x, vec4(0.0, 0.0, 0.0, 0.0)))) %s;  }", m_clipFunction, discard);
278     }
279 
280     // Output the special function used to emulate tex2Dlod.
281     if (m_tree->NeedsFunction("tex2Dlod"))
282     {
283         const char* function = "textureLod";
284 
285         if (m_versionLegacy)
286         {
287             m_writer.WriteLine(0, "#extension GL_ARB_shader_texture_lod : require");
288             function = "texture2DLod";
289         }
290         else if (m_version == Version_100_ES)
291         {
292             m_writer.WriteLine(0, "#extension GL_EXT_shader_texture_lod : require");
293             function = "texture2DLodEXT";
294         }
295 
296         m_writer.WriteLine(0, "vec4 %s(sampler2D samp, vec4 texCoord) { return %s(samp, texCoord.xy, texCoord.w);  }", m_tex2DlodFunction, function);
297     }
298 
299     // Output the special function used to emulate tex2Dgrad.
300     if (m_tree->NeedsFunction("tex2Dgrad"))
301     {
302         const char* function = "textureGrad";
303 
304         if (m_versionLegacy)
305         {
306             m_writer.WriteLine(0, "#extension GL_ARB_shader_texture_lod : require");
307             function = "texture2DGradARB";
308         }
309         else if (m_version == Version_100_ES)
310         {
311             m_writer.WriteLine(0, "#extension GL_EXT_shader_texture_lod : require");
312             function = "texture2DGradEXT";
313         }
314 
315         m_writer.WriteLine(0, "vec4 %s(sampler2D samp, vec2 texCoord, vec2 dx, vec2 dy) { return %s(samp, texCoord, dx, dy);  }", m_tex2DgradFunction, function);
316     }
317 
318     // Output the special function used to emulate tex2Dbias.
319     if (m_tree->NeedsFunction("tex2Dbias"))
320     {
321         if (target == Target_FragmentShader)
322         {
323             m_writer.WriteLine(0, "vec4 %s(sampler2D samp, vec4 texCoord) { return %s(samp, texCoord.xy, texCoord.w);  }", m_tex2DbiasFunction, m_versionLegacy ? "texture2D" : "texture" );
324         }
325         else
326         {
327             // Bias value is not supported in vertex shader.
328             m_writer.WriteLine(0, "vec4 %s(sampler2D samp, vec4 texCoord) { return texture(samp, texCoord.xy);  }", m_tex2DbiasFunction );
329         }
330     }
331 
332     // Output the special function used to emulate tex2DMSfetch.
333     if (m_tree->NeedsFunction("tex2DMSfetch"))
334     {
335         m_writer.WriteLine(0, "vec4 tex2DMSfetch(sampler2DMS samp, ivec2 texCoord, int sample) {");
336         m_writer.WriteLine(1, "return texelFetch(samp, texCoord, sample);");
337         m_writer.WriteLine(0, "}");
338     }
339 
340     // Output the special function used to emulate tex3Dlod.
341     if (m_tree->NeedsFunction("tex3Dlod"))
342     {
343         m_writer.WriteLine(0, "vec4 %s(sampler3D samp, vec4 texCoord) { return %s(samp, texCoord.xyz, texCoord.w);  }", m_tex3DlodFunction, m_versionLegacy ? "texture3D" : "texture" );
344     }
345 
346     // Output the special function used to emulate texCUBEbias.
347     if (m_tree->NeedsFunction("texCUBEbias"))
348     {
349         if (target == Target_FragmentShader)
350         {
351             m_writer.WriteLine(0, "vec4 %s(samplerCube samp, vec4 texCoord) { return %s(samp, texCoord.xyz, texCoord.w);  }", m_texCUBEbiasFunction, m_versionLegacy ? "textureCube" : "texture" );
352         }
353         else
354         {
355             // Bias value is not supported in vertex shader.
356             m_writer.WriteLine(0, "vec4 %s(samplerCube samp, vec4 texCoord) { return texture(samp, texCoord.xyz);  }", m_texCUBEbiasFunction );
357         }
358     }
359 
360 	// Output the special function used to emulate texCUBElod
361 	if (m_tree->NeedsFunction("texCUBElod"))
362 	{
363         const char* function = "textureLod";
364 
365         if (m_version == Version_110 || m_version == Version_120)
366         {
367             m_writer.WriteLine(0, "#extension GL_ARB_shader_texture_lod : require");
368             function = "textureCubeLod";
369         }
370         else if (m_version == Version_100_ES)
371         {
372             m_writer.WriteLine(0, "#extension GL_EXT_shader_texture_lod : require");
373             function = "textureCubeLodEXT";
374         }
375 
376 		m_writer.WriteLine( 0, "vec4 %s(samplerCube samp, vec4 texCoord) { return %s(samp, texCoord.xyz, texCoord.w);  }", m_texCUBElodFunction, function);
377 	}
378 
379     if (m_tree->NeedsFunction("modf"))
380     {
381         if (m_version == Version_110 || m_version == Version_120 || m_version == Version_100_ES)
382         {
383             m_writer.WriteLine(0, "float %s(float x, out int ip) { ip = int(x); return x - ip; }", m_modfFunction);
384         } else {
385             m_writer.WriteLine(0, "float %s(float x, out int ip) { return modf(x, ip); }", m_modfFunction);
386         }
387     }
388 
389     m_writer.WriteLine(0, "vec2  %s(float x) { return  vec2(x, x); }", m_scalarSwizzle2Function);
390     m_writer.WriteLine(0, "ivec2 %s(int   x) { return ivec2(x, x); }", m_scalarSwizzle2Function);
391 
392     m_writer.WriteLine(0, "vec3  %s(float x) { return  vec3(x, x, x); }", m_scalarSwizzle3Function);
393     m_writer.WriteLine(0, "ivec3 %s(int   x) { return ivec3(x, x, x); }", m_scalarSwizzle3Function);
394 
395     m_writer.WriteLine(0, "vec4  %s(float x) { return  vec4(x, x, x, x); }", m_scalarSwizzle4Function);
396     m_writer.WriteLine(0, "ivec4 %s(int   x) { return ivec4(x, x, x, x); }", m_scalarSwizzle4Function);
397 
398     if (!m_versionLegacy)
399     {
400         m_writer.WriteLine(0, "uvec2 %s(uint  x) { return uvec2(x, x); }", m_scalarSwizzle2Function);
401         m_writer.WriteLine(0, "uvec3 %s(uint  x) { return uvec3(x, x, x); }", m_scalarSwizzle3Function);
402         m_writer.WriteLine(0, "uvec4 %s(uint  x) { return uvec4(x, x, x, x); }", m_scalarSwizzle4Function);
403     }
404 
405     if (m_tree->NeedsFunction("sincos"))
406     {
407         const char* floatTypes[] = { "float", "vec2", "vec3", "vec4" };
408         for (int i = 0; i < 4; ++i)
409         {
410             m_writer.WriteLine(0, "void %s(%s x, out %s s, out %s c) { s = sin(x); c = cos(x); }", m_sinCosFunction,
411                 floatTypes[i], floatTypes[i], floatTypes[i]);
412         }
413     }
414 
415 	// special function to emulate ?: with bool{2,3,4} condition type
416 	m_writer.WriteLine( 0, "vec2 %s(bvec2 cond, vec2 trueExpr, vec2 falseExpr) { vec2 ret; ret.x = cond.x ? trueExpr.x : falseExpr.x; ret.y = cond.y ? trueExpr.y : falseExpr.y; return ret; }", m_bvecTernary );
417 	m_writer.WriteLine( 0, "vec3 %s(bvec3 cond, vec3 trueExpr, vec3 falseExpr) { vec3 ret; ret.x = cond.x ? trueExpr.x : falseExpr.x; ret.y = cond.y ? trueExpr.y : falseExpr.y; ret.z = cond.z ? trueExpr.z : falseExpr.z; return ret; }", m_bvecTernary );
418 	m_writer.WriteLine( 0, "vec4 %s(bvec4 cond, vec4 trueExpr, vec4 falseExpr) { vec4 ret; ret.x = cond.x ? trueExpr.x : falseExpr.x; ret.y = cond.y ? trueExpr.y : falseExpr.y; ret.z = cond.z ? trueExpr.z : falseExpr.z; ret.w = cond.w ? trueExpr.w : falseExpr.w; return ret; }", m_bvecTernary );
419 
420     m_tree->EnumerateMatrixCtorsNeeded(matrixCtors);
421     for(matrixCtor & ctor : matrixCtors)
422     {
423         std::string id = GetTypeName(HLSLType(ctor.matrixType));
424         id += "_from";
425         for(HLSLBaseType argType : ctor.argumentTypes)
426         {
427             id += "_";
428             id += GetTypeName(HLSLType(argType));
429         }
430         matrixCtorsId[ctor] = id;
431     }
432 
433     OutputMatrixCtors();
434 
435     // Output the extension used for dFdx/dFdy in GLES2
436     if (m_version == Version_100_ES && (m_tree->NeedsFunction("ddx") || m_tree->NeedsFunction("ddy")))
437     {
438         m_writer.WriteLine(0, "#extension GL_OES_standard_derivatives : require");
439     }
440 
441     OutputAttributes(entryFunction);
442 
443     if (m_target == Target_FragmentShader)
444     {
445         if (!m_outputTargets)
446             Error("Fragment shader must output a color");
447 
448         if (!m_versionLegacy)
449             m_writer.WriteLine(0, "out vec4 rast_FragData[%d];", m_outputTargets);
450     }
451 
452     OutputStatements(0, statement);
453     OutputEntryCaller(entryFunction);
454 
455     m_tree = NULL;
456 
457     // The GLSL compilers don't check for this, so generate our own error message.
458     if (target == Target_VertexShader && !m_outputPosition)
459     {
460         Error("Vertex shader must output a position");
461     }
462 
463     return !m_error;
464 
465 }
466 
GetResult() const467 const char* GLSLGenerator::GetResult() const
468 {
469     return m_writer.GetResult();
470 }
471 
OutputExpressionList(HLSLExpression * expression,HLSLArgument * argument)472 void GLSLGenerator::OutputExpressionList(HLSLExpression* expression, HLSLArgument* argument)
473 {
474     int numExpressions = 0;
475     while (expression != NULL)
476     {
477         if (numExpressions > 0)
478         {
479             m_writer.Write(", ");
480         }
481 
482         HLSLType* expectedType = NULL;
483         if (argument != NULL)
484         {
485             expectedType = &argument->type;
486             argument = argument->nextArgument;
487         }
488 
489         OutputExpression(expression, expectedType);
490         expression = expression->nextExpression;
491         ++numExpressions;
492     }
493 }
494 
commonScalarType(const HLSLType & lhs,const HLSLType & rhs)495 const HLSLType* commonScalarType(const HLSLType& lhs, const HLSLType& rhs)
496 {
497     if (!IsScalarType(lhs) || !IsScalarType(rhs))
498         return NULL;
499 
500     if (lhs.baseType == HLSLBaseType_Float || rhs.baseType == HLSLBaseType_Float)
501         return &kFloatType;
502 
503     if (lhs.baseType == HLSLBaseType_Uint || rhs.baseType == HLSLBaseType_Uint)
504         return &kUintType;
505 
506     if (lhs.baseType == HLSLBaseType_Int || rhs.baseType == HLSLBaseType_Int)
507         return &kIntType;
508 
509     if (lhs.baseType == HLSLBaseType_Bool || rhs.baseType == HLSLBaseType_Bool)
510         return &kBoolType;
511 
512     return NULL;
513 }
514 
OutputExpression(HLSLExpression * expression,const HLSLType * dstType)515 void GLSLGenerator::OutputExpression(HLSLExpression* expression, const HLSLType* dstType)
516 {
517 
518     bool cast = dstType != NULL && !GetCanImplicitCast(expression->expressionType, *dstType);
519     if (expression->nodeType == HLSLNodeType_CastingExpression)
520     {
521         // No need to include a cast if the expression is already doing it.
522         cast = false;
523     }
524 
525     if (cast)
526     {
527         OutputCast(*dstType);
528         m_writer.Write("(");
529     }
530 
531     HLSLBuffer* bufferAccess = (m_options.flags & Flag_EmulateConstantBuffer) ? GetBufferAccessExpression(expression) : 0;
532 
533     if (bufferAccess)
534     {
535         OutputBufferAccessExpression(bufferAccess, expression, expression->expressionType, 0);
536     }
537     else if (expression->nodeType == HLSLNodeType_IdentifierExpression)
538     {
539         HLSLIdentifierExpression* identifierExpression = static_cast<HLSLIdentifierExpression*>(expression);
540         OutputIdentifier(identifierExpression->name);
541     }
542     else if (expression->nodeType == HLSLNodeType_ConstructorExpression)
543     {
544         HLSLConstructorExpression* constructorExpression = static_cast<HLSLConstructorExpression*>(expression);
545 
546         bool matrixCtorNeeded = false;
547         if (IsMatrixType(constructorExpression->type.baseType))
548         {
549             matrixCtor ctor = matrixCtorBuilder(constructorExpression->type, constructorExpression->argument);
550             if (std::find(matrixCtors.cbegin(), matrixCtors.cend(), ctor) != matrixCtors.cend())
551             {
552                 matrixCtorNeeded = true;
553             }
554         }
555 
556         if (matrixCtorNeeded)
557         {
558             // Matrix contructors needs to be adapted since GLSL access a matrix as m[c][r] while HLSL is m[r][c]
559             matrixCtor ctor = matrixCtorBuilder(constructorExpression->type, constructorExpression->argument);
560             m_writer.Write("%s(", matrixCtorsId[ctor].c_str());
561             OutputExpressionList(constructorExpression->argument);
562             m_writer.Write(")");
563         }
564         else
565         {
566             m_writer.Write("%s(", GetTypeName(constructorExpression->type));
567             OutputExpressionList(constructorExpression->argument);
568             m_writer.Write(")");
569         }
570     }
571     else if (expression->nodeType == HLSLNodeType_CastingExpression)
572     {
573         HLSLCastingExpression* castingExpression = static_cast<HLSLCastingExpression*>(expression);
574         OutputCast(castingExpression->type);
575         m_writer.Write("(");
576         OutputExpression(castingExpression->expression);
577         m_writer.Write(")");
578     }
579     else if (expression->nodeType == HLSLNodeType_LiteralExpression)
580     {
581         HLSLLiteralExpression* literalExpression = static_cast<HLSLLiteralExpression*>(expression);
582         switch (literalExpression->type)
583         {
584         case HLSLBaseType_Float:
585             {
586                 // Don't use printf directly so that we don't use the system locale.
587                 char buffer[64];
588                 String_FormatFloat(buffer, sizeof(buffer), literalExpression->fValue);
589                 m_writer.Write("%s", buffer);
590             }
591             break;
592         case HLSLBaseType_Int:
593         case HLSLBaseType_Uint:
594             m_writer.Write("%d", literalExpression->iValue);
595             break;
596         case HLSLBaseType_Bool:
597             m_writer.Write("%s", literalExpression->bValue ? "true" : "false");
598             break;
599         default:
600             ASSERT(0);
601         }
602     }
603     else if (expression->nodeType == HLSLNodeType_UnaryExpression)
604     {
605         HLSLUnaryExpression* unaryExpression = static_cast<HLSLUnaryExpression*>(expression);
606         const char* op = "?";
607         bool pre = true;
608         const HLSLType* dstType2 = NULL;
609         switch (unaryExpression->unaryOp)
610         {
611         case HLSLUnaryOp_Negative:      op = "-";  break;
612         case HLSLUnaryOp_Positive:      op = "+";  break;
613         case HLSLUnaryOp_Not:           op = "!";  dstType2 = &unaryExpression->expressionType; break;
614         case HLSLUnaryOp_PreIncrement:  op = "++"; break;
615         case HLSLUnaryOp_PreDecrement:  op = "--"; break;
616         case HLSLUnaryOp_PostIncrement: op = "++"; pre = false; break;
617         case HLSLUnaryOp_PostDecrement: op = "--"; pre = false; break;
618         case HLSLUnaryOp_BitNot:        op = "~";  break;
619         }
620         m_writer.Write("(");
621         if (pre)
622         {
623             m_writer.Write("%s", op);
624             OutputExpression(unaryExpression->expression, dstType2);
625         }
626         else
627         {
628             OutputExpression(unaryExpression->expression, dstType2);
629             m_writer.Write("%s", op);
630         }
631         m_writer.Write(")");
632     }
633     else if (expression->nodeType == HLSLNodeType_BinaryExpression)
634     {
635         HLSLBinaryExpression* binaryExpression = static_cast<HLSLBinaryExpression*>(expression);
636         const char* op = "?";
637         const HLSLType* dstType1 = NULL;
638         const HLSLType* dstType2 = NULL;
639 
640 		//
641 		bool vectorExpression = IsVectorType( binaryExpression->expression1->expressionType ) || IsVectorType( binaryExpression->expression2->expressionType );
642 		if( vectorExpression && IsCompareOp( binaryExpression->binaryOp ))
643 		{
644 			switch (binaryExpression->binaryOp)
645 			{
646 			case HLSLBinaryOp_Less:         m_writer.Write("lessThan(");			break;
647 			case HLSLBinaryOp_Greater:      m_writer.Write("greaterThan(");			break;
648 			case HLSLBinaryOp_LessEqual:    m_writer.Write("lessThanEqual(");		break;
649 			case HLSLBinaryOp_GreaterEqual: m_writer.Write("greaterThanEqual(");	break;
650 			case HLSLBinaryOp_Equal:        m_writer.Write("equal(");				break;
651 			case HLSLBinaryOp_NotEqual:     m_writer.Write("notEqual(");			break;
652 			default:
653 				ASSERT(0); // is so, check isCompareOp
654 			}
655 
656 			if( IsVectorType( binaryExpression->expression1->expressionType ) && IsScalarType( binaryExpression->expression2->expressionType ) )
657 				dstType2 = &binaryExpression->expression1->expressionType;
658 			else if( IsScalarType( binaryExpression->expression1->expressionType ) && IsVectorType( binaryExpression->expression2->expressionType ) )
659 				dstType1 = &binaryExpression->expression2->expressionType;
660 			// TODO if both expressions are vector but with different dimension handle it here or in parser?
661 
662 			OutputExpression(binaryExpression->expression1, dstType1);
663 			m_writer.Write(", ");
664 			OutputExpression(binaryExpression->expression2, dstType2);
665 			m_writer.Write(")");
666 		}
667 		else
668 		{
669 			switch (binaryExpression->binaryOp)
670 			{
671 			case HLSLBinaryOp_Add:          op = " + "; dstType1 = dstType2 = &binaryExpression->expressionType; break;
672 			case HLSLBinaryOp_Sub:          op = " - "; dstType1 = dstType2 = &binaryExpression->expressionType; break;
673 			case HLSLBinaryOp_Mul:          op = " * "; dstType1 = dstType2 = &binaryExpression->expressionType; break;
674 			case HLSLBinaryOp_Div:          op = " / "; dstType1 = dstType2 = &binaryExpression->expressionType; break;
675             case HLSLBinaryOp_Mod:          op = " % "; dstType1 = dstType2 = &kIntType; break;
676 			case HLSLBinaryOp_Less:         op = " < "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
677 			case HLSLBinaryOp_Greater:      op = " > "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
678 			case HLSLBinaryOp_LessEqual:    op = " <= "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
679 			case HLSLBinaryOp_GreaterEqual: op = " >= "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
680 			case HLSLBinaryOp_Equal:        op = " == "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
681 			case HLSLBinaryOp_NotEqual:     op = " != "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
682 			case HLSLBinaryOp_Assign:       op = " = ";  dstType2 = &binaryExpression->expressionType; break;
683 			case HLSLBinaryOp_AddAssign:    op = " += "; dstType2 = &binaryExpression->expressionType; break;
684 			case HLSLBinaryOp_SubAssign:    op = " -= "; dstType2 = &binaryExpression->expressionType; break;
685 			case HLSLBinaryOp_MulAssign:    op = " *= "; dstType2 = &binaryExpression->expressionType; break;
686 			case HLSLBinaryOp_DivAssign:    op = " /= "; dstType2 = &binaryExpression->expressionType; break;
687 			case HLSLBinaryOp_And:          op = " && "; dstType1 = dstType2 = &binaryExpression->expressionType; break;
688 			case HLSLBinaryOp_Or:           op = " || "; dstType1 = dstType2 = &binaryExpression->expressionType; break;
689 			case HLSLBinaryOp_BitAnd:       op = " & "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
690 			case HLSLBinaryOp_BitOr:        op = " | "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
691 			case HLSLBinaryOp_BitXor:       op = " ^ "; dstType1 = dstType2 = commonScalarType(binaryExpression->expression1->expressionType, binaryExpression->expression2->expressionType); break;
692 			default:
693 				ASSERT(0);
694 			}
695             if ((m_version == Version_110 || m_version == Version_120 || m_version == Version_100_ES) && binaryExpression->binaryOp == HLSLBinaryOp_Mod) {
696                 m_writer.Write("(int(mod(");
697                 OutputExpression(binaryExpression->expression1, dstType1);
698                 m_writer.Write(",");
699                 OutputExpression(binaryExpression->expression2, dstType2);
700                 m_writer.Write(")))");
701             } else {
702 			    m_writer.Write("(");
703 			    OutputExpression(binaryExpression->expression1, dstType1);
704 			    m_writer.Write("%s", op);
705 			    OutputExpression(binaryExpression->expression2, dstType2);
706 			    m_writer.Write(")");
707             }
708 		}
709     }
710     else if (expression->nodeType == HLSLNodeType_ConditionalExpression)
711     {
712         HLSLConditionalExpression* conditionalExpression = static_cast<HLSLConditionalExpression*>(expression);
713 		if( IsVectorType( conditionalExpression->condition->expressionType ) )
714 		{
715 			m_writer.Write( "%s", m_bvecTernary );
716 			m_writer.Write( "( " );
717 			OutputExpression( conditionalExpression->condition );
718 			m_writer.Write( ", " );
719 			OutputExpression( conditionalExpression->trueExpression, &conditionalExpression->expressionType );
720 			m_writer.Write( ", " );
721 			OutputExpression( conditionalExpression->falseExpression, &conditionalExpression->expressionType  );
722 			m_writer.Write( " )" );
723 		}
724 		else
725 		{
726 			m_writer.Write( "((" );
727 			OutputExpression( conditionalExpression->condition, &kBoolType );
728 			m_writer.Write( ")?(" );
729 			OutputExpression( conditionalExpression->trueExpression, dstType );
730 			m_writer.Write( "):(" );
731 			OutputExpression( conditionalExpression->falseExpression, dstType );
732 			m_writer.Write( "))" );
733 		}
734     }
735     else if (expression->nodeType == HLSLNodeType_MemberAccess)
736     {
737 
738         HLSLMemberAccess* memberAccess = static_cast<HLSLMemberAccess*>(expression);
739 
740         if (memberAccess->object->expressionType.baseType == HLSLBaseType_Float ||
741             memberAccess->object->expressionType.baseType == HLSLBaseType_Int   ||
742             memberAccess->object->expressionType.baseType == HLSLBaseType_Uint)
743         {
744             // Handle swizzling on scalar values.
745             size_t swizzleLength = strlen(memberAccess->field);
746             if (swizzleLength == 2)
747             {
748                 m_writer.Write("%s", m_scalarSwizzle2Function);
749             }
750             else if (swizzleLength == 3)
751             {
752                 m_writer.Write("%s", m_scalarSwizzle3Function);
753             }
754             else if (swizzleLength == 4)
755             {
756                 m_writer.Write("%s", m_scalarSwizzle4Function);
757             }
758             m_writer.Write("(");
759             OutputExpression(memberAccess->object);
760             m_writer.Write(")");
761         }
762         else
763         {
764             m_writer.Write("(");
765             OutputExpression(memberAccess->object);
766             m_writer.Write(")");
767 
768             if( IsMatrixType(memberAccess->object->expressionType.baseType))
769             {
770                 // Handle HLSL matrix "swizzling".
771                 // TODO: Properly handle multiple element selection such as _m00_m12
772                 const char* n = memberAccess->field;
773                 while (n[0] != 0)
774                 {
775                     if ( n[0] != '_' )
776                     {
777                         ASSERT(0);
778                         break;
779                     }
780                     ++n;
781                     char base = '1';
782                     if (n[0] == 'm')
783                     {
784                         base = '0';
785                         ++n;
786                     }
787                     if (isdigit(n[0]) && isdigit(n[1]) )
788                     {
789                         m_writer.Write("[%d][%d]", n[1] - base, n[0] - base);
790                         n += 2;
791                     }
792                     else
793                     {
794                         ASSERT(0);
795                         break;
796                     }
797                 }
798             }
799             else
800             {
801                 m_writer.Write(".%s", memberAccess->field);
802             }
803 
804         }
805 
806     }
807     else if (expression->nodeType == HLSLNodeType_ArrayAccess)
808     {
809         HLSLArrayAccess* arrayAccess = static_cast<HLSLArrayAccess*>(expression);
810 
811         if (!arrayAccess->array->expressionType.array &&
812             IsMatrixType(arrayAccess->array->expressionType.baseType) )
813         {
814             // GLSL access a matrix as m[c][r] while HLSL is m[r][c], so use our
815             // special row access function to convert.
816             m_writer.Write("%s(", m_matrixRowFunction);
817             OutputExpression(arrayAccess->array);
818             m_writer.Write(",");
819             OutputExpression(arrayAccess->index);
820             m_writer.Write(")");
821         }
822         else
823         {
824             OutputExpression(arrayAccess->array);
825             m_writer.Write("[");
826             OutputExpression(arrayAccess->index);
827             m_writer.Write("]");
828         }
829 
830     }
831     else if (expression->nodeType == HLSLNodeType_FunctionCall)
832     {
833         HLSLFunctionCall* functionCall = static_cast<HLSLFunctionCall*>(expression);
834 
835         // Handle intrinsic funtions that are different between HLSL and GLSL.
836         bool handled = false;
837         const char* functionName = functionCall->function->name;
838 
839         if (String_Equal(functionName, "mul"))
840         {
841             HLSLExpression* argument[2];
842             if (GetFunctionArguments(functionCall, argument, 2) != 2)
843             {
844                 Error("mul expects 2 arguments");
845                 return;
846             }
847 
848             const HLSLType& type0 = functionCall->function->argument->type;
849             const HLSLType& type1 = functionCall->function->argument->nextArgument->type;
850 
851             if (IsVectorType(type0.baseType) && IsVectorType(type1.baseType))
852             {
853                 m_writer.Write("dot((");
854                 OutputExpression(argument[0], &type0);
855                 m_writer.Write("),(");
856                 OutputExpression(argument[1], &type1);
857                 m_writer.Write("))");
858             }
859             else
860             {
861                 m_writer.Write("((");
862                 OutputExpression(argument[0], &type0);
863                 m_writer.Write(")*(");
864                 OutputExpression(argument[1], &type1);
865                 m_writer.Write("))");
866             }
867 
868             handled = true;
869         }
870         else if (String_Equal(functionName, "saturate"))
871         {
872             HLSLExpression* argument[1];
873             if (GetFunctionArguments(functionCall, argument, 1) != 1)
874             {
875                 Error("saturate expects 1 argument");
876                 return;
877             }
878             m_writer.Write("clamp(");
879             OutputExpression(argument[0]);
880             HLSLBaseType baseType = argument[0]->expressionType.baseType;
881             switch (baseType) {
882             case HLSLBaseType_Float:
883             case HLSLBaseType_Float2:
884             case HLSLBaseType_Float3:
885             case HLSLBaseType_Float4:
886                 m_writer.Write(", 0.0, 1.0)");
887                 break;
888 
889             case HLSLBaseType_Int:
890             case HLSLBaseType_Int2:
891             case HLSLBaseType_Int3:
892             case HLSLBaseType_Int4:
893             case HLSLBaseType_Uint:
894             case HLSLBaseType_Uint2:
895             case HLSLBaseType_Uint3:
896             case HLSLBaseType_Uint4:
897                 m_writer.Write(", 0, 1)");
898                 break;
899 
900             default:
901                 Error("saturate unhandled type: %s", GetTypeName(argument[0]->expressionType));
902                 break;
903             }
904             handled = true;
905         }
906         else if (String_Equal(functionName, "rsqrt"))
907         {
908             HLSLExpression* argument[1];
909             if (GetFunctionArguments(functionCall, argument, 1) != 1)
910             {
911                 Error("rsqrt expects 1 argument");
912                 return;
913             }
914             m_writer.Write("inversesqrt(");
915             OutputExpression(argument[0]);
916             m_writer.Write(")");
917             handled = true;
918         }
919 
920         if (!handled)
921         {
922             OutputIdentifier(functionName);
923             m_writer.Write("(");
924             OutputExpressionList(functionCall->argument, functionCall->function->argument);
925             m_writer.Write(")");
926         }
927     }
928     else
929     {
930         m_writer.Write("<unknown expression>");
931     }
932 
933     if (cast)
934     {
935         if (IsVectorType(dstType->baseType) || IsMatrixType(dstType->baseType))
936         {
937             CompleteConstructorArguments(expression, dstType->baseType);
938         }
939 
940         m_writer.Write(")");
941     }
942 
943 }
944 
OutputIdentifier(const char * name)945 void GLSLGenerator::OutputIdentifier(const char* name)
946 {
947 
948     // Remap intrinstic functions.
949     if (String_Equal(name, "tex2D"))
950     {
951         name = m_versionLegacy ? "texture2D" : "texture";
952     }
953     else if (String_Equal(name, "tex2Dproj"))
954     {
955         name = m_versionLegacy ? "texture2DProj" : "textureProj";
956     }
957     else if (String_Equal(name, "texCUBE"))
958     {
959         name = m_versionLegacy ? "textureCube" : "texture";
960     }
961     else if (String_Equal(name, "tex3D"))
962     {
963         name = m_versionLegacy ? "texture3D" : "texture";
964     }
965     else if (String_Equal(name, "clip"))
966     {
967         name = m_clipFunction;
968     }
969     else if (String_Equal(name, "tex2Dlod"))
970     {
971         name = m_tex2DlodFunction;
972     }
973     else if (String_Equal(name, "tex2Dbias"))
974     {
975         name = m_tex2DbiasFunction;
976     }
977     else if (String_Equal(name, "tex2Dgrad"))
978     {
979         name = m_tex2DgradFunction;
980     }
981     else if (String_Equal(name, "tex2DArray"))
982     {
983         name = "texture";
984     }
985     else if (String_Equal(name, "texCUBEbias"))
986     {
987         name = m_texCUBEbiasFunction;
988     }
989 	else if( String_Equal( name, "texCUBElod" ) )
990 	{
991 		name = m_texCUBElodFunction;
992 	}
993     else if (String_Equal(name, "atan2"))
994     {
995         name = "atan";
996     }
997     else if (String_Equal(name, "sincos"))
998     {
999         name = m_sinCosFunction;
1000     }
1001     else if (String_Equal(name, "fmod"))
1002     {
1003         // mod is not the same as fmod if the parameter is negative!
1004         // The equivalent of fmod(x, y) is x - y * floor(x/y)
1005         // We use the mod version for performance.
1006         name = "mod";
1007     }
1008     else if (String_Equal(name, "lerp"))
1009     {
1010         name = "mix";
1011     }
1012     else if (String_Equal(name, "frac"))
1013     {
1014         name = "fract";
1015     }
1016     else if (String_Equal(name, "ddx"))
1017     {
1018         name = "dFdx";
1019     }
1020     else if (String_Equal(name, "ddy"))
1021     {
1022         name = "dFdy";
1023     }
1024     else if (String_Equal(name, "modf"))
1025     {
1026         name = m_modfFunction;
1027     }
1028     else
1029     {
1030         // The identifier could be a GLSL reserved word (if it's not also a HLSL reserved word).
1031         name = GetSafeIdentifierName(name);
1032     }
1033     m_writer.Write("%s", name);
1034 
1035 }
1036 
OutputArguments(HLSLArgument * argument)1037 void GLSLGenerator::OutputArguments(HLSLArgument* argument)
1038 {
1039     int numArgs = 0;
1040     while (argument != NULL)
1041     {
1042         if (numArgs > 0)
1043         {
1044             m_writer.Write(", ");
1045         }
1046 
1047         switch (argument->modifier)
1048         {
1049         case HLSLArgumentModifier_In:
1050             m_writer.Write("in ");
1051             break;
1052         case HLSLArgumentModifier_Out:
1053             m_writer.Write("out ");
1054             break;
1055         case HLSLArgumentModifier_Inout:
1056             m_writer.Write("inout ");
1057             break;
1058         default:
1059             break;
1060         }
1061 
1062         OutputDeclaration(argument->type, argument->name);
1063         argument = argument->nextArgument;
1064         ++numArgs;
1065     }
1066 }
1067 
OutputStatements(int indent,HLSLStatement * statement,const HLSLType * returnType)1068 void GLSLGenerator::OutputStatements(int indent, HLSLStatement* statement, const HLSLType* returnType)
1069 {
1070 
1071     while (statement != NULL)
1072     {
1073         if (statement->hidden)
1074         {
1075             statement = statement->nextStatement;
1076             continue;
1077         }
1078 
1079         if (statement->nodeType == HLSLNodeType_Declaration)
1080         {
1081             HLSLDeclaration* declaration = static_cast<HLSLDeclaration*>(statement);
1082 
1083             // GLSL doesn't seem have texture uniforms, so just ignore them.
1084             if (declaration->type.baseType != HLSLBaseType_Texture)
1085             {
1086                 bool skipAssignment = true;
1087                 if (indent != 0)
1088                 {
1089                     skipAssignment = false;
1090                 }
1091 
1092                 m_writer.BeginLine(indent, declaration->fileName, declaration->line);
1093                 if (indent == 0 && (declaration->type.flags & HLSLTypeFlag_Uniform))
1094                 {
1095                     // At the top level, we need the "uniform" keyword.
1096                     m_writer.Write("uniform ");
1097                     skipAssignment = false;
1098                 }
1099                 OutputDeclaration(declaration, skipAssignment);
1100                 m_writer.EndLine(";");
1101             }
1102         }
1103         else if (statement->nodeType == HLSLNodeType_Struct)
1104         {
1105             HLSLStruct* structure = static_cast<HLSLStruct*>(statement);
1106             m_writer.WriteLine(indent, "struct %s {", structure->name);
1107             HLSLStructField* field = structure->field;
1108             while (field != NULL)
1109             {
1110                 m_writer.BeginLine(indent + 1, field->fileName, field->line);
1111                 OutputDeclaration(field->type, field->name);
1112                 m_writer.Write(";");
1113                 m_writer.EndLine();
1114                 field = field->nextField;
1115             }
1116             m_writer.WriteLine(indent, "};");
1117         }
1118         else if (statement->nodeType == HLSLNodeType_Buffer)
1119         {
1120             HLSLBuffer* buffer = static_cast<HLSLBuffer*>(statement);
1121             OutputBuffer(indent, buffer);
1122         }
1123         else if (statement->nodeType == HLSLNodeType_Function)
1124         {
1125             HLSLFunction* function = static_cast<HLSLFunction*>(statement);
1126 
1127             // Use an alternate name for the function which is supposed to be entry point
1128             // so that we can supply our own function which will be the actual entry point.
1129             const char* functionName   = GetSafeIdentifierName(function->name);
1130             const char* returnTypeName = GetTypeName(function->returnType);
1131 
1132             m_writer.BeginLine(indent, function->fileName, function->line);
1133             m_writer.Write("%s %s(", returnTypeName, functionName);
1134 
1135             OutputArguments(function->argument);
1136 
1137             if (function->forward)
1138             {
1139                 m_writer.WriteLine(indent, ");");
1140             }
1141             else
1142             {
1143                 m_writer.Write(") {");
1144                 m_writer.EndLine();
1145 
1146                 OutputStatements(indent + 1, function->statement, &function->returnType);
1147                 m_writer.WriteLine(indent, "}");
1148             }
1149         }
1150         else if (statement->nodeType == HLSLNodeType_ExpressionStatement)
1151         {
1152             HLSLExpressionStatement* expressionStatement = static_cast<HLSLExpressionStatement*>(statement);
1153             m_writer.BeginLine(indent, statement->fileName, statement->line);
1154             OutputExpression(expressionStatement->expression);
1155             m_writer.EndLine(";");
1156         }
1157         else if (statement->nodeType == HLSLNodeType_ReturnStatement)
1158         {
1159             HLSLReturnStatement* returnStatement = static_cast<HLSLReturnStatement*>(statement);
1160             if (returnStatement->expression != NULL)
1161             {
1162                 m_writer.BeginLine(indent, returnStatement->fileName, returnStatement->line);
1163                 m_writer.Write("return ");
1164                 OutputExpression(returnStatement->expression, returnType);
1165                 m_writer.EndLine(";");
1166             }
1167             else
1168             {
1169                 m_writer.WriteLineTagged(indent, returnStatement->fileName, returnStatement->line, "return;");
1170             }
1171         }
1172         else if (statement->nodeType == HLSLNodeType_DiscardStatement)
1173         {
1174             HLSLDiscardStatement* discardStatement = static_cast<HLSLDiscardStatement*>(statement);
1175             if (m_target == Target_FragmentShader)
1176             {
1177                 m_writer.WriteLineTagged(indent, discardStatement->fileName, discardStatement->line, "discard;");
1178             }
1179         }
1180         else if (statement->nodeType == HLSLNodeType_BreakStatement)
1181         {
1182             HLSLBreakStatement* breakStatement = static_cast<HLSLBreakStatement*>(statement);
1183             m_writer.WriteLineTagged(indent, breakStatement->fileName, breakStatement->line, "break;");
1184         }
1185         else if (statement->nodeType == HLSLNodeType_ContinueStatement)
1186         {
1187             HLSLContinueStatement* continueStatement = static_cast<HLSLContinueStatement*>(statement);
1188             m_writer.WriteLineTagged(indent, continueStatement->fileName, continueStatement->line, "continue;");
1189         }
1190         else if (statement->nodeType == HLSLNodeType_IfStatement)
1191         {
1192             HLSLIfStatement* ifStatement = static_cast<HLSLIfStatement*>(statement);
1193             m_writer.BeginLine(indent, ifStatement->fileName, ifStatement->line);
1194             m_writer.Write("if (");
1195             OutputExpression(ifStatement->condition, &kBoolType);
1196             m_writer.Write(") {");
1197             m_writer.EndLine();
1198             OutputStatements(indent + 1, ifStatement->statement, returnType);
1199             m_writer.WriteLine(indent, "}");
1200             if (ifStatement->elseStatement != NULL)
1201             {
1202                 m_writer.WriteLine(indent, "else {");
1203                 OutputStatements(indent + 1, ifStatement->elseStatement, returnType);
1204                 m_writer.WriteLine(indent, "}");
1205             }
1206         }
1207         else if (statement->nodeType == HLSLNodeType_ForStatement)
1208         {
1209             HLSLForStatement* forStatement = static_cast<HLSLForStatement*>(statement);
1210             m_writer.BeginLine(indent, forStatement->fileName, forStatement->line);
1211             m_writer.Write("for (");
1212             if (forStatement->initialization != NULL)
1213             {
1214                 OutputDeclaration(forStatement->initialization, false);
1215             }
1216             else
1217             {
1218                 OutputExpression(forStatement->initializationWithoutType);
1219             }
1220             m_writer.Write("; ");
1221             OutputExpression(forStatement->condition, &kBoolType);
1222             m_writer.Write("; ");
1223             OutputExpression(forStatement->increment);
1224             m_writer.Write(") {");
1225             m_writer.EndLine();
1226             OutputStatements(indent + 1, forStatement->statement, returnType);
1227             m_writer.WriteLine(indent, "}");
1228         }
1229         else if (statement->nodeType == HLSLNodeType_WhileStatement)
1230         {
1231             HLSLWhileStatement* whileStatement = static_cast<HLSLWhileStatement*>(statement);
1232             m_writer.BeginLine(indent, whileStatement->fileName, whileStatement->line);
1233             m_writer.Write("while (");
1234             OutputExpression(whileStatement->condition, &kBoolType);
1235             m_writer.Write(") {");
1236             m_writer.EndLine();
1237             OutputStatements(indent + 1, whileStatement->statement, returnType);
1238             m_writer.WriteLine(indent, "}");
1239         }
1240         else if (statement->nodeType == HLSLNodeType_BlockStatement)
1241         {
1242             HLSLBlockStatement* blockStatement = static_cast<HLSLBlockStatement*>(statement);
1243             m_writer.WriteLine(indent, "{");
1244             OutputStatements(indent + 1, blockStatement->statement, returnType);
1245             m_writer.WriteLine(indent, "}");
1246         }
1247         else
1248         {
1249             // Unhanded statement type.
1250             ASSERT(0);
1251         }
1252 
1253         statement = statement->nextStatement;
1254 
1255     }
1256 
1257 }
1258 
OutputBuffer(int indent,HLSLBuffer * buffer)1259 void GLSLGenerator::OutputBuffer(int indent, HLSLBuffer* buffer)
1260 {
1261     // Empty uniform blocks cause compilation errors on NVIDIA, so don't emit them.
1262     if (buffer->field == NULL)
1263         return;
1264 
1265     if (m_options.flags & Flag_EmulateConstantBuffer)
1266     {
1267         unsigned int size = 0;
1268         LayoutBuffer(buffer, size);
1269 
1270         unsigned int uniformSize = (size + 3) / 4;
1271 
1272         m_writer.WriteLineTagged(indent, buffer->fileName, buffer->line, "uniform vec4 %s%s[%d];", m_options.constantBufferPrefix, buffer->name, uniformSize);
1273     }
1274     else
1275     {
1276         m_writer.WriteLineTagged(indent, buffer->fileName, buffer->line, "layout (std140) uniform %s%s {", m_options.constantBufferPrefix, buffer->name);
1277         HLSLDeclaration* field = buffer->field;
1278         while (field != NULL)
1279         {
1280             m_writer.BeginLine(indent + 1, field->fileName, field->line);
1281             OutputDeclaration(field->type, field->name);
1282             m_writer.Write(";");
1283             m_writer.EndLine();
1284             field = (HLSLDeclaration*)field->nextStatement;
1285         }
1286         m_writer.WriteLine(indent, "};");
1287     }
1288 }
1289 
alignForWrite(unsigned int & offset,unsigned int size)1290 inline void alignForWrite(unsigned int& offset, unsigned int size)
1291 {
1292     ASSERT(size <= 4);
1293 
1294     if (offset / 4 != (offset + size - 1) / 4)
1295         offset = (offset + 3) & ~3;
1296 }
1297 
LayoutBuffer(HLSLBuffer * buffer,unsigned int & offset)1298 void GLSLGenerator::LayoutBuffer(HLSLBuffer* buffer, unsigned int& offset)
1299 {
1300     for (HLSLDeclaration* field = buffer->field; field; field = (HLSLDeclaration*)field->nextStatement)
1301     {
1302         LayoutBuffer(field->type, offset);
1303     }
1304 }
1305 
LayoutBuffer(const HLSLType & type,unsigned int & offset)1306 void GLSLGenerator::LayoutBuffer(const HLSLType& type, unsigned int& offset)
1307 {
1308     LayoutBufferAlign(type, offset);
1309 
1310     if (type.array)
1311     {
1312         int arraySize = 0;
1313         m_tree->GetExpressionValue(type.arraySize, arraySize);
1314 
1315         unsigned int elementSize = 0;
1316         LayoutBufferElement(type, elementSize);
1317 
1318         unsigned int alignedElementSize = (elementSize + 3) & ~3;
1319 
1320         offset += alignedElementSize * arraySize;
1321     }
1322     else
1323     {
1324         LayoutBufferElement(type, offset);
1325     }
1326 }
1327 
LayoutBufferElement(const HLSLType & type,unsigned int & offset)1328 void GLSLGenerator::LayoutBufferElement(const HLSLType& type, unsigned int& offset)
1329 {
1330     if (type.baseType == HLSLBaseType_Float)
1331     {
1332         offset += 1;
1333     }
1334     else if (type.baseType == HLSLBaseType_Float2)
1335     {
1336         offset += 2;
1337     }
1338     else if (type.baseType == HLSLBaseType_Float3)
1339     {
1340         offset += 3;
1341     }
1342     else if (type.baseType == HLSLBaseType_Float4)
1343     {
1344         offset += 4;
1345     }
1346     else if (type.baseType == HLSLBaseType_Float4x4)
1347     {
1348         offset += 16;
1349     }
1350     else if (type.baseType == HLSLBaseType_UserDefined)
1351     {
1352         HLSLStruct * st = m_tree->FindGlobalStruct(type.typeName);
1353 
1354         if (st)
1355         {
1356             for (HLSLStructField* field = st->field; field; field = field->nextField)
1357             {
1358                 LayoutBuffer(field->type, offset);
1359             }
1360         }
1361         else
1362         {
1363             Error("Unknown type %s", type.typeName);
1364         }
1365     }
1366     else
1367     {
1368         Error("Constant buffer layout is not supported for %s", GetTypeName(type));
1369     }
1370 }
1371 
LayoutBufferAlign(const HLSLType & type,unsigned int & offset)1372 void GLSLGenerator::LayoutBufferAlign(const HLSLType& type, unsigned int& offset)
1373 {
1374     if (type.array)
1375     {
1376         alignForWrite(offset, 4);
1377     }
1378     else if (type.baseType == HLSLBaseType_Float)
1379     {
1380         alignForWrite(offset, 1);
1381     }
1382     else if (type.baseType == HLSLBaseType_Float2)
1383     {
1384         alignForWrite(offset, 2);
1385     }
1386     else if (type.baseType == HLSLBaseType_Float3)
1387     {
1388         alignForWrite(offset, 3);
1389     }
1390     else if (type.baseType == HLSLBaseType_Float4)
1391     {
1392         alignForWrite(offset, 4);
1393     }
1394     else if (type.baseType == HLSLBaseType_Float4x4)
1395     {
1396         alignForWrite(offset, 4);
1397     }
1398     else if (type.baseType == HLSLBaseType_UserDefined)
1399     {
1400         alignForWrite(offset, 4);
1401     }
1402     else
1403     {
1404         Error("Constant buffer layout is not supported for %s", GetTypeName(type));
1405     }
1406 }
1407 
GetBufferAccessExpression(HLSLExpression * expression)1408 HLSLBuffer* GLSLGenerator::GetBufferAccessExpression(HLSLExpression* expression)
1409 {
1410     if (expression->nodeType == HLSLNodeType_IdentifierExpression)
1411     {
1412         HLSLIdentifierExpression* identifierExpression = static_cast<HLSLIdentifierExpression*>(expression);
1413 
1414         if (identifierExpression->global)
1415         {
1416             HLSLDeclaration * declaration = m_tree->FindGlobalDeclaration(identifierExpression->name);
1417 
1418             if (declaration && declaration->buffer)
1419                 return declaration->buffer;
1420         }
1421     }
1422     else if (expression->nodeType == HLSLNodeType_MemberAccess)
1423     {
1424         HLSLMemberAccess* memberAccess = static_cast<HLSLMemberAccess*>(expression);
1425 
1426         if (memberAccess->object->expressionType.baseType == HLSLBaseType_UserDefined)
1427             return GetBufferAccessExpression(memberAccess->object);
1428     }
1429     else if (expression->nodeType == HLSLNodeType_ArrayAccess)
1430     {
1431         HLSLArrayAccess* arrayAccess = static_cast<HLSLArrayAccess*>(expression);
1432 
1433         if (arrayAccess->array->expressionType.array)
1434             return GetBufferAccessExpression(arrayAccess->array);
1435     }
1436 
1437     return 0;
1438 }
1439 
OutputBufferAccessExpression(HLSLBuffer * buffer,HLSLExpression * expression,const HLSLType & type,unsigned int postOffset)1440 void GLSLGenerator::OutputBufferAccessExpression(HLSLBuffer* buffer, HLSLExpression* expression, const HLSLType& type, unsigned int postOffset)
1441 {
1442     if (type.array)
1443     {
1444         Error("Constant buffer access is not supported for arrays (use indexing instead)");
1445     }
1446     else if (type.baseType == HLSLBaseType_Float)
1447     {
1448         m_writer.Write("%s%s[", m_options.constantBufferPrefix, buffer->name);
1449         unsigned int index = OutputBufferAccessIndex(expression, postOffset);
1450         m_writer.Write("%d].%c", index / 4, "xyzw"[index % 4]);
1451     }
1452     else if (type.baseType == HLSLBaseType_Float2)
1453     {
1454         m_writer.Write("%s%s[", m_options.constantBufferPrefix, buffer->name);
1455         unsigned int index = OutputBufferAccessIndex(expression, postOffset);
1456         m_writer.Write("%d].%s", index / 4, index % 4 == 0 ? "xy" : index % 4 == 1 ? "yz" : "zw");
1457     }
1458     else if (type.baseType == HLSLBaseType_Float3)
1459     {
1460         m_writer.Write("%s%s[", m_options.constantBufferPrefix, buffer->name);
1461         unsigned int index = OutputBufferAccessIndex(expression, postOffset);
1462         m_writer.Write("%d].%s", index / 4, index % 4 == 0 ? "xyz" : "yzw");
1463     }
1464     else if (type.baseType == HLSLBaseType_Float4)
1465     {
1466         m_writer.Write("%s%s[", m_options.constantBufferPrefix, buffer->name);
1467         unsigned int index = OutputBufferAccessIndex(expression, postOffset);
1468         ASSERT(index % 4 == 0);
1469         m_writer.Write("%d]", index / 4);
1470     }
1471     else if (type.baseType == HLSLBaseType_Float4x4)
1472     {
1473         m_writer.Write("mat4(");
1474         for (int i = 0; i < 4; ++i)
1475         {
1476             m_writer.Write("%s%s[", m_options.constantBufferPrefix, buffer->name);
1477             unsigned int index = OutputBufferAccessIndex(expression, postOffset + i * 4);
1478             ASSERT(index % 4 == 0);
1479             m_writer.Write("%d]%c", index / 4, i == 3 ? ')' : ',');
1480         }
1481     }
1482     else if (type.baseType == HLSLBaseType_UserDefined)
1483     {
1484         HLSLStruct * st = m_tree->FindGlobalStruct(type.typeName);
1485 
1486         if (st)
1487         {
1488             m_writer.Write("%s(", st->name);
1489 
1490             unsigned int offset = postOffset;
1491 
1492             for (HLSLStructField* field = st->field; field; field = field->nextField)
1493             {
1494                 OutputBufferAccessExpression(buffer, expression, field->type, offset);
1495 
1496                 if (field->nextField)
1497                     m_writer.Write(",");
1498 
1499                 LayoutBuffer(field->type, offset);
1500             }
1501 
1502             m_writer.Write(")");
1503         }
1504         else
1505         {
1506             Error("Unknown type %s", type.typeName);
1507         }
1508     }
1509     else
1510     {
1511         Error("Constant buffer layout is not supported for %s", GetTypeName(type));
1512     }
1513 }
1514 
OutputBufferAccessIndex(HLSLExpression * expression,unsigned int postOffset)1515 unsigned int GLSLGenerator::OutputBufferAccessIndex(HLSLExpression* expression, unsigned int postOffset)
1516 {
1517     if (expression->nodeType == HLSLNodeType_IdentifierExpression)
1518     {
1519         HLSLIdentifierExpression* identifierExpression = static_cast<HLSLIdentifierExpression*>(expression);
1520         ASSERT(identifierExpression->global);
1521 
1522         HLSLDeclaration * declaration = m_tree->FindGlobalDeclaration(identifierExpression->name);
1523         ASSERT(declaration);
1524 
1525         HLSLBuffer * buffer = declaration->buffer;
1526         ASSERT(buffer);
1527 
1528         unsigned int offset = 0;
1529 
1530         for (HLSLDeclaration* field = buffer->field; field; field = (HLSLDeclaration*)field->nextStatement)
1531         {
1532             if (field == declaration)
1533             {
1534                 LayoutBufferAlign(field->type, offset);
1535                 break;
1536             }
1537 
1538             LayoutBuffer(field->type, offset);
1539         }
1540 
1541         return offset + postOffset;
1542     }
1543     else if (expression->nodeType == HLSLNodeType_MemberAccess)
1544     {
1545         HLSLMemberAccess* memberAccess = static_cast<HLSLMemberAccess*>(expression);
1546 
1547         const HLSLType& type = memberAccess->object->expressionType;
1548         ASSERT(type.baseType == HLSLBaseType_UserDefined);
1549 
1550         HLSLStruct * st = m_tree->FindGlobalStruct(type.typeName);
1551 
1552         if (st)
1553         {
1554             unsigned int offset = 0;
1555 
1556             for (HLSLStructField* field = st->field; field; field = field->nextField)
1557             {
1558                 if (field->name == memberAccess->field)
1559                 {
1560                     LayoutBufferAlign(field->type, offset);
1561                     break;
1562                 }
1563 
1564                 LayoutBuffer(field->type, offset);
1565             }
1566 
1567             return offset + OutputBufferAccessIndex(memberAccess->object, postOffset);
1568         }
1569         else
1570         {
1571             Error("Unknown type %s", type.typeName);
1572         }
1573     }
1574     else if (expression->nodeType == HLSLNodeType_ArrayAccess)
1575     {
1576         HLSLArrayAccess* arrayAccess = static_cast<HLSLArrayAccess*>(expression);
1577 
1578         const HLSLType& type = arrayAccess->array->expressionType;
1579         ASSERT(type.array);
1580 
1581         unsigned int elementSize = 0;
1582         LayoutBufferElement(type, elementSize);
1583 
1584         unsigned int alignedElementSize = (elementSize + 3) & ~3;
1585 
1586         int arrayIndex = 0;
1587         if (m_tree->GetExpressionValue(arrayAccess->index, arrayIndex))
1588         {
1589             unsigned int offset = arrayIndex * alignedElementSize;
1590 
1591             return offset + OutputBufferAccessIndex(arrayAccess->array, postOffset);
1592         }
1593         else
1594         {
1595             m_writer.Write("%d*(", alignedElementSize / 4);
1596             OutputExpression(arrayAccess->index);
1597             m_writer.Write(")+");
1598 
1599             return OutputBufferAccessIndex(arrayAccess->array, postOffset);
1600         }
1601     }
1602     else
1603     {
1604         ASSERT(!"IsBufferAccessExpression should have returned false");
1605     }
1606 
1607     return 0;
1608 }
1609 
FindFunction(HLSLRoot * root,const char * name)1610 HLSLFunction* GLSLGenerator::FindFunction(HLSLRoot* root, const char* name)
1611 {
1612     HLSLStatement* statement = root->statement;
1613     while (statement != NULL)
1614     {
1615         if (statement->nodeType == HLSLNodeType_Function)
1616         {
1617             HLSLFunction* function = static_cast<HLSLFunction*>(statement);
1618             if (String_Equal(function->name, name))
1619             {
1620                 return function;
1621             }
1622         }
1623         statement = statement->nextStatement;
1624     }
1625     return NULL;
1626 }
1627 
FindStruct(HLSLRoot * root,const char * name)1628 HLSLStruct* GLSLGenerator::FindStruct(HLSLRoot* root, const char* name)
1629 {
1630     HLSLStatement* statement = root->statement;
1631     while (statement != NULL)
1632     {
1633         if (statement->nodeType == HLSLNodeType_Struct)
1634         {
1635             HLSLStruct* structDeclaration = static_cast<HLSLStruct*>(statement);
1636             if (String_Equal(structDeclaration->name, name))
1637             {
1638                 return structDeclaration;
1639             }
1640         }
1641         statement = statement->nextStatement;
1642     }
1643     return NULL;
1644 }
1645 
1646 
GetAttribQualifier(AttributeModifier modifier)1647 const char* GLSLGenerator::GetAttribQualifier(AttributeModifier modifier)
1648 {
1649     if (m_versionLegacy)
1650     {
1651         if (m_target == Target_VertexShader)
1652             return (modifier == AttributeModifier_In) ? "attribute" : "varying";
1653         else
1654             return (modifier == AttributeModifier_In) ? "varying" : "out";
1655     }
1656     else
1657     {
1658         return (modifier == AttributeModifier_In) ? "in" : "out";
1659     }
1660 }
1661 
OutputAttribute(const HLSLType & type,const char * semantic,AttributeModifier modifier)1662 void GLSLGenerator::OutputAttribute(const HLSLType& type, const char* semantic, AttributeModifier modifier)
1663 {
1664     const char* qualifier = GetAttribQualifier(modifier);
1665     const char* prefix = (modifier == AttributeModifier_In) ? m_inAttribPrefix : m_outAttribPrefix;
1666 
1667     HLSLRoot* root = m_tree->GetRoot();
1668     if (type.baseType == HLSLBaseType_UserDefined)
1669     {
1670         // If the argument is a struct with semantics specified, we need to
1671         // grab them.
1672         HLSLStruct* structDeclaration = FindStruct(root, type.typeName);
1673         ASSERT(structDeclaration != NULL);
1674         HLSLStructField* field = structDeclaration->field;
1675         while (field != NULL)
1676         {
1677             if (field->semantic != NULL && GetBuiltInSemantic(field->semantic, modifier) == NULL)
1678             {
1679                 m_writer.Write( "%s ", qualifier );
1680 				char attribName[ 64 ];
1681 				String_Printf( attribName, 64, "%s%s", prefix, field->semantic );
1682 				OutputDeclaration( field->type, attribName );
1683 				m_writer.EndLine(";");
1684             }
1685             field = field->nextField;
1686         }
1687     }
1688     else if (semantic != NULL && GetBuiltInSemantic(semantic, modifier) == NULL)
1689     {
1690 		m_writer.Write( "%s ", qualifier );
1691 		char attribName[ 64 ];
1692 		String_Printf( attribName, 64, "%s%s", prefix, semantic );
1693 		OutputDeclaration( type, attribName );
1694 		m_writer.EndLine(";");
1695     }
1696 }
1697 
OutputAttributes(HLSLFunction * entryFunction)1698 void GLSLGenerator::OutputAttributes(HLSLFunction* entryFunction)
1699 {
1700     // Write out the input/output attributes to the shader.
1701     HLSLArgument* argument = entryFunction->argument;
1702     while (argument != NULL)
1703     {
1704         if (argument->modifier == HLSLArgumentModifier_None || argument->modifier == HLSLArgumentModifier_In)
1705             OutputAttribute(argument->type, argument->semantic, AttributeModifier_In);
1706         if (argument->modifier == HLSLArgumentModifier_Out)
1707             OutputAttribute(argument->type, argument->semantic, AttributeModifier_Out);
1708 
1709         argument = argument->nextArgument;
1710     }
1711 
1712     // Write out the output attributes from the shader.
1713     OutputAttribute(entryFunction->returnType, entryFunction->semantic, AttributeModifier_Out);
1714 }
1715 
OutputSetOutAttribute(const char * semantic,const char * resultName)1716 void GLSLGenerator::OutputSetOutAttribute(const char* semantic, const char* resultName)
1717 {
1718     int outputIndex = -1;
1719     const char* builtInSemantic = GetBuiltInSemantic(semantic, AttributeModifier_Out, &outputIndex);
1720     if (builtInSemantic != NULL)
1721     {
1722         if (String_Equal(builtInSemantic, "gl_Position"))
1723         {
1724             if (m_options.flags & Flag_FlipPositionOutput)
1725             {
1726                 // Mirror the y-coordinate when we're outputing from
1727                 // the vertex shader so that we match the D3D texture
1728                 // coordinate origin convention in render-to-texture
1729                 // operations.
1730                 // We also need to convert the normalized device
1731                 // coordinates from the D3D convention of 0 to 1 to the
1732                 // OpenGL convention of -1 to 1.
1733                 m_writer.WriteLine(1, "vec4 temp = %s;", resultName);
1734                 m_writer.WriteLine(1, "%s = temp * vec4(1,-1,2,1) - vec4(0,0,temp.w,0);", builtInSemantic);
1735             }
1736             else
1737             {
1738                 m_writer.WriteLine(1, "%s = %s;", builtInSemantic, resultName);
1739             }
1740 
1741             m_outputPosition = true;
1742         }
1743         else if (String_Equal(builtInSemantic, "gl_FragDepth"))
1744         {
1745             // If the value goes outside of the 0 to 1 range, the
1746             // fragment will be rejected unlike in D3D, so clamp it.
1747             m_writer.WriteLine(1, "%s = clamp(float(%s), 0.0, 1.0);", builtInSemantic, resultName);
1748         }
1749         else if (outputIndex >= 0)
1750         {
1751             m_writer.WriteLine(1, "%s[%d] = %s;", builtInSemantic, outputIndex, resultName);
1752         }
1753         else
1754         {
1755             m_writer.WriteLine(1, "%s = %s;", builtInSemantic, resultName);
1756         }
1757     }
1758     else if (m_target == Target_FragmentShader)
1759     {
1760         Error("Output attribute %s does not map to any built-ins", semantic);
1761     }
1762     else
1763     {
1764         m_writer.WriteLine(1, "%s%s = %s;", m_outAttribPrefix, semantic, resultName);
1765     }
1766 }
1767 
OutputEntryCaller(HLSLFunction * entryFunction)1768 void GLSLGenerator::OutputEntryCaller(HLSLFunction* entryFunction)
1769 {
1770     HLSLRoot* root = m_tree->GetRoot();
1771 
1772     m_writer.WriteLine(0, "void main() {");
1773 
1774     // Create local variables for each of the parameters we'll need to pass
1775     // into the entry point function.
1776     HLSLArgument* argument = entryFunction->argument;
1777     while (argument != NULL)
1778     {
1779         m_writer.BeginLine(1);
1780         OutputDeclaration(argument->type, argument->name);
1781         m_writer.EndLine(";");
1782 
1783         if (argument->modifier != HLSLArgumentModifier_Out)
1784         {
1785             // Set the value for the local variable.
1786             if (argument->type.baseType == HLSLBaseType_UserDefined)
1787             {
1788                 HLSLStruct* structDeclaration = FindStruct(root, argument->type.typeName);
1789                 ASSERT(structDeclaration != NULL);
1790                 HLSLStructField* field = structDeclaration->field;
1791                 while (field != NULL)
1792                 {
1793                     if (field->semantic != NULL)
1794                     {
1795                         const char* builtInSemantic = GetBuiltInSemantic(field->semantic, AttributeModifier_In);
1796                         if (builtInSemantic)
1797                         {
1798                             m_writer.WriteLine(1, "%s.%s = %s;", GetSafeIdentifierName(argument->name), GetSafeIdentifierName(field->name), builtInSemantic);
1799                         }
1800                         else
1801                         {
1802                             m_writer.WriteLine(1, "%s.%s = %s%s;", GetSafeIdentifierName(argument->name), GetSafeIdentifierName(field->name), m_inAttribPrefix, field->semantic);
1803                         }
1804                     }
1805                     field = field->nextField;
1806                 }
1807             }
1808             else if (argument->semantic != NULL)
1809             {
1810                 const char* builtInSemantic = GetBuiltInSemantic(argument->semantic, AttributeModifier_In);
1811                 if (builtInSemantic)
1812                 {
1813                     m_writer.WriteLine(1, "%s = %s;", GetSafeIdentifierName(argument->name), builtInSemantic);
1814                 }
1815                 else
1816                 {
1817                     m_writer.WriteLine(1, "%s = %s%s;", GetSafeIdentifierName(argument->name), m_inAttribPrefix, argument->semantic);
1818                 }
1819             }
1820         }
1821 
1822         argument = argument->nextArgument;
1823     }
1824 
1825 
1826     // Initialize global variables
1827     for(HLSLDeclaration *declaration : globalVarsAssignments)
1828     {
1829         m_writer.BeginLine(1, declaration->fileName, declaration->line);
1830         OutputDeclarationBody( declaration->type, GetSafeIdentifierName( declaration->name ) );
1831 
1832         OutputDeclarationAssignment(declaration);
1833         m_writer.EndLine(";");
1834     }
1835 
1836 
1837     const char* resultName = "result";
1838 
1839     // Call the original entry function.
1840     m_writer.BeginLine(1);
1841     if (entryFunction->returnType.baseType != HLSLBaseType_Void)
1842         m_writer.Write("%s %s = ", GetTypeName(entryFunction->returnType), resultName);
1843     m_writer.Write("%s(", m_entryName);
1844 
1845     int numArgs = 0;
1846     argument = entryFunction->argument;
1847     while (argument != NULL)
1848     {
1849         if (numArgs > 0)
1850         {
1851             m_writer.Write(", ");
1852         }
1853 
1854         m_writer.Write("%s", GetSafeIdentifierName(argument->name));
1855 
1856         argument = argument->nextArgument;
1857         ++numArgs;
1858     }
1859     m_writer.EndLine(");");
1860 
1861     // Copy values from the result into the out attributes as necessary.
1862     argument = entryFunction->argument;
1863     while (argument != NULL)
1864     {
1865         if (argument->modifier == HLSLArgumentModifier_Out && argument->semantic)
1866             OutputSetOutAttribute(argument->semantic, GetSafeIdentifierName(argument->name));
1867 
1868         argument = argument->nextArgument;
1869     }
1870 
1871     if (entryFunction->returnType.baseType == HLSLBaseType_UserDefined)
1872     {
1873         HLSLStruct* structDeclaration = FindStruct(root, entryFunction->returnType.typeName);
1874         ASSERT(structDeclaration != NULL);
1875         HLSLStructField* field = structDeclaration->field;
1876         while (field != NULL)
1877         {
1878             char fieldResultName[1024];
1879             String_Printf( fieldResultName, sizeof(fieldResultName), "%s.%s", resultName, field->name );
1880             OutputSetOutAttribute( field->semantic, fieldResultName );
1881             field = field->nextField;
1882         }
1883     }
1884     else if (entryFunction->semantic != NULL)
1885     {
1886         OutputSetOutAttribute(entryFunction->semantic, resultName);
1887     }
1888 
1889     m_writer.WriteLine(0, "}");
1890 }
1891 
OutputDeclaration(HLSLDeclaration * declaration,const bool skipAssignment)1892 void GLSLGenerator::OutputDeclaration(HLSLDeclaration* declaration, const bool skipAssignment)
1893 {
1894 	OutputDeclarationType( declaration->type );
1895 
1896 	HLSLDeclaration* lastDecl = nullptr;
1897 	while( declaration )
1898 	{
1899 		if( lastDecl )
1900 			m_writer.Write( ", " );
1901 
1902 		OutputDeclarationBody( declaration->type, GetSafeIdentifierName( declaration->name ) );
1903 
1904 		if( declaration->assignment != NULL )
1905 		{
1906             if (!skipAssignment)
1907             {
1908                 OutputDeclarationAssignment(declaration);
1909             }
1910             else
1911             {
1912                 globalVarsAssignments.push_back(declaration);
1913             }
1914         }
1915 
1916 		lastDecl = declaration;
1917 		declaration = declaration->nextDeclaration;
1918 	}
1919 }
1920 
OutputDeclarationAssignment(HLSLDeclaration * declaration)1921 void GLSLGenerator::OutputDeclarationAssignment(HLSLDeclaration* declaration)
1922 {
1923    m_writer.Write( " = " );
1924    if( declaration->type.array )
1925    {
1926        m_writer.Write( "%s[]( ", GetTypeName( declaration->type ) );
1927        OutputExpressionList( declaration->assignment );
1928        m_writer.Write( " )" );
1929    }
1930    else
1931    {
1932        bool matrixCtorNeeded = false;
1933        if (IsMatrixType(declaration->type.baseType))
1934        {
1935            matrixCtor ctor = matrixCtorBuilder(declaration->type, declaration->assignment);
1936            if (std::find(matrixCtors.cbegin(), matrixCtors.cend(), ctor) != matrixCtors.cend())
1937            {
1938                matrixCtorNeeded = true;
1939            }
1940        }
1941 
1942        if (matrixCtorNeeded)
1943        {
1944            // Matrix contructors needs to be adapted since GLSL access a matrix as m[c][r] while HLSL is m[r][c]
1945            matrixCtor ctor = matrixCtorBuilder(declaration->type, declaration->assignment);
1946            m_writer.Write("%s(", matrixCtorsId[ctor].c_str());
1947            OutputExpressionList(declaration->assignment);
1948            m_writer.Write(")");
1949        }
1950        else
1951        {
1952            m_writer.Write( "%s( ", GetTypeName( declaration->type ) );
1953            OutputExpressionList( declaration->assignment );
1954            m_writer.Write( " )" );
1955        }
1956    }
1957 }
1958 
OutputDeclaration(const HLSLType & type,const char * name)1959 void GLSLGenerator::OutputDeclaration(const HLSLType& type, const char* name)
1960 {
1961 	OutputDeclarationType( type );
1962 	OutputDeclarationBody( type, name );
1963 }
1964 
OutputDeclarationType(const HLSLType & type)1965 void GLSLGenerator::OutputDeclarationType( const HLSLType& type )
1966 {
1967 	m_writer.Write( "%s ", GetTypeName( type ) );
1968 }
1969 
OutputDeclarationBody(const HLSLType & type,const char * name)1970 void GLSLGenerator::OutputDeclarationBody( const HLSLType& type, const char* name )
1971 {
1972 	if( !type.array )
1973 	{
1974 		m_writer.Write( "%s", GetSafeIdentifierName( name ) );
1975 	}
1976 	else
1977 	{
1978 		m_writer.Write( "%s[", GetSafeIdentifierName( name ) );
1979 		if( type.arraySize != NULL )
1980 		{
1981 			OutputExpression( type.arraySize );
1982 		}
1983 		m_writer.Write( "]" );
1984 	}
1985 }
1986 
OutputCast(const HLSLType & type)1987 void GLSLGenerator::OutputCast(const HLSLType& type)
1988 {
1989     if ((m_version == Version_110 || m_version == Version_120) && type.baseType == HLSLBaseType_Float3x3)
1990         m_writer.Write("%s", m_matrixCtorFunction);
1991     else
1992         OutputDeclaration(type, "");
1993 }
1994 
Error(const char * format,...)1995 void GLSLGenerator::Error(const char* format, ...)
1996 {
1997     // It's not always convenient to stop executing when an error occurs,
1998     // so just track once we've hit an error and stop reporting them until
1999     // we successfully bail out of execution.
2000     if (m_error)
2001     {
2002         return;
2003     }
2004     m_error = true;
2005 
2006     va_list arg;
2007     va_start(arg, format);
2008     Log_ErrorArgList(format, arg);
2009     va_end(arg);
2010 }
2011 
GetSafeIdentifierName(const char * name) const2012 const char* GLSLGenerator::GetSafeIdentifierName(const char* name) const
2013 {
2014     for (int i = 0; i < s_numReservedWords; ++i)
2015     {
2016         if (String_Equal(s_reservedWord[i], name))
2017         {
2018             return m_reservedWord[i];
2019         }
2020     }
2021     return name;
2022 }
2023 
ChooseUniqueName(const char * base,char * dst,int dstLength) const2024 bool GLSLGenerator::ChooseUniqueName(const char* base, char* dst, int dstLength) const
2025 {
2026     for (int i = 0; i < 1024; ++i)
2027     {
2028         String_Printf(dst, dstLength, "%s%d", base, i);
2029         if (!m_tree->GetContainsString(dst))
2030         {
2031             return true;
2032         }
2033     }
2034     return false;
2035 }
2036 
GetBuiltInSemantic(const char * semantic,AttributeModifier modifier,int * outputIndex)2037 const char* GLSLGenerator::GetBuiltInSemantic(const char* semantic, AttributeModifier modifier, int* outputIndex)
2038 {
2039     if (outputIndex)
2040         *outputIndex = -1;
2041 
2042     if (m_target == Target_VertexShader && modifier == AttributeModifier_Out && String_Equal(semantic, "POSITION"))
2043         return "gl_Position";
2044 
2045     if (m_target == Target_VertexShader && modifier == AttributeModifier_Out && String_Equal(semantic, "SV_Position"))
2046         return "gl_Position";
2047 
2048     if (m_target == Target_VertexShader && modifier == AttributeModifier_Out && String_Equal(semantic, "PSIZE"))
2049         return "gl_PointSize";
2050 
2051     if (m_target == Target_VertexShader && modifier == AttributeModifier_In && String_Equal(semantic, "SV_InstanceID"))
2052         return "gl_InstanceID";
2053 
2054     if (m_target == Target_FragmentShader && modifier == AttributeModifier_Out && String_Equal(semantic, "SV_Depth"))
2055         return "gl_FragDepth";
2056 
2057     if (m_target == Target_FragmentShader && modifier == AttributeModifier_In && String_Equal(semantic, "SV_Position"))
2058         return "gl_FragCoord";
2059 
2060     if (m_target == Target_FragmentShader && modifier == AttributeModifier_Out)
2061     {
2062         int index = -1;
2063 
2064         if (strncmp(semantic, "COLOR", 5) == 0)
2065             index = atoi(semantic + 5);
2066         else if (strncmp(semantic, "SV_Target", 9) == 0)
2067             index = atoi(semantic + 9);
2068 
2069         if (index >= 0)
2070         {
2071             if (m_outputTargets <= index)
2072                 m_outputTargets = index + 1;
2073 
2074             if (outputIndex)
2075                 *outputIndex = index;
2076 
2077             return m_versionLegacy ? "gl_FragData" : "rast_FragData";
2078         }
2079     }
2080 
2081     return NULL;
2082 }
2083 
CompleteConstructorArguments(HLSLExpression * expression,HLSLBaseType dstType)2084 void GLSLGenerator::CompleteConstructorArguments(HLSLExpression* expression, HLSLBaseType dstType)
2085 {
2086     int nbComponentsProvided = 0;
2087     int nbComponentsNeeded = 0;
2088 
2089     const BaseTypeDescription& dstTypeDesc = baseTypeDescriptions[dstType];
2090     nbComponentsNeeded = dstTypeDesc.numComponents * dstTypeDesc.height;
2091 
2092     const BaseTypeDescription& srcTypeDesc = baseTypeDescriptions[expression->expressionType.baseType];
2093     nbComponentsProvided = srcTypeDesc.numComponents * srcTypeDesc.height;
2094     if (IsMatrixType(expression->expressionType.baseType) ||
2095         IsVectorType(expression->expressionType.baseType) )
2096     {
2097         for(int i = nbComponentsProvided; i < nbComponentsNeeded; i++)
2098         {
2099             m_writer.Write(", 0");
2100         }
2101     }
2102 }
2103 
2104 
OutputMatrixCtors()2105 void GLSLGenerator::OutputMatrixCtors() {
2106     for(matrixCtor & ctor : matrixCtors)
2107     {
2108         m_writer.Write("%s %s(",
2109                             GetTypeName(HLSLType(ctor.matrixType)),
2110                             matrixCtorsId[ctor].c_str());
2111         int argNum = 0;
2112         for(HLSLBaseType argType : ctor.argumentTypes)
2113         {
2114             if (argNum == 0)
2115             {
2116                 m_writer.Write("%s %c", GetTypeName(HLSLType(argType)), 'a' + argNum);
2117             }
2118             else
2119             {
2120                 m_writer.Write(", %s %c", GetTypeName(HLSLType(argType)), 'a' + argNum);
2121             }
2122             argNum++;
2123         }
2124         m_writer.Write( ") { return %s(", GetTypeName(HLSLType(ctor.matrixType)));
2125 
2126         const BaseTypeDescription& ctorTypeDesc = baseTypeDescriptions[ctor.matrixType];
2127         std::vector<std::string> args(ctorTypeDesc.numComponents * ctorTypeDesc.height, "0");
2128         int argNumIn = 0;
2129         int argNumOut = 0;
2130         for(HLSLBaseType argType : ctor.argumentTypes)
2131         {
2132             std::string arg;
2133             arg += 'a' + argNumIn;
2134 
2135             if (IsScalarType(argType))
2136             {
2137                 int index = (argNumOut % ctorTypeDesc.height) * (ctorTypeDesc.numComponents) +
2138                             (argNumOut / ctorTypeDesc.height);
2139                 args[index] = arg;
2140                 argNumOut++;
2141             }
2142             else if (IsVectorType(argType))
2143             {
2144                 const BaseTypeDescription& argTypeDesc = baseTypeDescriptions[argType];
2145                 for(int dim = 0; dim < argTypeDesc.numComponents; dim++)
2146                 {
2147                     std::string argVect = arg + ".";
2148                     argVect += "xyzw"[dim];
2149                     int index = (argNumOut % ctorTypeDesc.height) * (ctorTypeDesc.numComponents) +
2150                                 (argNumOut / ctorTypeDesc.height);
2151                     args[index] = argVect;
2152                     argNumOut++;
2153                 }
2154             }
2155 
2156             argNumIn++;
2157         }
2158 
2159         bool first = true;
2160         for(std::string & arg : args)
2161         {
2162             if (!first)
2163             {
2164                 m_writer.Write(",%s", arg.c_str());
2165             }
2166             else
2167             {
2168                 m_writer.Write("%s", arg.c_str());
2169             }
2170             first = false;
2171         }
2172 
2173         m_writer.Write("); }");
2174         m_writer.EndLine();
2175     }
2176 }
2177 
2178 
2179 }
2180