xref: /aosp_15_r20/external/angle/src/compiler/translator/tree_util/DriverUniform.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 =
288         CreateBuiltInUnaryFunctionCallNode("unpackSnorm4x8", flipXY, *symbolTable, 310);
289 
290     if (stage == DriverUniformFlip::Fragment)
291     {
292         return new TIntermSwizzle(values, {0, 1});
293     }
294 
295     return new TIntermSwizzle(values, {2, 3});
296 }
297 
getNegFlipXY(TSymbolTable * symbolTable,DriverUniformFlip stage) const298 TIntermTyped *DriverUniform::getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const
299 {
300     TIntermTyped *flipXY = getFlipXY(symbolTable, stage);
301 
302     constexpr std::array<float, 2> kMultiplier = {1, -1};
303     return new TIntermBinary(EOpMul, flipXY, CreateVecNode(kMultiplier.data(), 2, EbpLow));
304 }
305 
getDither() const306 TIntermTyped *DriverUniform::getDither() const
307 {
308     return createDriverUniformRef(kDither);
309 }
310 
getSwapXY() const311 TIntermTyped *DriverUniform::getSwapXY() const
312 {
313     TIntermTyped *miscRef = createDriverUniformRef(kMisc);
314     TIntermTyped *swapXY  = new TIntermBinary(EOpBitwiseAnd, miscRef,
315                                               CreateUIntNode(vk::kDriverUniformsMiscSwapXYMask));
316 
317     TIntermSequence args = {
318         swapXY,
319     };
320     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
321                                                &args);
322 }
323 
getAdvancedBlendEquation() const324 TIntermTyped *DriverUniform::getAdvancedBlendEquation() const
325 {
326     TIntermTyped *miscRef = createDriverUniformRef(kMisc);
327     TIntermTyped *equation =
328         new TIntermBinary(EOpBitShiftRight, miscRef,
329                           CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationOffset));
330     equation = new TIntermBinary(EOpBitwiseAnd, equation,
331                                  CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationMask));
332 
333     return equation;
334 }
335 
getNumSamples() const336 TIntermTyped *DriverUniform::getNumSamples() const
337 {
338     TIntermTyped *miscRef     = createDriverUniformRef(kMisc);
339     TIntermTyped *sampleCount = new TIntermBinary(
340         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscSampleCountOffset));
341     sampleCount = new TIntermBinary(EOpBitwiseAnd, sampleCount,
342                                     CreateUIntNode(vk::kDriverUniformsMiscSampleCountMask));
343 
344     return sampleCount;
345 }
346 
getClipDistancesEnabled() const347 TIntermTyped *DriverUniform::getClipDistancesEnabled() const
348 {
349     TIntermTyped *miscRef     = createDriverUniformRef(kMisc);
350     TIntermTyped *enabledMask = new TIntermBinary(
351         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesOffset));
352     enabledMask = new TIntermBinary(EOpBitwiseAnd, enabledMask,
353                                     CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesMask));
354 
355     return enabledMask;
356 }
357 
getTransformDepth() const358 TIntermTyped *DriverUniform::getTransformDepth() const
359 {
360     TIntermTyped *miscRef        = createDriverUniformRef(kMisc);
361     TIntermTyped *transformDepth = new TIntermBinary(
362         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscTransformDepthOffset));
363     transformDepth = new TIntermBinary(EOpBitwiseAnd, transformDepth,
364                                        CreateUIntNode(vk::kDriverUniformsMiscTransformDepthMask));
365 
366     TIntermSequence args = {
367         transformDepth,
368     };
369     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
370                                                &args);
371 }
372 
getAlphaToCoverage() const373 TIntermTyped *DriverUniform::getAlphaToCoverage() const
374 {
375     TIntermTyped *miscRef         = createDriverUniformRef(kMisc);
376     TIntermTyped *alphaToCoverage = new TIntermBinary(
377         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscAlphaToCoverageOffset));
378     alphaToCoverage = new TIntermBinary(EOpBitwiseAnd, alphaToCoverage,
379                                         CreateUIntNode(vk::kDriverUniformsMiscAlphaToCoverageMask));
380 
381     TIntermSequence args = {
382         alphaToCoverage,
383     };
384     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
385                                                &args);
386 }
387 
getLayeredFramebuffer() const388 TIntermTyped *DriverUniform::getLayeredFramebuffer() const
389 {
390     TIntermTyped *miscRef            = createDriverUniformRef(kMisc);
391     TIntermTyped *layeredFramebuffer = new TIntermBinary(
392         EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscLayeredFramebufferOffset));
393     layeredFramebuffer =
394         new TIntermBinary(EOpBitwiseAnd, layeredFramebuffer,
395                           CreateUIntNode(vk::kDriverUniformsMiscLayeredFramebufferMask));
396 
397     TIntermSequence args = {
398         layeredFramebuffer,
399     };
400     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
401                                                &args);
402 }
403 
404 //
405 // Class DriverUniformExtended
406 //
createUniformFields(TSymbolTable * symbolTable)407 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable)
408 {
409     TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
410 
411     constexpr size_t kNumGraphicsDriverUniformsExt = 4;
412     constexpr std::array<const char *, kNumGraphicsDriverUniformsExt>
413         kGraphicsDriverUniformNamesExt = {
414             {kXfbBufferOffsets, kXfbVerticesPerInstance, kUnused, kUnused2}};
415 
416     const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
417         // xfbBufferOffsets: uvec4
418         new TType(EbtInt, EbpHigh, EvqGlobal, 4),
419         // xfbVerticesPerInstance: uint
420         new TType(EbtInt, EbpHigh, EvqGlobal),
421         // unused: uvec3
422         new TType(EbtUInt, EbpHigh, EvqGlobal),
423         new TType(EbtUInt, EbpHigh, EvqGlobal, 2),
424     }};
425 
426     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
427     {
428         TField *driverUniformField =
429             new TField(kDriverUniformTypesExt[uniformIndex],
430                        ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(),
431                        SymbolType::AngleInternal);
432         driverFieldList->push_back(driverUniformField);
433     }
434 
435     return driverFieldList;
436 }
437 
getXfbBufferOffsets() const438 TIntermTyped *DriverUniformExtended::getXfbBufferOffsets() const
439 {
440     return createDriverUniformRef(kXfbBufferOffsets);
441 }
442 
getXfbVerticesPerInstance() const443 TIntermTyped *DriverUniformExtended::getXfbVerticesPerInstance() const
444 {
445     return createDriverUniformRef(kXfbVerticesPerInstance);
446 }
447 
MakeSwapXMultiplier(TIntermTyped * swapped)448 TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped)
449 {
450     // float(!swapped)
451     TIntermSequence args = {
452         new TIntermUnary(EOpLogicalNot, swapped, nullptr),
453     };
454     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args);
455 }
456 
MakeSwapYMultiplier(TIntermTyped * swapped)457 TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped)
458 {
459     // float(swapped)
460     TIntermSequence args = {
461         swapped,
462     };
463     return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args);
464 }
465 }  // namespace sh
466