blob: 584d65377b8d9b2e1cc84ebaca362442be517f8e [file] [log] [blame]
daniel@transgaming.com91ed1492010-10-29 03:11:43 +00001//
2// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Lang17732822013-08-29 13:46:49 -04007#include "compiler/translator/util.h"
daniel@transgaming.com91ed1492010-10-29 03:11:43 +00008
Zhenyao Mof1d723c2013-09-23 14:57:07 -04009#include <limits>
10
Zhenyao Mocc4ec642013-09-23 14:57:10 -040011#include "compiler/preprocessor/numeric_lex.h"
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070012#include "compiler/translator/SymbolTable.h"
Jamie Madill77f74852014-07-08 15:02:34 -040013#include "common/utilities.h"
daniel@transgaming.com91ed1492010-10-29 03:11:43 +000014
Corentin Walleze2adce12015-06-19 23:06:32 +020015bool strtof_clamp(const std::string &str, float *value)
daniel@transgaming.com91ed1492010-10-29 03:11:43 +000016{
Zhenyao Mocc4ec642013-09-23 14:57:10 -040017 bool success = pp::numeric_lex_float(str, value);
Zhenyao Mof1d723c2013-09-23 14:57:07 -040018 if (!success)
19 *value = std::numeric_limits<float>::max();
20 return success;
daniel@transgaming.com91ed1492010-10-29 03:11:43 +000021}
Zhenyao Mof1d723c2013-09-23 14:57:07 -040022
Olli Etuahof541f522015-10-13 12:21:01 +030023bool atoi_clamp(const char *str, unsigned int *value)
Zhenyao Mof1d723c2013-09-23 14:57:07 -040024{
Zhenyao Mocc4ec642013-09-23 14:57:10 -040025 bool success = pp::numeric_lex_int(str, value);
26 if (!success)
Olli Etuahof541f522015-10-13 12:21:01 +030027 *value = std::numeric_limits<unsigned int>::max();
Zhenyao Mocc4ec642013-09-23 14:57:10 -040028 return success;
Zhenyao Mof1d723c2013-09-23 14:57:07 -040029}
30
Jamie Madill033dae62014-06-18 12:56:28 -040031namespace sh
32{
33
34GLenum GLVariableType(const TType &type)
35{
36 if (type.getBasicType() == EbtFloat)
37 {
38 if (type.isScalar())
39 {
40 return GL_FLOAT;
41 }
42 else if (type.isVector())
43 {
44 switch (type.getNominalSize())
45 {
46 case 2: return GL_FLOAT_VEC2;
47 case 3: return GL_FLOAT_VEC3;
48 case 4: return GL_FLOAT_VEC4;
49 default: UNREACHABLE();
50 }
51 }
52 else if (type.isMatrix())
53 {
54 switch (type.getCols())
55 {
56 case 2:
57 switch (type.getRows())
58 {
59 case 2: return GL_FLOAT_MAT2;
60 case 3: return GL_FLOAT_MAT2x3;
61 case 4: return GL_FLOAT_MAT2x4;
62 default: UNREACHABLE();
63 }
64
65 case 3:
66 switch (type.getRows())
67 {
68 case 2: return GL_FLOAT_MAT3x2;
69 case 3: return GL_FLOAT_MAT3;
70 case 4: return GL_FLOAT_MAT3x4;
71 default: UNREACHABLE();
72 }
73
74 case 4:
75 switch (type.getRows())
76 {
77 case 2: return GL_FLOAT_MAT4x2;
78 case 3: return GL_FLOAT_MAT4x3;
79 case 4: return GL_FLOAT_MAT4;
80 default: UNREACHABLE();
81 }
82
83 default: UNREACHABLE();
84 }
85 }
86 else UNREACHABLE();
87 }
88 else if (type.getBasicType() == EbtInt)
89 {
90 if (type.isScalar())
91 {
92 return GL_INT;
93 }
94 else if (type.isVector())
95 {
96 switch (type.getNominalSize())
97 {
98 case 2: return GL_INT_VEC2;
99 case 3: return GL_INT_VEC3;
100 case 4: return GL_INT_VEC4;
101 default: UNREACHABLE();
102 }
103 }
104 else UNREACHABLE();
105 }
106 else if (type.getBasicType() == EbtUInt)
107 {
108 if (type.isScalar())
109 {
110 return GL_UNSIGNED_INT;
111 }
112 else if (type.isVector())
113 {
114 switch (type.getNominalSize())
115 {
116 case 2: return GL_UNSIGNED_INT_VEC2;
117 case 3: return GL_UNSIGNED_INT_VEC3;
118 case 4: return GL_UNSIGNED_INT_VEC4;
119 default: UNREACHABLE();
120 }
121 }
122 else UNREACHABLE();
123 }
124 else if (type.getBasicType() == EbtBool)
125 {
126 if (type.isScalar())
127 {
128 return GL_BOOL;
129 }
130 else if (type.isVector())
131 {
132 switch (type.getNominalSize())
133 {
134 case 2: return GL_BOOL_VEC2;
135 case 3: return GL_BOOL_VEC3;
136 case 4: return GL_BOOL_VEC4;
137 default: UNREACHABLE();
138 }
139 }
140 else UNREACHABLE();
141 }
142
143 switch (type.getBasicType())
144 {
145 case EbtSampler2D: return GL_SAMPLER_2D;
146 case EbtSampler3D: return GL_SAMPLER_3D;
147 case EbtSamplerCube: return GL_SAMPLER_CUBE;
Jamie Madillaa72d782014-07-02 15:31:19 -0400148 case EbtSamplerExternalOES: return GL_SAMPLER_EXTERNAL_OES;
149 case EbtSampler2DRect: return GL_SAMPLER_2D_RECT_ARB;
Jamie Madill033dae62014-06-18 12:56:28 -0400150 case EbtSampler2DArray: return GL_SAMPLER_2D_ARRAY;
151 case EbtISampler2D: return GL_INT_SAMPLER_2D;
152 case EbtISampler3D: return GL_INT_SAMPLER_3D;
153 case EbtISamplerCube: return GL_INT_SAMPLER_CUBE;
154 case EbtISampler2DArray: return GL_INT_SAMPLER_2D_ARRAY;
155 case EbtUSampler2D: return GL_UNSIGNED_INT_SAMPLER_2D;
156 case EbtUSampler3D: return GL_UNSIGNED_INT_SAMPLER_3D;
157 case EbtUSamplerCube: return GL_UNSIGNED_INT_SAMPLER_CUBE;
158 case EbtUSampler2DArray: return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
159 case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW;
160 case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW;
161 case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW;
162 default: UNREACHABLE();
163 }
164
165 return GL_NONE;
166}
167
168GLenum GLVariablePrecision(const TType &type)
169{
170 if (type.getBasicType() == EbtFloat)
171 {
172 switch (type.getPrecision())
173 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400174 case EbpHigh:
Jamie Madill033dae62014-06-18 12:56:28 -0400175 return GL_HIGH_FLOAT;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400176 case EbpMedium:
Jamie Madill033dae62014-06-18 12:56:28 -0400177 return GL_MEDIUM_FLOAT;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400178 case EbpLow:
Jamie Madill033dae62014-06-18 12:56:28 -0400179 return GL_LOW_FLOAT;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400180 case EbpUndefined:
181 // Should be defined as the default precision by the parser
182 default:
Jamie Madill033dae62014-06-18 12:56:28 -0400183 UNREACHABLE();
184 }
185 }
186 else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
187 {
188 switch (type.getPrecision())
189 {
190 case EbpHigh:
191 return GL_HIGH_INT;
192 case EbpMedium:
193 return GL_MEDIUM_INT;
194 case EbpLow:
195 return GL_LOW_INT;
196 case EbpUndefined:
197 // Should be defined as the default precision by the parser
198 default:
199 UNREACHABLE();
200 }
201 }
202
203 // Other types (boolean, sampler) don't have a precision
204 return GL_NONE;
205}
206
207TString ArrayString(const TType &type)
208{
209 if (!type.isArray())
210 {
211 return "";
212 }
213
214 return "[" + str(type.getArraySize()) + "]";
215}
216
217bool IsVaryingOut(TQualifier qualifier)
218{
219 switch (qualifier)
220 {
221 case EvqVaryingOut:
Jamie Madill033dae62014-06-18 12:56:28 -0400222 case EvqSmoothOut:
223 case EvqFlatOut:
224 case EvqCentroidOut:
225 case EvqVertexOut:
226 return true;
227
228 default: break;
229 }
230
231 return false;
232}
233
234bool IsVaryingIn(TQualifier qualifier)
235{
236 switch (qualifier)
237 {
238 case EvqVaryingIn:
Jamie Madill033dae62014-06-18 12:56:28 -0400239 case EvqSmoothIn:
240 case EvqFlatIn:
241 case EvqCentroidIn:
242 case EvqFragmentIn:
243 return true;
244
245 default: break;
246 }
247
248 return false;
249}
250
251bool IsVarying(TQualifier qualifier)
252{
253 return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
254}
255
Jamie Madillf2575982014-06-25 16:04:54 -0400256InterpolationType GetInterpolationType(TQualifier qualifier)
Jamie Madill033dae62014-06-18 12:56:28 -0400257{
258 switch (qualifier)
259 {
260 case EvqFlatIn:
261 case EvqFlatOut:
Jamie Madillf2575982014-06-25 16:04:54 -0400262 return INTERPOLATION_FLAT;
Jamie Madill033dae62014-06-18 12:56:28 -0400263
264 case EvqSmoothIn:
265 case EvqSmoothOut:
266 case EvqVertexOut:
267 case EvqFragmentIn:
268 case EvqVaryingIn:
269 case EvqVaryingOut:
Jamie Madillf2575982014-06-25 16:04:54 -0400270 return INTERPOLATION_SMOOTH;
Jamie Madill033dae62014-06-18 12:56:28 -0400271
272 case EvqCentroidIn:
273 case EvqCentroidOut:
Jamie Madillf2575982014-06-25 16:04:54 -0400274 return INTERPOLATION_CENTROID;
Jamie Madill033dae62014-06-18 12:56:28 -0400275
276 default: UNREACHABLE();
Jamie Madillf2575982014-06-25 16:04:54 -0400277 return INTERPOLATION_SMOOTH;
Jamie Madill033dae62014-06-18 12:56:28 -0400278 }
279}
280
Qin Jiajia7835b522016-10-08 11:20:17 +0800281TType GetInterfaceBlockType(const sh::InterfaceBlock &block)
282{
283 TType type;
284 TFieldList *fields = new TFieldList;
285 TSourceLoc loc;
286 for (const auto &field : block.fields)
287 {
288 TType *fieldType = new TType(GetShaderVariableType(field));
289 fields->push_back(new TField(fieldType, new TString(field.name.c_str()), loc));
290 }
291
292 TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
293 new TString(block.name.c_str()), fields, new TString(block.instanceName.c_str()),
294 block.arraySize, TLayoutQualifier::create());
295
296 type.setBasicType(EbtInterfaceBlock);
297 type.setInterfaceBlock(interfaceBlock);
298 type.setArraySize(block.arraySize);
299 return type;
300}
301
Corentin Wallez509e4562016-08-25 14:55:44 -0400302TType GetShaderVariableBasicType(const sh::ShaderVariable &var)
Zhenyao Mo72111912016-07-20 17:45:56 -0700303{
Corentin Wallez509e4562016-08-25 14:55:44 -0400304 switch (var.type)
Zhenyao Mo72111912016-07-20 17:45:56 -0700305 {
Qin Jiajia7835b522016-10-08 11:20:17 +0800306 case GL_BOOL:
307 return TType(EbtBool);
308 case GL_BOOL_VEC2:
309 return TType(EbtBool, 2);
310 case GL_BOOL_VEC3:
311 return TType(EbtBool, 3);
312 case GL_BOOL_VEC4:
313 return TType(EbtBool, 4);
Zhenyao Mo72111912016-07-20 17:45:56 -0700314 case GL_FLOAT:
315 return TType(EbtFloat);
316 case GL_FLOAT_VEC2:
317 return TType(EbtFloat, 2);
318 case GL_FLOAT_VEC3:
319 return TType(EbtFloat, 3);
320 case GL_FLOAT_VEC4:
321 return TType(EbtFloat, 4);
322 case GL_FLOAT_MAT2:
323 return TType(EbtFloat, 2, 2);
324 case GL_FLOAT_MAT3:
325 return TType(EbtFloat, 3, 3);
326 case GL_FLOAT_MAT4:
327 return TType(EbtFloat, 4, 4);
328 case GL_FLOAT_MAT2x3:
329 return TType(EbtFloat, 2, 3);
330 case GL_FLOAT_MAT2x4:
331 return TType(EbtFloat, 2, 4);
332 case GL_FLOAT_MAT3x2:
333 return TType(EbtFloat, 3, 2);
334 case GL_FLOAT_MAT3x4:
335 return TType(EbtFloat, 3, 4);
336 case GL_FLOAT_MAT4x2:
337 return TType(EbtFloat, 4, 2);
338 case GL_FLOAT_MAT4x3:
339 return TType(EbtFloat, 4, 3);
340 case GL_INT:
341 return TType(EbtInt);
342 case GL_INT_VEC2:
343 return TType(EbtInt, 2);
344 case GL_INT_VEC3:
345 return TType(EbtInt, 3);
346 case GL_INT_VEC4:
347 return TType(EbtInt, 4);
348 case GL_UNSIGNED_INT:
349 return TType(EbtUInt);
350 case GL_UNSIGNED_INT_VEC2:
351 return TType(EbtUInt, 2);
352 case GL_UNSIGNED_INT_VEC3:
353 return TType(EbtUInt, 3);
354 case GL_UNSIGNED_INT_VEC4:
355 return TType(EbtUInt, 4);
356 default:
357 UNREACHABLE();
358 return TType();
359 }
360}
361
Corentin Wallez509e4562016-08-25 14:55:44 -0400362TType GetShaderVariableType(const sh::ShaderVariable &var)
363{
364 TType type;
365 if (var.isStruct())
366 {
367 TFieldList *fields = new TFieldList;
368 TSourceLoc loc;
369 for (const auto &field : var.fields)
370 {
371 TType *fieldType = new TType(GetShaderVariableType(field));
372 fields->push_back(new TField(fieldType, new TString(field.name.c_str()), loc));
373 }
374 TStructure *structure = new TStructure(new TString(var.structName.c_str()), fields);
375
376 type.setBasicType(EbtStruct);
377 type.setStruct(structure);
378 }
379 else
380 {
381 type = GetShaderVariableBasicType(var);
382 }
383
384 if (var.isArray())
385 {
386 type.setArraySize(var.elementCount());
387 }
388 return type;
389}
390
Geoff Lang156d7192016-07-21 16:11:00 -0400391TOperator TypeToConstructorOperator(const TType &type)
392{
393 switch (type.getBasicType())
394 {
395 case EbtFloat:
396 if (type.isMatrix())
397 {
398 switch (type.getCols())
399 {
400 case 2:
401 switch (type.getRows())
402 {
403 case 2:
404 return EOpConstructMat2;
405 case 3:
406 return EOpConstructMat2x3;
407 case 4:
408 return EOpConstructMat2x4;
409 default:
410 break;
411 }
412 break;
413
414 case 3:
415 switch (type.getRows())
416 {
417 case 2:
418 return EOpConstructMat3x2;
419 case 3:
420 return EOpConstructMat3;
421 case 4:
422 return EOpConstructMat3x4;
423 default:
424 break;
425 }
426 break;
427
428 case 4:
429 switch (type.getRows())
430 {
431 case 2:
432 return EOpConstructMat4x2;
433 case 3:
434 return EOpConstructMat4x3;
435 case 4:
436 return EOpConstructMat4;
437 default:
438 break;
439 }
440 break;
441 }
442 }
443 else
444 {
445 switch (type.getNominalSize())
446 {
447 case 1:
448 return EOpConstructFloat;
449 case 2:
450 return EOpConstructVec2;
451 case 3:
452 return EOpConstructVec3;
453 case 4:
454 return EOpConstructVec4;
455 default:
456 break;
457 }
458 }
459 break;
460
461 case EbtInt:
462 switch (type.getNominalSize())
463 {
464 case 1:
465 return EOpConstructInt;
466 case 2:
467 return EOpConstructIVec2;
468 case 3:
469 return EOpConstructIVec3;
470 case 4:
471 return EOpConstructIVec4;
472 default:
473 break;
474 }
475 break;
476
477 case EbtUInt:
478 switch (type.getNominalSize())
479 {
480 case 1:
481 return EOpConstructUInt;
482 case 2:
483 return EOpConstructUVec2;
484 case 3:
485 return EOpConstructUVec3;
486 case 4:
487 return EOpConstructUVec4;
488 default:
489 break;
490 }
491 break;
492
493 case EbtBool:
494 switch (type.getNominalSize())
495 {
496 case 1:
497 return EOpConstructBool;
498 case 2:
499 return EOpConstructBVec2;
500 case 3:
501 return EOpConstructBVec3;
502 case 4:
503 return EOpConstructBVec4;
504 default:
505 break;
506 }
507 break;
508
509 case EbtStruct:
510 return EOpConstructStruct;
511
512 default:
513 break;
514 }
515
516 return EOpNull;
517}
518
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700519GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable)
520 : mSymbolTable(symbolTable)
521{
522}
523
524template void GetVariableTraverser::setTypeSpecificInfo(
525 const TType &type, const TString& name, InterfaceBlockField *variable);
526template void GetVariableTraverser::setTypeSpecificInfo(
527 const TType &type, const TString& name, ShaderVariable *variable);
528template void GetVariableTraverser::setTypeSpecificInfo(
529 const TType &type, const TString& name, Uniform *variable);
530
531template<>
532void GetVariableTraverser::setTypeSpecificInfo(
533 const TType &type, const TString& name, Varying *variable)
534{
535 ASSERT(variable);
536 switch (type.getQualifier())
537 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700538 case EvqVaryingIn:
539 case EvqVaryingOut:
Olli Etuaho37ad4742015-04-27 13:18:50 +0300540 case EvqVertexOut:
541 case EvqSmoothOut:
542 case EvqFlatOut:
543 case EvqCentroidOut:
Olli Etuaho214c2d82015-04-27 14:49:13 +0300544 if (mSymbolTable.isVaryingInvariant(std::string(name.c_str())) || type.isInvariant())
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700545 {
546 variable->isInvariant = true;
547 }
548 break;
549 default:
550 break;
551 }
Jamie Madill70a0b2a2014-10-21 11:48:39 -0400552
553 variable->interpolation = GetInterpolationType(type.getQualifier());
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700554}
555
Jamie Madill77f74852014-07-08 15:02:34 -0400556template <typename VarT>
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700557void GetVariableTraverser::traverse(const TType &type,
558 const TString &name,
559 std::vector<VarT> *output)
Jamie Madill77f74852014-07-08 15:02:34 -0400560{
561 const TStructure *structure = type.getStruct();
562
563 VarT variable;
564 variable.name = name.c_str();
Olli Etuaho856c4972016-08-08 11:38:39 +0300565 variable.arraySize = type.getArraySize();
Jamie Madill77f74852014-07-08 15:02:34 -0400566
567 if (!structure)
568 {
569 variable.type = GLVariableType(type);
570 variable.precision = GLVariablePrecision(type);
571 }
572 else
573 {
Jamie Madill42bcf322014-08-25 16:20:46 -0400574 // Note: this enum value is not exposed outside ANGLE
Jamie Madill77f74852014-07-08 15:02:34 -0400575 variable.type = GL_STRUCT_ANGLEX;
Jamie Madill42bcf322014-08-25 16:20:46 -0400576 variable.structName = structure->name().c_str();
Jamie Madill77f74852014-07-08 15:02:34 -0400577
578 const TFieldList &fields = structure->fields();
579
580 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
581 {
582 TField *field = fields[fieldIndex];
Jamie Madill42bcf322014-08-25 16:20:46 -0400583 traverse(*field->type(), field->name(), &variable.fields);
Jamie Madill77f74852014-07-08 15:02:34 -0400584 }
Jamie Madill77f74852014-07-08 15:02:34 -0400585 }
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700586 setTypeSpecificInfo(type, name, &variable);
Jamie Madill77f74852014-07-08 15:02:34 -0400587 visitVariable(&variable);
588
Jamie Madill77f74852014-07-08 15:02:34 -0400589 ASSERT(output);
Jamie Madill42bcf322014-08-25 16:20:46 -0400590 output->push_back(variable);
Jamie Madill77f74852014-07-08 15:02:34 -0400591}
592
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700593template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
594template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *);
Jamie Madill42bcf322014-08-25 16:20:46 -0400595template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
596template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
Jamie Madill77f74852014-07-08 15:02:34 -0400597
Martin Radev70866b82016-07-22 15:27:42 +0300598// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier
599bool CanBeInvariantESSL1(TQualifier qualifier)
600{
601 return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) ||
602 IsBuiltinOutputVariable(qualifier) ||
603 (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing);
Jamie Madill033dae62014-06-18 12:56:28 -0400604}
Martin Radev70866b82016-07-22 15:27:42 +0300605
606// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier
607// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier
608bool CanBeInvariantESSL3OrGreater(TQualifier qualifier)
609{
610 return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut ||
611 IsBuiltinOutputVariable(qualifier);
612}
613
614bool IsBuiltinOutputVariable(TQualifier qualifier)
615{
616 switch (qualifier)
617 {
618 case EvqPosition:
619 case EvqPointSize:
620 case EvqFragDepth:
621 case EvqFragDepthEXT:
622 case EvqFragColor:
623 case EvqSecondaryFragColorEXT:
624 case EvqFragData:
625 case EvqSecondaryFragDataEXT:
626 return true;
627 default:
628 break;
629 }
630 return false;
631}
632
633bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
634{
635 switch (qualifier)
636 {
637 case EvqFragCoord:
638 case EvqPointCoord:
639 case EvqFrontFacing:
640 return true;
641 default:
642 break;
643 }
644 return false;
645}
646} // namespace sh