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