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