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, 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 mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
71 TLayoutQualifier::Create(), TMemoryQualifier::Create(),
72 0, ImmutableString(vk::kDriverUniformsBlockName),
73 ImmutableString(vk::kDriverUniformsVarName));
74 return mDriverUniforms != nullptr;
75 }
76
createUniformFields(TSymbolTable * symbolTable)77 TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable)
78 {
79 constexpr size_t kNumGraphicsDriverUniforms = 8;
80 constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {
81 {kViewport, kClipDistancesEnabled, kXfbActiveUnpaused, kXfbVerticesPerInstance, kNumSamples,
82 kXfbBufferOffsets, kAcbBufferOffsets, kDepthRange}};
83
84 // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp.
85 TFieldList *driverFieldList = new TFieldList;
86
87 const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
88 new TType(EbtFloat, 4),
89 new TType(EbtUInt), // uint clipDistancesEnabled; // 32 bits for 32 clip distances max
90 new TType(EbtUInt),
91 new TType(EbtInt),
92 new TType(EbtInt),
93 new TType(EbtInt, 4),
94 new TType(EbtUInt, 4),
95 createEmulatedDepthRangeType(symbolTable),
96 }};
97
98 for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex)
99 {
100 TField *driverUniformField =
101 new TField(kDriverUniformTypes[uniformIndex],
102 ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(),
103 SymbolType::AngleInternal);
104 driverFieldList->push_back(driverUniformField);
105 }
106
107 return driverFieldList;
108 }
109
createEmulatedDepthRangeType(TSymbolTable * symbolTable)110 TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable)
111 {
112 // If already defined, return it immediately.
113 if (mEmulatedDepthRangeType != nullptr)
114 {
115 return mEmulatedDepthRangeType;
116 }
117
118 // Create the depth range type.
119 TFieldList *depthRangeParamsFields = new TFieldList();
120 depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
121 ImmutableString("near"), TSourceLoc(),
122 SymbolType::AngleInternal));
123 depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
124 ImmutableString("far"), TSourceLoc(),
125 SymbolType::AngleInternal));
126 depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
127 ImmutableString("diff"), TSourceLoc(),
128 SymbolType::AngleInternal));
129 // This additional field might be used by subclass such as TranslatorMetal.
130 depthRangeParamsFields->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1),
131 ImmutableString("reserved"), TSourceLoc(),
132 SymbolType::AngleInternal));
133
134 TStructure *emulatedDepthRangeParams = new TStructure(
135 symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal);
136
137 mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false);
138
139 // Note: this should really return a const TType *, but one of its uses is with TField who takes
140 // a non-const TType. See comment on that class.
141 return mEmulatedDepthRangeType;
142 }
143
144 // The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver
145 // block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms
146 // variable.
147 //
148 // There are Graphics and Compute variations as they require different uniforms.
addGraphicsDriverUniformsToShader(TIntermBlock * root,TSymbolTable * symbolTable)149 bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
150 {
151 ASSERT(!mDriverUniforms);
152
153 // Declare the depth range struct type.
154 TType *emulatedDepthRangeType = createEmulatedDepthRangeType(symbolTable);
155 TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true);
156
157 TVariable *depthRangeVar =
158 new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty,
159 TExtension::UNDEFINED, emulatedDepthRangeDeclType);
160
161 DeclareGlobalVariable(root, depthRangeVar);
162
163 TFieldList *driverFieldList = createUniformFields(symbolTable);
164 if (mMode == DriverUniformMode::InterfaceBlock)
165 {
166 // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
167 mDriverUniforms = DeclareInterfaceBlock(
168 root, symbolTable, driverFieldList, EvqUniform, TLayoutQualifier::Create(),
169 TMemoryQualifier::Create(), 0, ImmutableString(vk::kDriverUniformsBlockName),
170 ImmutableString(vk::kDriverUniformsVarName));
171 }
172 else
173 {
174 // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms".
175 // This code path is taken only by the direct-to-Metal backend, and the assumptions
176 // about the naming conventions of ANGLE-internal variables run too deeply to rename
177 // this one.
178 auto varName = ImmutableString("ANGLE_angleUniforms");
179 auto result = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform,
180 TMemoryQualifier::Create(), 0,
181 ImmutableString(vk::kDriverUniformsBlockName), &varName);
182 mDriverUniforms = result.second;
183 }
184
185 return mDriverUniforms != nullptr;
186 }
187
createDriverUniformRef(const char * fieldName) const188 TIntermBinary *DriverUniform::createDriverUniformRef(const char *fieldName) const
189 {
190 size_t fieldIndex = 0;
191 if (mMode == DriverUniformMode::InterfaceBlock)
192 {
193 fieldIndex =
194 FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName);
195 }
196 else
197 {
198 fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName);
199 }
200
201 TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms);
202 TConstantUnion *uniformIndex = new TConstantUnion;
203 uniformIndex->setIConst(static_cast<int>(fieldIndex));
204 TIntermConstantUnion *indexRef =
205 new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt>());
206 if (mMode == DriverUniformMode::InterfaceBlock)
207 {
208 return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
209 }
210 return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef);
211 }
212
getViewportRef() const213 TIntermBinary *DriverUniform::getViewportRef() const
214 {
215 return createDriverUniformRef(kViewport);
216 }
217
getAbcBufferOffsets() const218 TIntermBinary *DriverUniform::getAbcBufferOffsets() const
219 {
220 return createDriverUniformRef(kAcbBufferOffsets);
221 }
222
getXfbActiveUnpaused() const223 TIntermBinary *DriverUniform::getXfbActiveUnpaused() const
224 {
225 return createDriverUniformRef(kXfbActiveUnpaused);
226 }
227
getXfbVerticesPerInstance() const228 TIntermBinary *DriverUniform::getXfbVerticesPerInstance() const
229 {
230 return createDriverUniformRef(kXfbVerticesPerInstance);
231 }
232
getXfbBufferOffsets() const233 TIntermBinary *DriverUniform::getXfbBufferOffsets() const
234 {
235 return createDriverUniformRef(kXfbBufferOffsets);
236 }
237
getClipDistancesEnabled() const238 TIntermBinary *DriverUniform::getClipDistancesEnabled() const
239 {
240 return createDriverUniformRef(kClipDistancesEnabled);
241 }
242
getDepthRangeRef() const243 TIntermBinary *DriverUniform::getDepthRangeRef() const
244 {
245 return createDriverUniformRef(kDepthRange);
246 }
247
getDepthRangeReservedFieldRef() const248 TIntermBinary *DriverUniform::getDepthRangeReservedFieldRef() const
249 {
250 TIntermBinary *depthRange = createDriverUniformRef(kDepthRange);
251
252 return new TIntermBinary(EOpIndexDirectStruct, depthRange, CreateIndexNode(3));
253 }
254
getNumSamplesRef() const255 TIntermBinary *DriverUniform::getNumSamplesRef() const
256 {
257 return createDriverUniformRef(kNumSamples);
258 }
259
260 //
261 // Class DriverUniformExtended
262 //
createUniformFields(TSymbolTable * symbolTable)263 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable)
264 {
265 TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
266
267 constexpr size_t kNumGraphicsDriverUniformsExt = 7;
268 constexpr std::array<const char *, kNumGraphicsDriverUniformsExt>
269 kGraphicsDriverUniformNamesExt = {{kHalfRenderArea, kFlipXY, kNegFlipXY,
270 kEmulatedInstanceId, kCoverageMask, kFragRotation,
271 kPreRotation}};
272
273 const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{
274 new TType(EbtFloat, 2),
275 new TType(EbtFloat, 2),
276 new TType(EbtFloat, 2),
277 new TType(EbtUInt),
278 new TType(EbtUInt),
279 new TType(EbtFloat, 2, 2),
280 new TType(EbtFloat, 2, 2),
281 }};
282
283 for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex)
284 {
285 TField *driverUniformField =
286 new TField(kDriverUniformTypesExt[uniformIndex],
287 ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(),
288 SymbolType::AngleInternal);
289 driverFieldList->push_back(driverUniformField);
290 }
291
292 return driverFieldList;
293 }
294
getFlipXYRef() const295 TIntermBinary *DriverUniformExtended::getFlipXYRef() const
296 {
297 return createDriverUniformRef(kFlipXY);
298 }
299
getNegFlipXYRef() const300 TIntermBinary *DriverUniformExtended::getNegFlipXYRef() const
301 {
302 return createDriverUniformRef(kNegFlipXY);
303 }
304
getNegFlipYRef() const305 TIntermSwizzle *DriverUniformExtended::getNegFlipYRef() const
306 {
307 // Create a swizzle to "negFlipXY.y"
308 TIntermBinary *negFlipXY = createDriverUniformRef(kNegFlipXY);
309 TVector<int> swizzleOffsetY = {1};
310 TIntermSwizzle *negFlipY = new TIntermSwizzle(negFlipXY, swizzleOffsetY);
311 return negFlipY;
312 }
313
getPreRotationMatrixRef() const314 TIntermBinary *DriverUniformExtended::getPreRotationMatrixRef() const
315 {
316 return createDriverUniformRef(kPreRotation);
317 }
318
getFragRotationMatrixRef() const319 TIntermBinary *DriverUniformExtended::getFragRotationMatrixRef() const
320 {
321 return createDriverUniformRef(kFragRotation);
322 }
323
getHalfRenderAreaRef() const324 TIntermBinary *DriverUniformExtended::getHalfRenderAreaRef() const
325 {
326 return createDriverUniformRef(kHalfRenderArea);
327 }
328
getEmulatedInstanceId() const329 TIntermBinary *DriverUniformExtended::getEmulatedInstanceId() const
330 {
331 return createDriverUniformRef(kEmulatedInstanceId);
332 }
333
getCoverageMask() const334 TIntermBinary *DriverUniformExtended::getCoverageMask() const
335 {
336 return createDriverUniformRef(kCoverageMask);
337 }
338
339 } // namespace sh
340