• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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/TranslatorMetalDirect/Pipeline.h"
8 #include "compiler/translator/tree_util/BuiltIn.h"
9 
10 using namespace sh;
11 
12 ////////////////////////////////////////////////////////////////////////////////
13 
14 #define VARIANT_NAME(variant, base) (variant == Variant::Modified ? base "Mod" : base)
15 
uses(const TVariable & var) const16 bool Pipeline::uses(const TVariable &var) const
17 {
18     if (var.symbolType() == SymbolType::Empty)
19     {
20         return false;
21     }
22 
23     if (globalInstanceVar)
24     {
25         return &var == globalInstanceVar;
26     }
27 
28     const TType &nodeType      = var.getType();
29     const TQualifier qualifier = nodeType.getQualifier();
30 
31     switch (type)
32     {
33         case Type::VertexIn:
34             switch (qualifier)
35             {
36                 case TQualifier::EvqAttribute:
37                 case TQualifier::EvqVertexIn:
38                     return true;
39                 default:
40                     return false;
41             }
42 
43         case Type::VertexOut:
44             switch (qualifier)
45             {
46                 case TQualifier::EvqVertexOut:
47                 case TQualifier::EvqPosition:
48                 case TQualifier::EvqFlatOut:
49                 case TQualifier::EvqPointSize:
50                 case TQualifier::EvqSmoothOut:
51                 case TQualifier::EvqCentroidOut:
52                 case TQualifier::EvqNoPerspectiveOut:
53                 case TQualifier::EvqVaryingOut:
54                     return true;
55                 default:
56                     return false;
57             }
58 
59         case Type::FragmentIn:
60             switch (qualifier)
61             {
62                 case TQualifier::EvqFragmentIn:
63                 case TQualifier::EvqFlatIn:
64                 case TQualifier::EvqSmoothIn:
65                 case TQualifier::EvqCentroidIn:
66                 case TQualifier::EvqNoPerspectiveIn:
67                 case TQualifier::EvqVaryingIn:
68                     return true;
69                 default:
70                     return false;
71             }
72 
73         case Type::FragmentOut:
74             switch (qualifier)
75             {
76                 case TQualifier::EvqFragmentOut:
77                 case TQualifier::EvqFragColor:
78                 case TQualifier::EvqFragData:
79                 case TQualifier::EvqFragDepth:
80                 case TQualifier::EvqSampleMask:
81                     return true;
82                 default:
83                     return false;
84             }
85 
86         case Type::UserUniforms:
87             switch (qualifier)
88             {
89                 case TQualifier::EvqUniform:
90                     return true;
91                 default:
92                     return false;
93             }
94 
95         case Type::NonConstantGlobals:
96             switch (qualifier)
97             {
98                 case TQualifier::EvqGlobal:
99                     return true;
100                 default:
101                     return false;
102             }
103 
104         case Type::InvocationVertexGlobals:
105             switch (qualifier)
106             {
107                 case TQualifier::EvqVertexID:
108                     return true;
109                 default:
110                     return false;
111             }
112 
113         case Type::InvocationFragmentGlobals:
114             switch (qualifier)
115             {
116                 case TQualifier::EvqFragCoord:
117                 case TQualifier::EvqPointCoord:
118                 case TQualifier::EvqFrontFacing:
119                     return true;
120                 default:
121                     return false;
122             }
123 
124         case Type::UniformBuffer:
125             switch (qualifier)
126             {
127                 case TQualifier::EvqBuffer:
128                     return true;
129                 default:
130                     return false;
131             }
132         case Type::AngleUniforms:
133             UNREACHABLE();  // globalInstanceVar should be non-null and thus never reach here.
134             return false;
135 
136         case Type::Texture:
137             return IsSampler(nodeType.getBasicType());
138 
139         case Type::InstanceId:
140             return Name(var) == Name(*BuiltInVariable::gl_InstanceID());
141     }
142 }
143 
getStructTypeName(Variant variant) const144 Name Pipeline::getStructTypeName(Variant variant) const
145 {
146     const char *name;
147     switch (type)
148     {
149         case Type::VertexIn:
150             name = VARIANT_NAME(variant, "VertexIn");
151             break;
152         case Type::VertexOut:
153             name = VARIANT_NAME(variant, "VertexOut");
154             break;
155         case Type::FragmentIn:
156             name = VARIANT_NAME(variant, "FragmentIn");
157             break;
158         case Type::FragmentOut:
159             name = VARIANT_NAME(variant, "FragmentOut");
160             break;
161         case Type::UserUniforms:
162             name = VARIANT_NAME(variant, "UserUniforms");
163             break;
164         case Type::AngleUniforms:
165             name = VARIANT_NAME(variant, "AngleUniforms");
166             break;
167         case Type::NonConstantGlobals:
168             name = VARIANT_NAME(variant, "NonConstGlobals");
169             break;
170         case Type::InvocationVertexGlobals:
171             name = VARIANT_NAME(variant, "InvocationVertexGlobals");
172             break;
173         case Type::InvocationFragmentGlobals:
174             name = VARIANT_NAME(variant, "InvocationFragmentGlobals");
175             break;
176         case Type::Texture:
177             name = VARIANT_NAME(variant, "TextureEnvs");
178             break;
179         case Type::InstanceId:
180             name = VARIANT_NAME(variant, "InstanceId");
181             break;
182         case Type::UniformBuffer:
183             name = VARIANT_NAME(variant, "UniformBuffer");
184     }
185     return Name(name);
186 }
187 
getStructInstanceName(Variant variant) const188 Name Pipeline::getStructInstanceName(Variant variant) const
189 {
190     const char *name;
191     switch (type)
192     {
193         case Type::VertexIn:
194             name = VARIANT_NAME(variant, "vertexIn");
195             break;
196         case Type::VertexOut:
197             name = VARIANT_NAME(variant, "vertexOut");
198             break;
199         case Type::FragmentIn:
200             name = VARIANT_NAME(variant, "fragmentIn");
201             break;
202         case Type::FragmentOut:
203             name = VARIANT_NAME(variant, "fragmentOut");
204             break;
205         case Type::UserUniforms:
206             name = VARIANT_NAME(variant, "userUniforms");
207             break;
208         case Type::AngleUniforms:
209             name = VARIANT_NAME(variant, "angleUniforms");
210             break;
211         case Type::NonConstantGlobals:
212             name = VARIANT_NAME(variant, "nonConstGlobals");
213             break;
214         case Type::InvocationVertexGlobals:
215             name = VARIANT_NAME(variant, "invocationVertexGlobals");
216             break;
217         case Type::InvocationFragmentGlobals:
218             name = VARIANT_NAME(variant, "invocationFragmentGlobals");
219             break;
220         case Type::Texture:
221             name = VARIANT_NAME(variant, "textureEnvs");
222             break;
223         case Type::InstanceId:
224             name = VARIANT_NAME(variant, "instanceId");
225             break;
226         case Type::UniformBuffer:
227             name = VARIANT_NAME(variant, "uniformBuffer");
228     }
229     return Name(name);
230 }
231 
AllowPacking(Pipeline::Type type)232 static bool AllowPacking(Pipeline::Type type)
233 {
234     using Type = Pipeline::Type;
235 
236     switch (type)
237     {
238         case Type::UniformBuffer:
239         case Type::UserUniforms:
240             return true;
241 
242         case Type::VertexIn:
243         case Type::VertexOut:
244         case Type::FragmentIn:
245         case Type::FragmentOut:
246         case Type::AngleUniforms:
247         case Type::NonConstantGlobals:
248         case Type::InvocationVertexGlobals:
249         case Type::InvocationFragmentGlobals:
250         case Type::Texture:
251         case Type::InstanceId:
252             return false;
253     }
254 }
255 
AllowPadding(Pipeline::Type type)256 static bool AllowPadding(Pipeline::Type type)
257 {
258     using Type = Pipeline::Type;
259 
260     switch (type)
261     {
262         case Type::UserUniforms:
263         case Type::VertexIn:
264         case Type::VertexOut:
265         case Type::FragmentIn:
266         case Type::FragmentOut:
267         case Type::AngleUniforms:
268         case Type::NonConstantGlobals:
269         case Type::InvocationVertexGlobals:
270         case Type::InvocationFragmentGlobals:
271         case Type::UniformBuffer:
272             return true;
273 
274         case Type::Texture:
275         case Type::InstanceId:
276             return false;
277     }
278 }
279 enum Compare
280 {
281     LT,
282     LTE,
283     EQ,
284     GTE,
285     GT,
286 };
287 
288 template <typename T>
CompareBy(Compare op,const T & x,const T & y)289 static bool CompareBy(Compare op, const T &x, const T &y)
290 {
291     switch (op)
292     {
293         case LT:
294             return x < y;
295         case LTE:
296             return x <= y;
297         case EQ:
298             return x == y;
299         case GTE:
300             return x >= y;
301         case GT:
302             return x > y;
303     }
304 }
305 
306 template <TBasicType BT, Compare Cmp, int MatchDim, int NewDim>
SaturateVectorOf(const TField & field)307 static int SaturateVectorOf(const TField &field)
308 {
309     static_assert(NewDim >= MatchDim, "");
310 
311     const TType &type = *field.type();
312     ASSERT(type.isScalar() || type.isVector());
313 
314     const bool cond = type.getBasicType() == BT && !type.isArray() &&
315                       CompareBy(Cmp, type.getNominalSize(), MatchDim) &&
316                       type.getQualifier() != TQualifier::EvqFragDepth;
317 
318     if (cond)
319     {
320         return NewDim;
321     }
322     return 0;
323 }
324 
externalStructModifyConfig() const325 ModifyStructConfig Pipeline::externalStructModifyConfig() const
326 {
327     using Pred   = ModifyStructConfig::Predicate;
328     using SatVec = ModifyStructConfig::SaturateVector;
329 
330     ModifyStructConfig config(
331         isPipelineOut() ? ConvertType::OriginalToModified : ConvertType::ModifiedToOriginal,
332         AllowPacking(type), AllowPadding(type));
333 
334     config.externalAddressSpace = externalAddressSpace();
335 
336     switch (type)
337     {
338         case Type::VertexIn:
339             config.inlineArray        = Pred::True;
340             config.splitMatrixColumns = Pred::True;
341             config.inlineStruct       = Pred::True;
342             break;
343 
344         case Type::VertexOut:
345             config.inlineArray        = Pred::True;
346             config.splitMatrixColumns = Pred::True;
347             config.inlineStruct       = Pred::True;
348             break;
349 
350         case Type::FragmentIn:
351             config.inlineArray        = Pred::True;
352             config.splitMatrixColumns = Pred::True;
353             config.inlineStruct       = Pred::True;
354             break;
355 
356         case Type::FragmentOut:
357             config.inlineArray            = Pred::True;
358             config.splitMatrixColumns     = Pred::True;
359             config.inlineStruct           = Pred::True;
360             config.saturateScalarOrVector = [](const TField &field) {
361                 if (field.type()->getQualifier() == TQualifier::EvqSampleMask)
362                 {
363                     return 1;
364                 }
365                 if (int s = SaturateVectorOf<TBasicType::EbtInt, LT, 4, 4>(field))
366                 {
367                     return s;
368                 }
369                 if (int s = SaturateVectorOf<TBasicType::EbtUInt, LT, 4, 4>(field))
370                 {
371                     return s;
372                 }
373                 if (int s = SaturateVectorOf<TBasicType::EbtFloat, LT, 4, 4>(field))
374                 {
375                     return s;
376                 }
377                 return 0;
378             };
379             break;
380         case Type::UserUniforms:
381             config.promoteBoolToUint            = Pred::True;
382             config.saturateMatrixRows           = SatVec::FullySaturate;
383             config.saturateScalarOrVectorArrays = SatVec::FullySaturate;
384             config.recurseStruct                = Pred::True;
385             break;
386 
387         case Type::AngleUniforms:
388             config.initialBlockStorage = TLayoutBlockStorage::EbsStd430;  // XXX: Correct?
389             break;
390 
391         case Type::NonConstantGlobals:
392             break;
393         case Type::UniformBuffer:
394             config.promoteBoolToUint            = Pred::True;
395             config.saturateMatrixRows           = SatVec::FullySaturate;
396             config.saturateScalarOrVectorArrays = SatVec::FullySaturate;
397             config.recurseStruct                = Pred::True;
398             break;
399         case Type::InvocationVertexGlobals:
400         case Type::InvocationFragmentGlobals:
401         case Type::Texture:
402         case Type::InstanceId:
403             break;
404     }
405 
406     return config;
407 }
408 
alwaysRequiresLocalVariableDeclarationInMain() const409 bool Pipeline::alwaysRequiresLocalVariableDeclarationInMain() const
410 {
411     switch (type)
412     {
413         case Type::VertexIn:
414         case Type::FragmentIn:
415         case Type::UserUniforms:
416         case Type::AngleUniforms:
417         case Type::UniformBuffer:
418             return false;
419 
420         case Type::VertexOut:
421         case Type::FragmentOut:
422         case Type::NonConstantGlobals:
423         case Type::InvocationVertexGlobals:
424         case Type::InvocationFragmentGlobals:
425         case Type::Texture:
426         case Type::InstanceId:
427             return true;
428     }
429 }
430 
isPipelineOut() const431 bool Pipeline::isPipelineOut() const
432 {
433     switch (type)
434     {
435         case Type::VertexIn:
436         case Type::FragmentIn:
437         case Type::UserUniforms:
438         case Type::AngleUniforms:
439         case Type::NonConstantGlobals:
440         case Type::InvocationVertexGlobals:
441         case Type::InvocationFragmentGlobals:
442         case Type::Texture:
443         case Type::InstanceId:
444         case Type::UniformBuffer:
445             return false;
446 
447         case Type::VertexOut:
448         case Type::FragmentOut:
449             return true;
450     }
451 }
452 
externalAddressSpace() const453 AddressSpace Pipeline::externalAddressSpace() const
454 {
455     switch (type)
456     {
457         case Type::VertexIn:
458         case Type::FragmentIn:
459         case Type::NonConstantGlobals:
460         case Type::InvocationVertexGlobals:
461         case Type::InvocationFragmentGlobals:
462         case Type::Texture:
463         case Type::InstanceId:
464         case Type::FragmentOut:
465         case Type::VertexOut:
466             return AddressSpace::Thread;
467 
468         case Type::UserUniforms:
469         case Type::AngleUniforms:
470         case Type::UniformBuffer:
471             return AddressSpace::Constant;
472     }
473 }
474 
matches(const TStructure & s,bool internal,bool external) const475 bool PipelineStructs::matches(const TStructure &s, bool internal, bool external) const
476 {
477     PipelineScoped<TStructure> ps[] = {
478         fragmentIn,
479         fragmentOut,
480         vertexIn,
481         vertexOut,
482         userUniforms,
483         /* angleUniforms, */
484         nonConstantGlobals,
485         invocationVertexGlobals,
486         invocationFragmentGlobals,
487         uniformBuffers,
488         texture,
489         instanceId,
490     };
491     for (const auto &p : ps)
492     {
493         if (internal && p.internal == &s)
494         {
495             return true;
496         }
497         if (external && p.external == &s)
498         {
499             return true;
500         }
501     }
502     return false;
503 }
504