• 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 kXfbActiveUnpaused[]      = "xfbActiveUnpaused";
30 constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance";
31 constexpr const char kXfbBufferOffsets[]       = "xfbBufferOffsets";
32 constexpr const char kAcbBufferOffsets[]       = "acbBufferOffsets";
33 constexpr const char kDepthRange[]             = "depthRange";
34 constexpr const char kNumSamples[]             = "numSamples";
35 constexpr const char kHalfRenderArea[]         = "halfRenderArea";
36 constexpr const char kFlipXY[]                 = "flipXY";
37 constexpr const char kNegFlipXY[]              = "negFlipXY";
38 constexpr const char kPreRotation[]            = "preRotation";
39 constexpr const char kFragRotation[]           = "fragRotation";
40 constexpr const char kEmulatedInstanceId[]     = "emulatedInstanceID";
41 constexpr const char kCoverageMask[]           = "coverageMask";
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, kXfbActiveUnpaused, kXfbVerticesPerInstance, kNumSamples,
85          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(EbtUInt, EbpLow, EvqGlobal),  // uint xfbActiveUnpaused;  // 1 bit
95         new TType(EbtInt, EbpHigh, EvqGlobal),
96         new TType(EbtInt, EbpLow, EvqGlobal),  // uint numSamples;         // Up to 16
97         new TType(EbtInt, EbpHigh, EvqGlobal, 4),
98         new TType(EbtUInt, EbpHigh, EvqGlobal, 4),
99         createEmulatedDepthRangeType(symbolTable),
100     }};
101 
102     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex)
103     {
104         TField *driverUniformField =
105             new TField(kDriverUniformTypes[uniformIndex],
106                        ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(),
107                        SymbolType::AngleInternal);
108         driverFieldList->push_back(driverUniformField);
109     }
110 
111     return driverFieldList;
112 }
113 
createEmulatedDepthRangeType(TSymbolTable * symbolTable)114 TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable)
115 {
116     // If already defined, return it immediately.
117     if (mEmulatedDepthRangeType != nullptr)
118     {
119         return mEmulatedDepthRangeType;
120     }
121 
122     // Create the depth range type.
123     TFieldList *depthRangeParamsFields = new TFieldList();
124     TType *floatType                   = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1);
125     depthRangeParamsFields->push_back(
126         new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal));
127     depthRangeParamsFields->push_back(
128         new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal));
129     depthRangeParamsFields->push_back(
130         new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal));
131     // This additional field might be used by subclass such as TranslatorMetal.
132     depthRangeParamsFields->push_back(new TField(floatType, ImmutableString("reserved"),
133                                                  TSourceLoc(), SymbolType::AngleInternal));
134 
135     TStructure *emulatedDepthRangeParams = new TStructure(
136         symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
137 
138     mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false);
139 
140     // Note: this should really return a const TType *, but one of its uses is with TField who takes
141     // a non-const TType.  See comment on that class.
142     return mEmulatedDepthRangeType;
143 }
144 
145 // The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver
146 // block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms
147 // variable.
148 //
149 // There are Graphics and Compute variations as they require different uniforms.
addGraphicsDriverUniformsToShader(TIntermBlock * root,TSymbolTable * symbolTable)150 bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
151 {
152     ASSERT(!mDriverUniforms);
153 
154     // Declare the depth range struct type.
155     TType *emulatedDepthRangeType     = createEmulatedDepthRangeType(symbolTable);
156     TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true);
157 
158     TVariable *depthRangeVar =
159         new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty,
160                       TExtension::UNDEFINED, emulatedDepthRangeDeclType);
161 
162     DeclareGlobalVariable(root, depthRangeVar);
163 
164     TFieldList *driverFieldList = createUniformFields(symbolTable);
165     if (mMode == DriverUniformMode::InterfaceBlock)
166     {
167         // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
168         TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
169         layoutQualifier.blockStorage     = EbsStd140;
170 
171         mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
172                                                 layoutQualifier, TMemoryQualifier::Create(), 0,
173                                                 ImmutableString(vk::kDriverUniformsBlockName),
174                                                 ImmutableString(vk::kDriverUniformsVarName));
175     }
176     else
177     {
178         // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms".
179         // This code path is taken only by the direct-to-Metal backend, and the assumptions
180         // about the naming conventions of ANGLE-internal variables run too deeply to rename
181         // this one.
182         auto varName    = ImmutableString("ANGLE_angleUniforms");
183         auto result     = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform,
184                                        TMemoryQualifier::Create(), 0,
185                                        ImmutableString(vk::kDriverUniformsBlockName), &varName);
186         mDriverUniforms = result.second;
187     }
188 
189     return mDriverUniforms != nullptr;
190 }
191 
createDriverUniformRef(const char * fieldName) const192 TIntermBinary *DriverUniform::createDriverUniformRef(const char *fieldName) const
193 {
194     size_t fieldIndex = 0;
195     if (mMode == DriverUniformMode::InterfaceBlock)
196     {
197         fieldIndex =
198             FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName);
199     }
200     else
201     {
202         fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName);
203     }
204 
205     TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms);
206     TConstantUnion *uniformIndex    = new TConstantUnion;
207     uniformIndex->setIConst(static_cast<int>(fieldIndex));
208     TIntermConstantUnion *indexRef =
209         new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt, EbpLow>());
210     if (mMode == DriverUniformMode::InterfaceBlock)
211     {
212         return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
213     }
214     return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef);
215 }
216 
getViewportRef() const217 TIntermBinary *DriverUniform::getViewportRef() const
218 {
219     return createDriverUniformRef(kViewport);
220 }
221 
getAbcBufferOffsets() const222 TIntermBinary *DriverUniform::getAbcBufferOffsets() const
223 {
224     return createDriverUniformRef(kAcbBufferOffsets);
225 }
226 
getXfbActiveUnpaused() const227 TIntermBinary *DriverUniform::getXfbActiveUnpaused() const
228 {
229     return createDriverUniformRef(kXfbActiveUnpaused);
230 }
231 
getXfbVerticesPerInstance() const232 TIntermBinary *DriverUniform::getXfbVerticesPerInstance() const
233 {
234     return createDriverUniformRef(kXfbVerticesPerInstance);
235 }
236 
getXfbBufferOffsets() const237 TIntermBinary *DriverUniform::getXfbBufferOffsets() const
238 {
239     return createDriverUniformRef(kXfbBufferOffsets);
240 }
241 
getClipDistancesEnabled() const242 TIntermBinary *DriverUniform::getClipDistancesEnabled() const
243 {
244     return createDriverUniformRef(kClipDistancesEnabled);
245 }
246 
getDepthRangeRef() const247 TIntermBinary *DriverUniform::getDepthRangeRef() const
248 {
249     return createDriverUniformRef(kDepthRange);
250 }
251 
getDepthRangeReservedFieldRef() const252 TIntermBinary *DriverUniform::getDepthRangeReservedFieldRef() const
253 {
254     TIntermBinary *depthRange = createDriverUniformRef(kDepthRange);
255 
256     return new TIntermBinary(EOpIndexDirectStruct, depthRange, CreateIndexNode(3));
257 }
258 
getNumSamplesRef() const259 TIntermBinary *DriverUniform::getNumSamplesRef() const
260 {
261     return createDriverUniformRef(kNumSamples);
262 }
263 
264 //
265 // Class DriverUniformExtended
266 //
createUniformFields(TSymbolTable * symbolTable)267 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable)
268 {
269     TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
270 
271     constexpr size_t kNumGraphicsDriverUniformsExt = 7;
272     constexpr std::array<const char *, kNumGraphicsDriverUniformsExt>
273         kGraphicsDriverUniformNamesExt = {{kHalfRenderArea, kFlipXY, kNegFlipXY,
274                                            kEmulatedInstanceId, kCoverageMask, kFragRotation,
275                                            kPreRotation}};
276 
277     const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
278         new TType(EbtFloat, EbpHigh, EvqGlobal, 2),
279         new TType(EbtFloat, EbpLow, EvqGlobal, 2),
280         new TType(EbtFloat, EbpLow, EvqGlobal, 2),
281         new TType(EbtUInt, EbpHigh, EvqGlobal),
282         new TType(EbtUInt, EbpHigh, EvqGlobal),
283         new TType(EbtFloat, EbpLow, EvqGlobal, 2, 2),
284         new TType(EbtFloat, EbpLow, EvqGlobal, 2, 2),
285     }};
286 
287     for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
288     {
289         TField *driverUniformField =
290             new TField(kDriverUniformTypesExt[uniformIndex],
291                        ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(),
292                        SymbolType::AngleInternal);
293         driverFieldList->push_back(driverUniformField);
294     }
295 
296     return driverFieldList;
297 }
298 
getFlipXYRef() const299 TIntermBinary *DriverUniformExtended::getFlipXYRef() const
300 {
301     return createDriverUniformRef(kFlipXY);
302 }
303 
getNegFlipXYRef() const304 TIntermBinary *DriverUniformExtended::getNegFlipXYRef() const
305 {
306     return createDriverUniformRef(kNegFlipXY);
307 }
308 
getNegFlipYRef() const309 TIntermSwizzle *DriverUniformExtended::getNegFlipYRef() const
310 {
311     // Create a swizzle to "negFlipXY.y"
312     TIntermBinary *negFlipXY    = createDriverUniformRef(kNegFlipXY);
313     TVector<int> swizzleOffsetY = {1};
314     TIntermSwizzle *negFlipY    = new TIntermSwizzle(negFlipXY, swizzleOffsetY);
315     return negFlipY;
316 }
317 
getPreRotationMatrixRef() const318 TIntermBinary *DriverUniformExtended::getPreRotationMatrixRef() const
319 {
320     return createDriverUniformRef(kPreRotation);
321 }
322 
getFragRotationMatrixRef() const323 TIntermBinary *DriverUniformExtended::getFragRotationMatrixRef() const
324 {
325     return createDriverUniformRef(kFragRotation);
326 }
327 
getHalfRenderAreaRef() const328 TIntermBinary *DriverUniformExtended::getHalfRenderAreaRef() const
329 {
330     return createDriverUniformRef(kHalfRenderArea);
331 }
332 
getEmulatedInstanceId() const333 TIntermBinary *DriverUniformExtended::getEmulatedInstanceId() const
334 {
335     return createDriverUniformRef(kEmulatedInstanceId);
336 }
337 
getCoverageMask() const338 TIntermBinary *DriverUniformExtended::getCoverageMask() const
339 {
340     return createDriverUniformRef(kCoverageMask);
341 }
342 
343 }  // namespace sh
344