• 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 
27 constexpr const char kViewport[]               = "viewport";
28 constexpr const char kClipDistancesEnabled[]   = "clipDistancesEnabled";
29 constexpr const char kUnused[]                 = "_unused";
30 constexpr const char kAdvancedBlendEquation[]  = "advancedBlendEquation";
31 constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance";
32 constexpr const char kXfbBufferOffsets[]       = "xfbBufferOffsets";
33 constexpr const char kAcbBufferOffsets[]       = "acbBufferOffsets";
34 constexpr const char kDepthRange[]             = "depthRange";
35 constexpr const char kNumSamples[]             = "numSamples";
36 constexpr const char kHalfRenderArea[]         = "halfRenderArea";
37 constexpr const char kFlipXY[]                 = "flipXY";
38 constexpr const char kNegFlipXY[]              = "negFlipXY";
39 constexpr const char kPreRotation[]            = "preRotation";
40 constexpr const char kFragRotation[]           = "fragRotation";
41 constexpr const char kDither[]                 = "dither";
42 
43 }  // anonymous namespace
44 
45 // Class DriverUniform
addComputeDriverUniformsToShader(TIntermBlock * root,TSymbolTable * symbolTable)46 bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
47 {
48     constexpr size_t kNumComputeDriverUniforms                                               = 1;
49     constexpr std::array<const char *, kNumComputeDriverUniforms> kComputeDriverUniformNames = {
50         {kAcbBufferOffsets}};
51 
52     ASSERT(!mDriverUniforms);
53     // This field list mirrors the structure of ComputeDriverUniforms in ContextVk.cpp.
54     TFieldList *driverFieldList = new TFieldList;
55 
56     const std::array<TType *, kNumComputeDriverUniforms> kDriverUniformTypes = {{
57         new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
58     }};
59 
60     for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex)
61     {
62         TField *driverUniformField =
63             new TField(kDriverUniformTypes[uniformIndex],
64                        ImmutableString(kComputeDriverUniformNames[uniformIndex]), TSourceLoc(),
65                        SymbolType::AngleInternal);
66         driverFieldList->push_back(driverUniformField);
67     }
68 
69     // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
70     TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
71     layoutQualifier.blockStorage     = EbsStd140;
72 
73     mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
74                                             layoutQualifier, TMemoryQualifier::Create(), 0,
75                                             ImmutableString(vk::kDriverUniformsBlockName),
76                                             ImmutableString(vk::kDriverUniformsVarName));
77     return mDriverUniforms != nullptr;
78 }
79 
createUniformFields(TSymbolTable * symbolTable)80 TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable)
81 {
82     constexpr size_t kNumGraphicsDriverUniforms                                                = 8;
83     constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {
84         {kViewport, kClipDistancesEnabled, kAdvancedBlendEquation, kXfbVerticesPerInstance,
85          kNumSamples, kXfbBufferOffsets, kAcbBufferOffsets, kDepthRange}};
86 
87     // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp.
88     TFieldList *driverFieldList = new TFieldList;
89 
90     const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
91         new TType(EbtFloat, EbpHigh, EvqGlobal, 4),
92         new TType(EbtUInt, EbpHigh,
93                   EvqGlobal),  // uint clipDistancesEnabled;  // 32 bits for 32 clip distances max
94         new TType(
95             EbtUInt, EbpLow,
96             EvqGlobal),  // uint advancedBlendEquation;
97                          // Up to BlendEquationType::HslLuminosity-BlendEquationType::Multiply+1
98         new TType(EbtInt, EbpHigh, EvqGlobal),
99         new TType(EbtInt, EbpLow, EvqGlobal),  // uint numSamples;         // Up to 16
100         new TType(EbtInt, EbpHigh, EvqGlobal, 4),
101         new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
102         createEmulatedDepthRangeType(symbolTable),
103     }};
104 
105     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex)
106     {
107         TField *driverUniformField =
108             new TField(kDriverUniformTypes[uniformIndex],
109                        ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(),
110                        SymbolType::AngleInternal);
111         driverFieldList->push_back(driverUniformField);
112     }
113 
114     return driverFieldList;
115 }
116 
createEmulatedDepthRangeType(TSymbolTable * symbolTable)117 TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable)
118 {
119     // If already defined, return it immediately.
120     if (mEmulatedDepthRangeType != nullptr)
121     {
122         return mEmulatedDepthRangeType;
123     }
124 
125     // Create the depth range type.
126     TFieldList *depthRangeParamsFields = new TFieldList();
127     TType *floatType                   = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1);
128     depthRangeParamsFields->push_back(
129         new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal));
130     depthRangeParamsFields->push_back(
131         new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal));
132     depthRangeParamsFields->push_back(
133         new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal));
134     // This additional field might be used by subclass such as TranslatorMetal.
135     depthRangeParamsFields->push_back(new TField(floatType, ImmutableString("reserved"),
136                                                  TSourceLoc(), SymbolType::AngleInternal));
137 
138     TStructure *emulatedDepthRangeParams = new TStructure(
139         symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
140 
141     mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false);
142 
143     // Note: this should really return a const TType *, but one of its uses is with TField who takes
144     // a non-const TType.  See comment on that class.
145     return mEmulatedDepthRangeType;
146 }
147 
148 // The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver
149 // block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms
150 // variable.
151 //
152 // There are Graphics and Compute variations as they require different uniforms.
addGraphicsDriverUniformsToShader(TIntermBlock * root,TSymbolTable * symbolTable)153 bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
154 {
155     ASSERT(!mDriverUniforms);
156 
157     // Declare the depth range struct type.
158     TType *emulatedDepthRangeType     = createEmulatedDepthRangeType(symbolTable);
159     TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true);
160 
161     TVariable *depthRangeVar =
162         new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty,
163                       TExtension::UNDEFINED, emulatedDepthRangeDeclType);
164 
165     DeclareGlobalVariable(root, depthRangeVar);
166 
167     TFieldList *driverFieldList = createUniformFields(symbolTable);
168     if (mMode == DriverUniformMode::InterfaceBlock)
169     {
170         // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
171         TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
172         layoutQualifier.blockStorage     = EbsStd140;
173 
174         mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
175                                                 layoutQualifier, TMemoryQualifier::Create(), 0,
176                                                 ImmutableString(vk::kDriverUniformsBlockName),
177                                                 ImmutableString(vk::kDriverUniformsVarName));
178     }
179     else
180     {
181         // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms".
182         // This code path is taken only by the direct-to-Metal backend, and the assumptions
183         // about the naming conventions of ANGLE-internal variables run too deeply to rename
184         // this one.
185         auto varName    = ImmutableString("ANGLE_angleUniforms");
186         auto result     = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform,
187                                        TMemoryQualifier::Create(), 0,
188                                        ImmutableString(vk::kDriverUniformsBlockName), &varName);
189         mDriverUniforms = result.second;
190     }
191 
192     return mDriverUniforms != nullptr;
193 }
194 
createDriverUniformRef(const char * fieldName) const195 TIntermTyped *DriverUniform::createDriverUniformRef(const char *fieldName) const
196 {
197     size_t fieldIndex = 0;
198     if (mMode == DriverUniformMode::InterfaceBlock)
199     {
200         fieldIndex =
201             FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName);
202     }
203     else
204     {
205         fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName);
206     }
207 
208     TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms);
209     TConstantUnion *uniformIndex    = new TConstantUnion;
210     uniformIndex->setIConst(static_cast<int>(fieldIndex));
211     TIntermConstantUnion *indexRef =
212         new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt, EbpLow>());
213     if (mMode == DriverUniformMode::InterfaceBlock)
214     {
215         return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
216     }
217     return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef);
218 }
219 
getViewportRef() const220 TIntermTyped *DriverUniform::getViewportRef() const
221 {
222     return createDriverUniformRef(kViewport);
223 }
224 
getAbcBufferOffsets() const225 TIntermTyped *DriverUniform::getAbcBufferOffsets() const
226 {
227     return createDriverUniformRef(kAcbBufferOffsets);
228 }
229 
getXfbVerticesPerInstance() const230 TIntermTyped *DriverUniform::getXfbVerticesPerInstance() const
231 {
232     return createDriverUniformRef(kXfbVerticesPerInstance);
233 }
234 
getXfbBufferOffsets() const235 TIntermTyped *DriverUniform::getXfbBufferOffsets() const
236 {
237     return createDriverUniformRef(kXfbBufferOffsets);
238 }
239 
getClipDistancesEnabled() const240 TIntermTyped *DriverUniform::getClipDistancesEnabled() const
241 {
242     return createDriverUniformRef(kClipDistancesEnabled);
243 }
244 
getDepthRangeRef() const245 TIntermTyped *DriverUniform::getDepthRangeRef() const
246 {
247     return createDriverUniformRef(kDepthRange);
248 }
249 
getDepthRangeReservedFieldRef() const250 TIntermTyped *DriverUniform::getDepthRangeReservedFieldRef() const
251 {
252     TIntermTyped *depthRange = createDriverUniformRef(kDepthRange);
253 
254     return new TIntermBinary(EOpIndexDirectStruct, depthRange, CreateIndexNode(3));
255 }
256 
getNumSamplesRef() const257 TIntermTyped *DriverUniform::getNumSamplesRef() const
258 {
259     return createDriverUniformRef(kNumSamples);
260 }
261 
getAdvancedBlendEquationRef() const262 TIntermTyped *DriverUniform::getAdvancedBlendEquationRef() const
263 {
264     return createDriverUniformRef(kAdvancedBlendEquation);
265 }
266 
267 //
268 // Class DriverUniformExtended
269 //
createUniformFields(TSymbolTable * symbolTable)270 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable)
271 {
272     TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
273 
274     constexpr size_t kNumGraphicsDriverUniformsExt = 7;
275     constexpr std::array<const char *, kNumGraphicsDriverUniformsExt>
276         kGraphicsDriverUniformNamesExt = {
277             {kHalfRenderArea, kFlipXY, kNegFlipXY, kDither, kUnused, kFragRotation, kPreRotation}};
278 
279     const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
280         new TType(EbtFloat, EbpHigh, EvqGlobal, 2),
281         new TType(EbtFloat, EbpLow, EvqGlobal, 2),
282         new TType(EbtFloat, EbpLow, EvqGlobal, 2),
283         new TType(EbtUInt, EbpHigh, EvqGlobal),
284         new TType(EbtUInt, EbpHigh, EvqGlobal),
285         new TType(EbtFloat, EbpLow, EvqGlobal, 2, 2),
286         new TType(EbtFloat, EbpLow, EvqGlobal, 2, 2),
287     }};
288 
289     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
290     {
291         TField *driverUniformField =
292             new TField(kDriverUniformTypesExt[uniformIndex],
293                        ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(),
294                        SymbolType::AngleInternal);
295         driverFieldList->push_back(driverUniformField);
296     }
297 
298     return driverFieldList;
299 }
300 
getFlipXYRef() const301 TIntermTyped *DriverUniformExtended::getFlipXYRef() const
302 {
303     return createDriverUniformRef(kFlipXY);
304 }
305 
getNegFlipXYRef() const306 TIntermTyped *DriverUniformExtended::getNegFlipXYRef() const
307 {
308     return createDriverUniformRef(kNegFlipXY);
309 }
310 
getNegFlipYRef() const311 TIntermTyped *DriverUniformExtended::getNegFlipYRef() const
312 {
313     // Create a swizzle to "negFlipXY.y"
314     TIntermTyped *negFlipXY     = createDriverUniformRef(kNegFlipXY);
315     TVector<int> swizzleOffsetY = {1};
316     TIntermSwizzle *negFlipY    = new TIntermSwizzle(negFlipXY, swizzleOffsetY);
317     return negFlipY;
318 }
319 
getPreRotationMatrixRef() const320 TIntermTyped *DriverUniformExtended::getPreRotationMatrixRef() const
321 {
322     return createDriverUniformRef(kPreRotation);
323 }
324 
getFragRotationMatrixRef() const325 TIntermTyped *DriverUniformExtended::getFragRotationMatrixRef() const
326 {
327     return createDriverUniformRef(kFragRotation);
328 }
329 
getHalfRenderAreaRef() const330 TIntermTyped *DriverUniformExtended::getHalfRenderAreaRef() const
331 {
332     return createDriverUniformRef(kHalfRenderArea);
333 }
334 
getDitherRef() const335 TIntermTyped *DriverUniformExtended::getDitherRef() const
336 {
337     return createDriverUniformRef(kDither);
338 }
339 
340 }  // namespace sh
341