• 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 // DriverUniform.cpp: Add code to support driver uniforms
7 //
8 
9 #include "compiler/translator/tree_util/DriverUniform.h"
10 
11 #include "compiler/translator/Compiler.h"
12 #include "compiler/translator/IntermNode.h"
13 #include "compiler/translator/StaticType.h"
14 #include "compiler/translator/SymbolTable.h"
15 #include "compiler/translator/tree_util/FindMain.h"
16 #include "compiler/translator/tree_util/IntermNode_util.h"
17 #include "compiler/translator/tree_util/IntermTraverse.h"
18 #include "compiler/translator/util.h"
19 
20 namespace sh
21 {
22 
23 namespace
24 {
25 constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams");
26 constexpr ImmutableString kDriverUniformsBlockName  = ImmutableString("ANGLEUniformBlock");
27 constexpr ImmutableString kDriverUniformsVarName    = ImmutableString("ANGLEUniforms");
28 
29 constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets";
30 constexpr const char kDepthRange[]       = "depthRange";
31 constexpr const char kRenderArea[]       = "renderArea";
32 constexpr const char kFlipXY[]           = "flipXY";
33 constexpr const char kDither[]           = "dither";
34 constexpr const char kMisc[]             = "misc";
35 
36 // Extended uniforms
37 constexpr const char kXfbBufferOffsets[]       = "xfbBufferOffsets";
38 constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance";
39 constexpr const char kUnused[]                 = "unused";
40 constexpr const char kUnused2[]                = "unused2";
41 }  // anonymous namespace
42 
43 // Class DriverUniform
addComputeDriverUniformsToShader(TIntermBlock * root,TSymbolTable * symbolTable)44 bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
45 {
46     constexpr size_t kNumComputeDriverUniforms                                               = 1;
47     constexpr std::array<const char *, kNumComputeDriverUniforms> kComputeDriverUniformNames = {
48         {kAcbBufferOffsets}};
49 
50     ASSERT(!mDriverUniforms);
51     // This field list mirrors the structure of ComputeDriverUniforms in ContextVk.cpp.
52     TFieldList *driverFieldList = new TFieldList;
53 
54     const std::array<TType *, kNumComputeDriverUniforms> kDriverUniformTypes = {{
55         new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
56     }};
57 
58     for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex)
59     {
60         TField *driverUniformField =
61             new TField(kDriverUniformTypes[uniformIndex],
62                        ImmutableString(kComputeDriverUniformNames[uniformIndex]), TSourceLoc(),
63                        SymbolType::AngleInternal);
64         driverFieldList->push_back(driverUniformField);
65     }
66 
67     // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
68     TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
69     layoutQualifier.blockStorage     = EbsStd140;
70     layoutQualifier.pushConstant     = true;
71 
72     mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
73                                             layoutQualifier, TMemoryQualifier::Create(), 0,
74                                             kDriverUniformsBlockName, kDriverUniformsVarName);
75     return mDriverUniforms != nullptr;
76 }
77 
createUniformFields(TSymbolTable * symbolTable)78 TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable)
79 {
80     constexpr size_t kNumGraphicsDriverUniforms                                                = 6;
81     constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {{
82         kAcbBufferOffsets,
83         kDepthRange,
84         kRenderArea,
85         kFlipXY,
86         kDither,
87         kMisc,
88     }};
89 
90     // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp.
91     TFieldList *driverFieldList = new TFieldList;
92 
93     const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
94         // acbBufferOffsets: Packed ubyte8
95         new TType(EbtUInt, EbpHigh, EvqGlobal, 2),
96         // depthRange: Near and far depth
97         new TType(EbtFloat, EbpHigh, EvqGlobal, 2),
98         // renderArea: Packed ushort2
99         new TType(EbtUInt, EbpHigh, EvqGlobal),
100         // flipXY: Packed snorm4
101         new TType(EbtUInt, EbpHigh, EvqGlobal),
102         // dither: ushort
103         new TType(EbtUInt, EbpHigh, EvqGlobal),
104         // misc: Various bits of state
105         new TType(EbtUInt, EbpHigh, EvqGlobal),
106     }};
107 
108     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex)
109     {
110         TField *driverUniformField =
111             new TField(kDriverUniformTypes[uniformIndex],
112                        ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(),
113                        SymbolType::AngleInternal);
114         driverFieldList->push_back(driverUniformField);
115     }
116 
117     return driverFieldList;
118 }
119 
createEmulatedDepthRangeType(TSymbolTable * symbolTable)120 const TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable)
121 {
122     // If already defined, return it immediately.
123     if (mEmulatedDepthRangeType != nullptr)
124     {
125         return mEmulatedDepthRangeType;
126     }
127 
128     // Create the depth range type.
129     TFieldList *depthRangeParamsFields = new TFieldList();
130     TType *floatType                   = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1);
131     depthRangeParamsFields->push_back(
132         new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal));
133     depthRangeParamsFields->push_back(
134         new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal));
135     depthRangeParamsFields->push_back(
136         new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal));
137 
138     TStructure *emulatedDepthRangeParams = new TStructure(
139         symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
140 
141     mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false);
142 
143     return mEmulatedDepthRangeType;
144 }
145 
146 // The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver
147 // block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms
148 // variable.
149 //
150 // There are Graphics and Compute variations as they require different uniforms.
addGraphicsDriverUniformsToShader(TIntermBlock * root,TSymbolTable * symbolTable)151 bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
152 {
153     ASSERT(!mDriverUniforms);
154 
155     // Declare the depth range struct type.
156     const TType *emulatedDepthRangeType     = createEmulatedDepthRangeType(symbolTable);
157     const TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true);
158 
159     const TVariable *depthRangeVar =
160         new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty,
161                       TExtension::UNDEFINED, emulatedDepthRangeDeclType);
162 
163     DeclareGlobalVariable(root, depthRangeVar);
164 
165     TFieldList *driverFieldList = createUniformFields(symbolTable);
166     if (mMode == DriverUniformMode::InterfaceBlock)
167     {
168         // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
169         TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
170         layoutQualifier.blockStorage     = EbsStd140;
171         layoutQualifier.pushConstant     = true;
172 
173         mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
174                                                 layoutQualifier, TMemoryQualifier::Create(), 0,
175                                                 kDriverUniformsBlockName, kDriverUniformsVarName);
176     }
177     else
178     {
179         // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms".
180         // This code path is taken only by the direct-to-Metal backend, and the assumptions
181         // about the naming conventions of ANGLE-internal variables run too deeply to rename
182         // this one.
183         auto varName = ImmutableString("ANGLE_angleUniforms");
184         auto result =
185             DeclareStructure(root, symbolTable, driverFieldList, EvqUniform,
186                              TMemoryQualifier::Create(), 0, kDriverUniformsBlockName, &varName);
187         mDriverUniforms = result.second;
188     }
189 
190     return mDriverUniforms != nullptr;
191 }
192 
createDriverUniformRef(const char * fieldName) const193 TIntermTyped *DriverUniform::createDriverUniformRef(const char *fieldName) const
194 {
195     size_t fieldIndex = 0;
196     if (mMode == DriverUniformMode::InterfaceBlock)
197     {
198         fieldIndex =
199             FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName);
200     }
201     else
202     {
203         fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName);
204     }
205 
206     TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms);
207     TConstantUnion *uniformIndex    = new TConstantUnion;
208     uniformIndex->setIConst(static_cast<int>(fieldIndex));
209     TIntermConstantUnion *indexRef =
210         new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt, EbpLow>());
211     if (mMode == DriverUniformMode::InterfaceBlock)
212     {
213         return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
214     }
215     return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef);
216 }
217 
getAcbBufferOffsets() const218 TIntermTyped *DriverUniform::getAcbBufferOffsets() const
219 {
220     return createDriverUniformRef(kAcbBufferOffsets);
221 }
222 
getDepthRange() const223 TIntermTyped *DriverUniform::getDepthRange() const
224 {
225     ASSERT(mEmulatedDepthRangeType != nullptr);
226 
227     TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange);
228     TIntermTyped *nearRef       = new TIntermSwizzle(depthRangeRef, {0});
229     TIntermTyped *farRef        = new TIntermSwizzle(depthRangeRef->deepCopy(), {1});
230     TIntermTyped *diff          = new TIntermBinary(EOpSub, farRef, nearRef);
231 
232     TIntermSequence args = {
233         nearRef->deepCopy(),
234         farRef->deepCopy(),
235         diff,
236     };
237 
238     return TIntermAggregate::CreateConstructor(*mEmulatedDepthRangeType, &args);
239 }
240 
getViewportZScale() const241 TIntermTyped *DriverUniform::getViewportZScale() const
242 {
243     ASSERT(mEmulatedDepthRangeType != nullptr);
244 
245     TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange);
246     TIntermTyped *nearRef       = new TIntermSwizzle(depthRangeRef, {0});
247     TIntermTyped *farRef        = new TIntermSwizzle(depthRangeRef->deepCopy(), {1});
248 
249     TIntermTyped *isNegative = new TIntermBinary(EOpLessThan, farRef, nearRef);
250 
251     return new TIntermTernary(isNegative, CreateFloatNode(-1, EbpMedium),
252                               CreateFloatNode(1, EbpMedium));
253 }
254 
getHalfRenderArea() const255 TIntermTyped *DriverUniform::getHalfRenderArea() const
256 {
257     TIntermTyped *renderAreaRef = createDriverUniformRef(kRenderArea);
258     TIntermTyped *width = new TIntermBinary(EOpBitwiseAnd, renderAreaRef, CreateUIntNode(0xFFFF));
259     TIntermTyped *height =
260         new TIntermBinary(EOpBitShiftRight, renderAreaRef->deepCopy(), CreateUIntNode(16));
261 
262     TIntermSequence widthArgs = {
263         width,
264     };
265     TIntermTyped *widthAsFloat =
266         TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpHigh>(), &widthArgs);
267 
268     TIntermSequence heightArgs = {
269         height,
270     };
271     TIntermTyped *heightAsFloat = TIntermAggregate::CreateConstructor(
272         *StaticType::GetBasic<EbtFloat, EbpHigh>(), &heightArgs);
273 
274     TIntermSequence args = {
275         widthAsFloat,
276         heightAsFloat,
277     };
278 
279     TIntermTyped *renderArea =
280         TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpHigh, 2>(), &args);
281     return new TIntermBinary(EOpVectorTimesScalar, renderArea, CreateFloatNode(0.5, EbpMedium));
282 }
283 
getFlipXY(TSymbolTable * symbolTable,DriverUniformFlip stage) const284 TIntermTyped *DriverUniform::getFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const
285 {
286     TIntermTyped *flipXY = createDriverUniformRef(kFlipXY);
287     TIntermTyped *values = CreateBuiltInUnaryFunctionCallNode(
288         "unpackSnorm4x8", flipXY, *symbolTable,
289         GetESSLOrGLSLVersion(symbolTable->getShaderSpec(), 310, 400));
290 
291     if (stage == DriverUniformFlip::Fragment)
292     {
293         return new TIntermSwizzle(values, {0, 1});
294     }
295 
296     return new TIntermSwizzle(values, {2, 3});
297 }
298 
getNegFlipXY(TSymbolTable * symbolTable,DriverUniformFlip stage) const299 TIntermTyped *DriverUniform::getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const
300 {
301     TIntermTyped *flipXY = getFlipXY(symbolTable, stage);
302 
303     constexpr std::array<float, 2> kMultiplier = {1, -1};
304     return new TIntermBinary(EOpMul, flipXY, CreateVecNode(kMultiplier.data(), 2, EbpLow));
305 }
306 
getDither() const307 TIntermTyped *DriverUniform::getDither() const
308 {
309     return createDriverUniformRef(kDither);
310 }
311 
getSwapXY() const312 TIntermTyped *DriverUniform::getSwapXY() const
313 {
314     TIntermTyped *miscRef = createDriverUniformRef(kMisc);
315     TIntermTyped *swapXY  = new TIntermBinary(EOpBitwiseAnd, miscRef,
316                                               CreateUIntNode(vk::kDriverUniformsMiscSwapXYMask));
317 
318     TIntermSequence args = {
319         swapXY,
320     };
321     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
322                                                &args);
323 }
324 
getAdvancedBlendEquation() const325 TIntermTyped *DriverUniform::getAdvancedBlendEquation() const
326 {
327     TIntermTyped *miscRef = createDriverUniformRef(kMisc);
328     TIntermTyped *equation =
329         new TIntermBinary(EOpBitShiftRight, miscRef,
330                           CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationOffset));
331     equation = new TIntermBinary(EOpBitwiseAnd, equation,
332                                  CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationMask));
333 
334     return equation;
335 }
336 
getNumSamples() const337 TIntermTyped *DriverUniform::getNumSamples() const
338 {
339     TIntermTyped *miscRef     = createDriverUniformRef(kMisc);
340     TIntermTyped *sampleCount = new TIntermBinary(
341         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscSampleCountOffset));
342     sampleCount = new TIntermBinary(EOpBitwiseAnd, sampleCount,
343                                     CreateUIntNode(vk::kDriverUniformsMiscSampleCountMask));
344 
345     return sampleCount;
346 }
347 
getClipDistancesEnabled() const348 TIntermTyped *DriverUniform::getClipDistancesEnabled() const
349 {
350     TIntermTyped *miscRef     = createDriverUniformRef(kMisc);
351     TIntermTyped *enabledMask = new TIntermBinary(
352         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesOffset));
353     enabledMask = new TIntermBinary(EOpBitwiseAnd, enabledMask,
354                                     CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesMask));
355 
356     return enabledMask;
357 }
358 
getTransformDepth() const359 TIntermTyped *DriverUniform::getTransformDepth() const
360 {
361     TIntermTyped *miscRef        = createDriverUniformRef(kMisc);
362     TIntermTyped *transformDepth = new TIntermBinary(
363         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscTransformDepthOffset));
364     transformDepth = new TIntermBinary(EOpBitwiseAnd, transformDepth,
365                                        CreateUIntNode(vk::kDriverUniformsMiscTransformDepthMask));
366 
367     TIntermSequence args = {
368         transformDepth,
369     };
370     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
371                                                &args);
372 }
373 
getAlphaToCoverage() const374 TIntermTyped *DriverUniform::getAlphaToCoverage() const
375 {
376     TIntermTyped *miscRef         = createDriverUniformRef(kMisc);
377     TIntermTyped *alphaToCoverage = new TIntermBinary(
378         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscAlphaToCoverageOffset));
379     alphaToCoverage = new TIntermBinary(EOpBitwiseAnd, alphaToCoverage,
380                                         CreateUIntNode(vk::kDriverUniformsMiscAlphaToCoverageMask));
381 
382     TIntermSequence args = {
383         alphaToCoverage,
384     };
385     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
386                                                &args);
387 }
388 
389 //
390 // Class DriverUniformExtended
391 //
createUniformFields(TSymbolTable * symbolTable)392 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable)
393 {
394     TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
395 
396     constexpr size_t kNumGraphicsDriverUniformsExt = 4;
397     constexpr std::array<const char *, kNumGraphicsDriverUniformsExt>
398         kGraphicsDriverUniformNamesExt = {
399             {kXfbBufferOffsets, kXfbVerticesPerInstance, kUnused, kUnused2}};
400 
401     const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
402         // xfbBufferOffsets: uvec4
403         new TType(EbtInt, EbpHigh, EvqGlobal, 4),
404         // xfbVerticesPerInstance: uint
405         new TType(EbtInt, EbpHigh, EvqGlobal),
406         // unused: uvec3
407         new TType(EbtUInt, EbpHigh, EvqGlobal),
408         new TType(EbtUInt, EbpHigh, EvqGlobal, 2),
409     }};
410 
411     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
412     {
413         TField *driverUniformField =
414             new TField(kDriverUniformTypesExt[uniformIndex],
415                        ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(),
416                        SymbolType::AngleInternal);
417         driverFieldList->push_back(driverUniformField);
418     }
419 
420     return driverFieldList;
421 }
422 
getXfbBufferOffsets() const423 TIntermTyped *DriverUniformExtended::getXfbBufferOffsets() const
424 {
425     return createDriverUniformRef(kXfbBufferOffsets);
426 }
427 
getXfbVerticesPerInstance() const428 TIntermTyped *DriverUniformExtended::getXfbVerticesPerInstance() const
429 {
430     return createDriverUniformRef(kXfbVerticesPerInstance);
431 }
432 
MakeSwapXMultiplier(TIntermTyped * swapped)433 TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped)
434 {
435     // float(!swapped)
436     TIntermSequence args = {
437         new TIntermUnary(EOpLogicalNot, swapped, nullptr),
438     };
439     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args);
440 }
441 
MakeSwapYMultiplier(TIntermTyped * swapped)442 TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped)
443 {
444     // float(swapped)
445     TIntermSequence args = {
446         swapped,
447     };
448     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args);
449 }
450 }  // namespace sh
451