Line data Source code
1 : //
2 : // Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
3 : // Use of this source code is governed by a BSD-style license that can be
4 : // found in the LICENSE file.
5 : //
6 :
7 : #include "compiler/translator/QualifierTypes.h"
8 :
9 : #include "compiler/translator/Diagnostics.h"
10 :
11 : #include <algorithm>
12 :
13 : namespace sh
14 : {
15 :
16 : namespace
17 : {
18 :
19 : // GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout
20 : // declarations.
21 : // GLSL ES 3.10 Revision 4, 4.10 Order of Qualification
22 0 : bool AreTypeQualifierChecksRelaxed(int shaderVersion)
23 : {
24 0 : return shaderVersion >= 310;
25 : }
26 :
27 0 : bool IsScopeQualifier(TQualifier qualifier)
28 : {
29 0 : return qualifier == EvqGlobal || qualifier == EvqTemporary;
30 : }
31 :
32 0 : bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier)
33 : {
34 0 : if (qualifier->getType() != QtStorage)
35 0 : return false;
36 : const TStorageQualifierWrapper *storageQualifier =
37 0 : static_cast<const TStorageQualifierWrapper *>(qualifier);
38 0 : TQualifier q = storageQualifier->getQualifier();
39 0 : return IsScopeQualifier(q);
40 : }
41 :
42 : // Returns true if the invariant for the qualifier sequence holds
43 0 : bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers)
44 : {
45 : // We should have at least one qualifier.
46 : // The first qualifier always tells the scope.
47 0 : return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]);
48 : }
49 :
50 : // Returns true if there are qualifiers which have been specified multiple times
51 : // If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed.
52 0 : bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
53 : bool areQualifierChecksRelaxed,
54 : std::string *errorMessage)
55 : {
56 0 : bool invariantFound = false;
57 0 : bool precisionFound = false;
58 0 : bool layoutFound = false;
59 0 : bool interpolationFound = false;
60 :
61 0 : unsigned int locationsSpecified = 0;
62 0 : bool isOut = false;
63 :
64 : // The iteration starts from one since the first qualifier only reveals the scope of the
65 : // expression. It is inserted first whenever the sequence gets created.
66 0 : for (size_t i = 1; i < qualifiers.size(); ++i)
67 : {
68 0 : switch (qualifiers[i]->getType())
69 : {
70 : case QtInvariant:
71 : {
72 0 : if (invariantFound)
73 : {
74 0 : *errorMessage = "The invariant qualifier specified multiple times.";
75 0 : return true;
76 : }
77 0 : invariantFound = true;
78 0 : break;
79 : }
80 : case QtPrecision:
81 : {
82 0 : if (precisionFound)
83 : {
84 0 : *errorMessage = "The precision qualifier specified multiple times.";
85 0 : return true;
86 : }
87 0 : precisionFound = true;
88 0 : break;
89 : }
90 : case QtLayout:
91 : {
92 0 : if (layoutFound && !areQualifierChecksRelaxed)
93 : {
94 0 : *errorMessage = "The layout qualifier specified multiple times.";
95 0 : return true;
96 : }
97 0 : if (invariantFound && !areQualifierChecksRelaxed)
98 : {
99 : // This combination is not correct according to the syntax specified in the
100 : // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have
101 : // a similar restriction.
102 : *errorMessage =
103 : "The layout qualifier and invariant qualifier cannot coexist in the same "
104 0 : "declaration according to the grammar.";
105 0 : return true;
106 : }
107 0 : layoutFound = true;
108 : const TLayoutQualifier ¤tQualifier =
109 0 : static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier();
110 0 : locationsSpecified += currentQualifier.locationsSpecified;
111 0 : break;
112 : }
113 : case QtInterpolation:
114 : {
115 : // 'centroid' is treated as a storage qualifier
116 : // 'flat centroid' will be squashed to 'flat'
117 : // 'smooth centroid' will be squashed to 'centroid'
118 0 : if (interpolationFound)
119 : {
120 0 : *errorMessage = "The interpolation qualifier specified multiple times.";
121 0 : return true;
122 : }
123 0 : interpolationFound = true;
124 0 : break;
125 : }
126 : case QtStorage:
127 : {
128 : // Go over all of the storage qualifiers up until the current one and check for
129 : // repetitions.
130 : TQualifier currentQualifier =
131 0 : static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
132 0 : if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
133 : {
134 0 : isOut = true;
135 : }
136 0 : for (size_t j = 1; j < i; ++j)
137 : {
138 0 : if (qualifiers[j]->getType() == QtStorage)
139 : {
140 : const TStorageQualifierWrapper *previousQualifierWrapper =
141 0 : static_cast<const TStorageQualifierWrapper *>(qualifiers[j]);
142 0 : TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
143 0 : if (currentQualifier == previousQualifier)
144 : {
145 0 : *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
146 0 : *errorMessage += " specified multiple times";
147 0 : return true;
148 : }
149 : }
150 : }
151 0 : break;
152 : }
153 : case QtMemory:
154 : {
155 : // Go over all of the memory qualifiers up until the current one and check for
156 : // repetitions.
157 : // Having both readonly and writeonly in a sequence is valid.
158 : // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
159 : TQualifier currentQualifier =
160 0 : static_cast<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier();
161 0 : for (size_t j = 1; j < i; ++j)
162 : {
163 0 : if (qualifiers[j]->getType() == QtMemory)
164 : {
165 : const TMemoryQualifierWrapper *previousQualifierWrapper =
166 0 : static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]);
167 0 : TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
168 0 : if (currentQualifier == previousQualifier)
169 : {
170 0 : *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
171 0 : *errorMessage += " specified multiple times";
172 0 : return true;
173 : }
174 : }
175 : }
176 0 : break;
177 : }
178 : default:
179 0 : UNREACHABLE();
180 : }
181 : }
182 :
183 0 : if (locationsSpecified > 1 && isOut)
184 : {
185 : // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers
186 : // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers
187 : // "The qualifier may appear at most once within a declaration."
188 0 : *errorMessage = "Output layout location specified multiple times.";
189 0 : return true;
190 : }
191 :
192 0 : return false;
193 : }
194 :
195 : // GLSL ES 3.00_6, 4.7 Order of Qualification
196 : // The correct order of qualifiers is:
197 : // invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier
198 : // layout-qualifier has to be before storage-qualifier.
199 0 : bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
200 : std::string *errorMessage)
201 : {
202 0 : bool foundInterpolation = false;
203 0 : bool foundStorage = false;
204 0 : bool foundPrecision = false;
205 0 : for (size_t i = 1; i < qualifiers.size(); ++i)
206 : {
207 0 : switch (qualifiers[i]->getType())
208 : {
209 : case QtInvariant:
210 0 : if (foundInterpolation || foundStorage || foundPrecision)
211 : {
212 0 : *errorMessage = "The invariant qualifier has to be first in the expression.";
213 0 : return false;
214 : }
215 0 : break;
216 : case QtInterpolation:
217 0 : if (foundStorage)
218 : {
219 0 : *errorMessage = "Storage qualifiers have to be after interpolation qualifiers.";
220 0 : return false;
221 : }
222 0 : else if (foundPrecision)
223 : {
224 : *errorMessage =
225 0 : "Precision qualifiers have to be after interpolation qualifiers.";
226 0 : return false;
227 : }
228 0 : foundInterpolation = true;
229 0 : break;
230 : case QtLayout:
231 0 : if (foundStorage)
232 : {
233 0 : *errorMessage = "Storage qualifiers have to be after layout qualifiers.";
234 0 : return false;
235 : }
236 0 : else if (foundPrecision)
237 : {
238 0 : *errorMessage = "Precision qualifiers have to be after layout qualifiers.";
239 0 : return false;
240 : }
241 0 : break;
242 : case QtStorage:
243 0 : if (foundPrecision)
244 : {
245 0 : *errorMessage = "Precision qualifiers have to be after storage qualifiers.";
246 0 : return false;
247 : }
248 0 : foundStorage = true;
249 0 : break;
250 : case QtMemory:
251 0 : if (foundPrecision)
252 : {
253 0 : *errorMessage = "Precision qualifiers have to be after memory qualifiers.";
254 0 : return false;
255 : }
256 0 : break;
257 : case QtPrecision:
258 0 : foundPrecision = true;
259 0 : break;
260 : default:
261 0 : UNREACHABLE();
262 : }
263 : }
264 0 : return true;
265 : }
266 :
267 : struct QualifierComparator
268 : {
269 0 : bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2)
270 : {
271 0 : return q1->getRank() < q2->getRank();
272 : }
273 : };
274 :
275 0 : void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers)
276 : {
277 : // We need a stable sorting algorithm since the order of layout-qualifier declarations matter.
278 : // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope
279 : // and we always want it to be first.
280 0 : std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator());
281 0 : }
282 :
283 : // Handles the joining of storage qualifiers for variables.
284 0 : bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
285 : {
286 0 : switch (*joinedQualifier)
287 : {
288 : case EvqGlobal:
289 0 : *joinedQualifier = storageQualifier;
290 0 : break;
291 : case EvqTemporary:
292 : {
293 0 : switch (storageQualifier)
294 : {
295 : case EvqConst:
296 0 : *joinedQualifier = storageQualifier;
297 0 : break;
298 : default:
299 0 : return false;
300 : }
301 0 : break;
302 : }
303 : case EvqSmooth:
304 : {
305 0 : switch (storageQualifier)
306 : {
307 : case EvqCentroid:
308 0 : *joinedQualifier = EvqCentroid;
309 0 : break;
310 : case EvqVertexOut:
311 0 : *joinedQualifier = EvqSmoothOut;
312 0 : break;
313 : case EvqFragmentIn:
314 0 : *joinedQualifier = EvqSmoothIn;
315 0 : break;
316 : default:
317 0 : return false;
318 : }
319 0 : break;
320 : }
321 : case EvqFlat:
322 : {
323 0 : switch (storageQualifier)
324 : {
325 : case EvqCentroid:
326 0 : *joinedQualifier = EvqFlat;
327 0 : break;
328 : case EvqVertexOut:
329 0 : *joinedQualifier = EvqFlatOut;
330 0 : break;
331 : case EvqFragmentIn:
332 0 : *joinedQualifier = EvqFlatIn;
333 0 : break;
334 : default:
335 0 : return false;
336 : }
337 0 : break;
338 : }
339 : case EvqCentroid:
340 : {
341 0 : switch (storageQualifier)
342 : {
343 : case EvqVertexOut:
344 0 : *joinedQualifier = EvqCentroidOut;
345 0 : break;
346 : case EvqFragmentIn:
347 0 : *joinedQualifier = EvqCentroidIn;
348 0 : break;
349 : default:
350 0 : return false;
351 : }
352 0 : break;
353 : }
354 : default:
355 0 : return false;
356 : }
357 0 : return true;
358 : }
359 :
360 : // Handles the joining of storage qualifiers for a parameter in a function.
361 0 : bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
362 : {
363 0 : switch (*joinedQualifier)
364 : {
365 : case EvqTemporary:
366 0 : *joinedQualifier = storageQualifier;
367 0 : break;
368 : case EvqConst:
369 : {
370 0 : switch (storageQualifier)
371 : {
372 : case EvqIn:
373 0 : *joinedQualifier = EvqConstReadOnly;
374 0 : break;
375 : default:
376 0 : return false;
377 : }
378 0 : break;
379 : }
380 : default:
381 0 : return false;
382 : }
383 0 : return true;
384 : }
385 :
386 0 : bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier)
387 : {
388 0 : switch (memoryQualifier)
389 : {
390 : case EvqReadOnly:
391 0 : joinedMemoryQualifier->readonly = true;
392 0 : break;
393 : case EvqWriteOnly:
394 0 : joinedMemoryQualifier->writeonly = true;
395 0 : break;
396 : case EvqCoherent:
397 0 : joinedMemoryQualifier->coherent = true;
398 0 : break;
399 : case EvqRestrict:
400 0 : joinedMemoryQualifier->restrictQualifier = true;
401 0 : break;
402 : case EvqVolatile:
403 : // Variables having the volatile qualifier are automatcally treated as coherent as well.
404 : // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
405 0 : joinedMemoryQualifier->volatileQualifier = true;
406 0 : joinedMemoryQualifier->coherent = true;
407 0 : break;
408 : default:
409 0 : UNREACHABLE();
410 : }
411 0 : return true;
412 : }
413 :
414 0 : TTypeQualifier GetVariableTypeQualifierFromSortedSequence(
415 : const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
416 : TDiagnostics *diagnostics)
417 : {
418 : TTypeQualifier typeQualifier(
419 0 : static_cast<const TStorageQualifierWrapper *>(sortedSequence[0])->getQualifier(),
420 0 : sortedSequence[0]->getLine());
421 0 : for (size_t i = 1; i < sortedSequence.size(); ++i)
422 : {
423 0 : const TQualifierWrapperBase *qualifier = sortedSequence[i];
424 0 : bool isQualifierValid = false;
425 0 : switch (qualifier->getType())
426 : {
427 : case QtInvariant:
428 0 : isQualifierValid = true;
429 0 : typeQualifier.invariant = true;
430 0 : break;
431 : case QtInterpolation:
432 : {
433 0 : switch (typeQualifier.qualifier)
434 : {
435 : case EvqGlobal:
436 0 : isQualifierValid = true;
437 0 : typeQualifier.qualifier =
438 : static_cast<const TInterpolationQualifierWrapper *>(qualifier)
439 0 : ->getQualifier();
440 0 : break;
441 : default:
442 0 : isQualifierValid = false;
443 : }
444 0 : break;
445 : }
446 : case QtLayout:
447 : {
448 : const TLayoutQualifierWrapper *layoutQualifierWrapper =
449 0 : static_cast<const TLayoutQualifierWrapper *>(qualifier);
450 0 : isQualifierValid = true;
451 : typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers(
452 0 : typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(),
453 0 : layoutQualifierWrapper->getLine(), diagnostics);
454 0 : break;
455 : }
456 : case QtStorage:
457 0 : isQualifierValid = JoinVariableStorageQualifier(
458 : &typeQualifier.qualifier,
459 0 : static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
460 0 : break;
461 : case QtPrecision:
462 0 : isQualifierValid = true;
463 0 : typeQualifier.precision =
464 0 : static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
465 0 : ASSERT(typeQualifier.precision != EbpUndefined);
466 0 : break;
467 : case QtMemory:
468 0 : isQualifierValid = JoinMemoryQualifier(
469 : &typeQualifier.memoryQualifier,
470 0 : static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
471 0 : break;
472 : default:
473 0 : UNREACHABLE();
474 : }
475 0 : if (!isQualifierValid)
476 : {
477 0 : const TString &qualifierString = qualifier->getQualifierString();
478 0 : diagnostics->error(qualifier->getLine(), "invalid qualifier combination",
479 0 : qualifierString.c_str(), "");
480 0 : break;
481 : }
482 : }
483 0 : return typeQualifier;
484 : }
485 :
486 0 : TTypeQualifier GetParameterTypeQualifierFromSortedSequence(
487 : const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
488 : TDiagnostics *diagnostics)
489 : {
490 0 : TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine());
491 0 : for (size_t i = 1; i < sortedSequence.size(); ++i)
492 : {
493 0 : const TQualifierWrapperBase *qualifier = sortedSequence[i];
494 0 : bool isQualifierValid = false;
495 0 : switch (qualifier->getType())
496 : {
497 : case QtInvariant:
498 : case QtInterpolation:
499 : case QtLayout:
500 0 : break;
501 : case QtMemory:
502 0 : isQualifierValid = JoinMemoryQualifier(
503 : &typeQualifier.memoryQualifier,
504 0 : static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
505 0 : break;
506 : case QtStorage:
507 0 : isQualifierValid = JoinParameterStorageQualifier(
508 : &typeQualifier.qualifier,
509 0 : static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
510 0 : break;
511 : case QtPrecision:
512 0 : isQualifierValid = true;
513 0 : typeQualifier.precision =
514 0 : static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
515 0 : ASSERT(typeQualifier.precision != EbpUndefined);
516 0 : break;
517 : default:
518 0 : UNREACHABLE();
519 : }
520 0 : if (!isQualifierValid)
521 : {
522 0 : const TString &qualifierString = qualifier->getQualifierString();
523 0 : diagnostics->error(qualifier->getLine(), "invalid parameter qualifier",
524 0 : qualifierString.c_str(), "");
525 0 : break;
526 : }
527 : }
528 :
529 0 : switch (typeQualifier.qualifier)
530 : {
531 : case EvqIn:
532 : case EvqConstReadOnly: // const in
533 : case EvqOut:
534 : case EvqInOut:
535 0 : break;
536 : case EvqConst:
537 0 : typeQualifier.qualifier = EvqConstReadOnly;
538 0 : break;
539 : case EvqTemporary:
540 : // no qualifier has been specified, set it to EvqIn which is the default
541 0 : typeQualifier.qualifier = EvqIn;
542 0 : break;
543 : default:
544 0 : diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ",
545 0 : getQualifierString(typeQualifier.qualifier), "");
546 : }
547 0 : return typeQualifier;
548 : }
549 : } // namespace
550 :
551 0 : TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
552 : TLayoutQualifier rightQualifier,
553 : const TSourceLoc &rightQualifierLocation,
554 : TDiagnostics *diagnostics)
555 : {
556 0 : TLayoutQualifier joinedQualifier = leftQualifier;
557 :
558 0 : if (rightQualifier.location != -1)
559 : {
560 0 : joinedQualifier.location = rightQualifier.location;
561 0 : ++joinedQualifier.locationsSpecified;
562 : }
563 0 : if (rightQualifier.matrixPacking != EmpUnspecified)
564 : {
565 0 : joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
566 : }
567 0 : if (rightQualifier.blockStorage != EbsUnspecified)
568 : {
569 0 : joinedQualifier.blockStorage = rightQualifier.blockStorage;
570 : }
571 :
572 0 : for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
573 : {
574 0 : if (rightQualifier.localSize[i] != -1)
575 : {
576 0 : if (joinedQualifier.localSize[i] != -1 &&
577 0 : joinedQualifier.localSize[i] != rightQualifier.localSize[i])
578 : {
579 0 : diagnostics->error(rightQualifierLocation,
580 : "Cannot have multiple different work group size specifiers",
581 0 : getWorkGroupSizeString(i), "");
582 : }
583 0 : joinedQualifier.localSize[i] = rightQualifier.localSize[i];
584 : }
585 : }
586 :
587 0 : if (rightQualifier.imageInternalFormat != EiifUnspecified)
588 : {
589 0 : joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat;
590 : }
591 :
592 0 : return joinedQualifier;
593 : }
594 :
595 0 : unsigned int TInvariantQualifierWrapper::getRank() const
596 : {
597 0 : return 0u;
598 : }
599 :
600 0 : unsigned int TInterpolationQualifierWrapper::getRank() const
601 : {
602 0 : return 1u;
603 : }
604 :
605 0 : unsigned int TLayoutQualifierWrapper::getRank() const
606 : {
607 0 : return 2u;
608 : }
609 :
610 0 : unsigned int TStorageQualifierWrapper::getRank() const
611 : {
612 : // Force the 'centroid' auxilary storage qualifier to be always first among all storage
613 : // qualifiers.
614 0 : if (mStorageQualifier == EvqCentroid)
615 : {
616 0 : return 3u;
617 : }
618 : else
619 : {
620 0 : return 4u;
621 : }
622 : }
623 :
624 0 : unsigned int TMemoryQualifierWrapper::getRank() const
625 : {
626 0 : return 4u;
627 : }
628 :
629 0 : unsigned int TPrecisionQualifierWrapper::getRank() const
630 : {
631 0 : return 5u;
632 : }
633 :
634 0 : TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
635 : : layoutQualifier(TLayoutQualifier::create()),
636 : memoryQualifier(TMemoryQualifier::create()),
637 : precision(EbpUndefined),
638 : qualifier(scope),
639 : invariant(false),
640 0 : line(loc)
641 : {
642 0 : ASSERT(IsScopeQualifier(qualifier));
643 0 : }
644 :
645 0 : TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope,
646 0 : int shaderVersion)
647 0 : : mShaderVersion(shaderVersion)
648 : {
649 0 : ASSERT(IsScopeQualifier(scope->getQualifier()));
650 0 : mQualifiers.push_back(scope);
651 0 : }
652 :
653 0 : void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier)
654 : {
655 0 : mQualifiers.push_back(qualifier);
656 0 : }
657 :
658 0 : bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const
659 : {
660 0 : bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion);
661 0 : std::string errorMessage;
662 0 : if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage))
663 : {
664 0 : diagnostics->error(mQualifiers[0]->getLine(), "qualifier sequence", errorMessage.c_str(),
665 0 : "");
666 0 : return false;
667 : }
668 :
669 0 : if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage))
670 : {
671 0 : diagnostics->error(mQualifiers[0]->getLine(), "qualifier sequence", errorMessage.c_str(),
672 0 : "");
673 0 : return false;
674 : }
675 :
676 0 : return true;
677 : }
678 :
679 0 : TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const
680 : {
681 0 : ASSERT(IsInvariantCorrect(mQualifiers));
682 0 : ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() ==
683 0 : EvqTemporary);
684 :
685 0 : if (!checkSequenceIsValid(diagnostics))
686 : {
687 0 : return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine());
688 : }
689 :
690 : // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
691 : // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
692 : // combine the qualifiers.
693 0 : if (AreTypeQualifierChecksRelaxed(mShaderVersion))
694 : {
695 : // Copy the qualifier sequence so that we can sort them.
696 0 : QualifierSequence sortedQualifierSequence = mQualifiers;
697 0 : SortSequence(sortedQualifierSequence);
698 0 : return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
699 : }
700 0 : return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
701 : }
702 :
703 0 : TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const
704 : {
705 0 : ASSERT(IsInvariantCorrect(mQualifiers));
706 :
707 0 : if (!checkSequenceIsValid(diagnostics))
708 : {
709 : return TTypeQualifier(
710 0 : static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(),
711 0 : mQualifiers[0]->getLine());
712 : }
713 :
714 : // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
715 : // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
716 : // combine the qualifiers.
717 0 : if (AreTypeQualifierChecksRelaxed(mShaderVersion))
718 : {
719 : // Copy the qualifier sequence so that we can sort them.
720 0 : QualifierSequence sortedQualifierSequence = mQualifiers;
721 0 : SortSequence(sortedQualifierSequence);
722 0 : return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
723 : }
724 0 : return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
725 : }
726 :
727 : } // namespace sh
|