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 // SpecializationConst.cpp: Add code to generate AST node for various specialization constants.
7 //
8
9 #include "compiler/translator/tree_util/SpecializationConstant.h"
10 #include "common/PackedEnums.h"
11 #include "common/angleutils.h"
12 #include "compiler/translator/StaticType.h"
13 #include "compiler/translator/SymbolTable.h"
14 #include "compiler/translator/tree_util/IntermNode_util.h"
15
16 namespace sh
17 {
18
19 namespace
20 {
21 // Specialization constant names
22 constexpr ImmutableString kLineRasterEmulationSpecConstVarName =
23 ImmutableString("ANGLELineRasterEmulation");
24 constexpr ImmutableString kSurfaceRotationSpecConstVarName =
25 ImmutableString("ANGLESurfaceRotation");
26 constexpr ImmutableString kDrawableWidthSpecConstVarName = ImmutableString("ANGLEDrawableWidth");
27 constexpr ImmutableString kDrawableHeightSpecConstVarName = ImmutableString("ANGLEDrawableHeight");
28
29 // When an Android surface is rotated differently than the device's native orientation, ANGLE must
30 // rotate gl_Position in the vertex shader and gl_FragCoord in the fragment shader. The following
31 // are the rotation matrices used.
32 //
33 // This is 2x2 matrix in column major. The first column is for dFdx and second column is for dFdy.
34 using Mat2x2 = std::array<float, 4>;
35 using Mat2x2EnumMap =
36 angle::PackedEnumMap<vk::SurfaceRotation, Mat2x2, angle::EnumSize<vk::SurfaceRotation>()>;
37
38 constexpr Mat2x2EnumMap kPreRotationMatrices = {
39 {{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
40 {vk::SurfaceRotation::Rotated90Degrees, {{0.0f, -1.0f, 1.0f, 0.0f}}},
41 {vk::SurfaceRotation::Rotated180Degrees, {{-1.0f, 0.0f, 0.0f, -1.0f}}},
42 {vk::SurfaceRotation::Rotated270Degrees, {{0.0f, 1.0f, -1.0f, 0.0f}}},
43 {vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
44 {vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, -1.0f, 1.0f, 0.0f}}},
45 {vk::SurfaceRotation::FlippedRotated180Degrees, {{-1.0f, 0.0f, 0.0f, -1.0f}}},
46 {vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, -1.0f, 0.0f}}}}};
47
48 constexpr Mat2x2EnumMap kFragRotationMatrices = {
49 {{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
50 {vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
51 {vk::SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
52 {vk::SurfaceRotation::Rotated270Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
53 {vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
54 {vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
55 {vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
56 {vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}}}};
57
58 // TODO: https://issuetracker.google.com/174066134. This is to make sure the specialization constant
59 // code path behaves exactly the same as driver uniform code path. Not sure why this has to be
60 // different from kFragRotationMatrices.
61 constexpr Mat2x2EnumMap kHalfRenderAreaRotationMatrices = {
62 {{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
63 {vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
64 {vk::SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
65 {vk::SurfaceRotation::Rotated270Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
66 {vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
67 {vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
68 {vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
69 {vk::SurfaceRotation::FlippedRotated270Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}}}};
70
71 // Returns mat2(m0, m1, m2, m3)
CreateMat2x2(const Mat2x2EnumMap & matrix,vk::SurfaceRotation rotation)72 TIntermAggregate *CreateMat2x2(const Mat2x2EnumMap &matrix, vk::SurfaceRotation rotation)
73 {
74 auto mat2Type = new TType(EbtFloat, 2, 2);
75 TIntermSequence mat2Args;
76 mat2Args.push_back(CreateFloatNode(matrix[rotation][0]));
77 mat2Args.push_back(CreateFloatNode(matrix[rotation][1]));
78 mat2Args.push_back(CreateFloatNode(matrix[rotation][2]));
79 mat2Args.push_back(CreateFloatNode(matrix[rotation][3]));
80 TIntermAggregate *constVarConstructor =
81 TIntermAggregate::CreateConstructor(*mat2Type, &mat2Args);
82 return constVarConstructor;
83 }
84
85 // Generates an array of vec2 and then use rotation to retrieve the desired flipXY out.
GenerateMat2x2ArrayWithIndex(const Mat2x2EnumMap & matrix,TIntermSymbol * rotation)86 TIntermTyped *GenerateMat2x2ArrayWithIndex(const Mat2x2EnumMap &matrix, TIntermSymbol *rotation)
87 {
88 auto mat2Type = new TType(EbtFloat, 2, 2);
89 TType *typeMat2Array = new TType(*mat2Type);
90 typeMat2Array->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
91
92 TIntermSequence sequences = {
93 CreateMat2x2(matrix, vk::SurfaceRotation::Identity),
94 CreateMat2x2(matrix, vk::SurfaceRotation::Rotated90Degrees),
95 CreateMat2x2(matrix, vk::SurfaceRotation::Rotated180Degrees),
96 CreateMat2x2(matrix, vk::SurfaceRotation::Rotated270Degrees),
97 CreateMat2x2(matrix, vk::SurfaceRotation::FlippedIdentity),
98 CreateMat2x2(matrix, vk::SurfaceRotation::FlippedRotated90Degrees),
99 CreateMat2x2(matrix, vk::SurfaceRotation::FlippedRotated180Degrees),
100 CreateMat2x2(matrix, vk::SurfaceRotation::FlippedRotated270Degrees)};
101 TIntermTyped *array = TIntermAggregate::CreateConstructor(*typeMat2Array, &sequences);
102 return new TIntermBinary(EOpIndexIndirect, array, rotation);
103 }
104
105 using Vec2 = std::array<float, 2>;
106 using Vec2EnumMap =
107 angle::PackedEnumMap<vk::SurfaceRotation, Vec2, angle::EnumSize<vk::SurfaceRotation>()>;
108 constexpr Vec2EnumMap kFlipXYValue = {
109 {{vk::SurfaceRotation::Identity, {{1.0f, 1.0f}}},
110 {vk::SurfaceRotation::Rotated90Degrees, {{1.0f, 1.0f}}},
111 {vk::SurfaceRotation::Rotated180Degrees, {{-1.0f, 1.0f}}},
112 {vk::SurfaceRotation::Rotated270Degrees, {{-1.0f, -1.0f}}},
113 {vk::SurfaceRotation::FlippedIdentity, {{1.0f, -1.0f}}},
114 {vk::SurfaceRotation::FlippedRotated90Degrees, {{1.0f, 1.0f}}},
115 {vk::SurfaceRotation::FlippedRotated180Degrees, {{-1.0f, 1.0f}}},
116 {vk::SurfaceRotation::FlippedRotated270Degrees, {{-1.0f, -1.0f}}}}};
117
118 // Returns [[flipX*m0+flipY*m1] [flipX*m2+flipY*m3]] where [m0 m1] is the first column of
119 // kFragRotation matrix and [m2 m3] is the second column of kFragRotation matrix.
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation rotation)120 constexpr Vec2 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation rotation)
121 {
122 return Vec2({kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][0] +
123 kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][1],
124 kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][2] +
125 kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][3]});
126 }
127
128 // Returns vec2(vec2Values.x, vec2Values.y*yscale)
CreateVec2(Vec2EnumMap vec2Values,float yscale,vk::SurfaceRotation rotation)129 TIntermAggregate *CreateVec2(Vec2EnumMap vec2Values, float yscale, vk::SurfaceRotation rotation)
130 {
131 auto vec2Type = new TType(EbtFloat, 2);
132 TIntermSequence vec2Args;
133 vec2Args.push_back(CreateFloatNode(vec2Values[rotation][0]));
134 vec2Args.push_back(CreateFloatNode(vec2Values[rotation][1] * yscale));
135 TIntermAggregate *constVarConstructor =
136 TIntermAggregate::CreateConstructor(*vec2Type, &vec2Args);
137 return constVarConstructor;
138 }
139
140 // Generates an array of vec2 and then use rotation to retrieve the desired flipXY out.
CreateVec2ArrayWithIndex(Vec2EnumMap vec2Values,float yscale,TIntermSymbol * rotation)141 TIntermTyped *CreateVec2ArrayWithIndex(Vec2EnumMap vec2Values,
142 float yscale,
143 TIntermSymbol *rotation)
144 {
145 auto vec2Type = new TType(EbtFloat, 2);
146 TType *typeVec2Array = new TType(*vec2Type);
147 typeVec2Array->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
148
149 TIntermSequence sequences = {
150 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Identity),
151 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Rotated90Degrees),
152 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Rotated180Degrees),
153 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Rotated270Degrees),
154 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedIdentity),
155 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedRotated90Degrees),
156 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedRotated180Degrees),
157 CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedRotated270Degrees)};
158 TIntermTyped *vec2Array = TIntermAggregate::CreateConstructor(*typeVec2Array, &sequences);
159 return new TIntermBinary(EOpIndexIndirect, vec2Array, rotation);
160 }
161
162 // Returns [flipX*m0, flipY*m1], where [m0 m1] is the first column of kFragRotation matrix.
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation rotation)163 constexpr Vec2 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation rotation)
164 {
165 return Vec2({kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][0],
166 kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][1]});
167 }
168 constexpr Vec2EnumMap kRotatedFlipXYForDFdx = {
169 {{vk::SurfaceRotation::Identity, CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Identity)},
170 {vk::SurfaceRotation::Rotated90Degrees,
171 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated90Degrees)},
172 {vk::SurfaceRotation::Rotated180Degrees,
173 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated180Degrees)},
174 {vk::SurfaceRotation::Rotated270Degrees,
175 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated270Degrees)},
176 {vk::SurfaceRotation::FlippedIdentity,
177 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedIdentity)},
178 {vk::SurfaceRotation::FlippedRotated90Degrees,
179 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated90Degrees)},
180 {vk::SurfaceRotation::FlippedRotated180Degrees,
181 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated180Degrees)},
182 {vk::SurfaceRotation::FlippedRotated270Degrees,
183 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
184
185 // Returns [flipX*m2, flipY*m3], where [m2 m3] is the second column of kFragRotation matrix.
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation rotation)186 constexpr Vec2 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation rotation)
187 {
188 return Vec2({kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][2],
189 kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][3]});
190 }
191 constexpr Vec2EnumMap kRotatedFlipXYForDFdy = {
192 {{vk::SurfaceRotation::Identity, CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Identity)},
193 {vk::SurfaceRotation::Rotated90Degrees,
194 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated90Degrees)},
195 {vk::SurfaceRotation::Rotated180Degrees,
196 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated180Degrees)},
197 {vk::SurfaceRotation::Rotated270Degrees,
198 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated270Degrees)},
199 {vk::SurfaceRotation::FlippedIdentity,
200 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedIdentity)},
201 {vk::SurfaceRotation::FlippedRotated90Degrees,
202 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated90Degrees)},
203 {vk::SurfaceRotation::FlippedRotated180Degrees,
204 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated180Degrees)},
205 {vk::SurfaceRotation::FlippedRotated270Degrees,
206 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
207
208 // Returns an array of float and then use rotation to retrieve the desired float value out.
CreateFloatArrayWithRotationIndex(const Vec2EnumMap & valuesEnumMap,int subscript,float scale,TIntermSymbol * rotation)209 TIntermTyped *CreateFloatArrayWithRotationIndex(const Vec2EnumMap &valuesEnumMap,
210 int subscript,
211 float scale,
212 TIntermSymbol *rotation)
213 {
214 const TType *floatType = StaticType::GetBasic<EbtFloat>();
215 TType *typeFloat8 = new TType(*floatType);
216 typeFloat8->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
217
218 TIntermSequence sequences = {
219 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Identity][subscript] * scale),
220 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Rotated90Degrees][subscript] * scale),
221 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Rotated180Degrees][subscript] * scale),
222 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Rotated270Degrees][subscript] * scale),
223 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedIdentity][subscript] * scale),
224 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedRotated90Degrees][subscript] *
225 scale),
226 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedRotated180Degrees][subscript] *
227 scale),
228 CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedRotated270Degrees][subscript] *
229 scale)};
230 TIntermTyped *array = TIntermAggregate::CreateConstructor(*typeFloat8, &sequences);
231
232 return new TIntermBinary(EOpIndexIndirect, array, rotation);
233 }
234
MakeSpecConst(const TType & type,vk::SpecializationConstantId id)235 const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id)
236 {
237 // Create a new type with the EvqSpecConst qualifier
238 TType *specConstType = new TType(type);
239 specConstType->setQualifier(EvqSpecConst);
240
241 // Set the constant_id of the spec const
242 TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
243 layoutQualifier.location = static_cast<int>(id);
244 specConstType->setLayoutQualifier(layoutQualifier);
245
246 return specConstType;
247 }
248 } // anonymous namespace
249
SpecConst(TSymbolTable * symbolTable,ShCompileOptions compileOptions,GLenum shaderType)250 SpecConst::SpecConst(TSymbolTable *symbolTable, ShCompileOptions compileOptions, GLenum shaderType)
251 : mSymbolTable(symbolTable),
252 mCompileOptions(compileOptions),
253 mLineRasterEmulationVar(nullptr),
254 mSurfaceRotationVar(nullptr),
255 mDrawableWidthVar(nullptr),
256 mDrawableHeightVar(nullptr)
257 {
258 if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER)
259 {
260 return;
261 }
262
263 // Mark SpecConstUsage::Rotation unconditionally. gl_Position is always rotated.
264 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) != 0 &&
265 (mCompileOptions & SH_ADD_PRE_ROTATION) != 0)
266 {
267 mUsageBits.set(vk::SpecConstUsage::Rotation);
268 }
269 }
270
~SpecConst()271 SpecConst::~SpecConst() {}
272
declareSpecConsts(TIntermBlock * root)273 void SpecConst::declareSpecConsts(TIntermBlock *root)
274 {
275 // Add specialization constant declarations. The default value of the specialization
276 // constant is irrelevant, as it will be set when creating the pipeline.
277 // Only emit specialized const declaration if it has been referenced.
278 if (mLineRasterEmulationVar != nullptr)
279 {
280 TIntermDeclaration *decl = new TIntermDeclaration();
281 decl->appendDeclarator(
282 new TIntermBinary(EOpInitialize, getLineRasterEmulation(), CreateBoolNode(false)));
283
284 root->insertStatement(0, decl);
285 }
286
287 if (mSurfaceRotationVar != nullptr)
288 {
289 TIntermDeclaration *decl = new TIntermDeclaration();
290 decl->appendDeclarator(
291 new TIntermBinary(EOpInitialize, getFlipRotation(), CreateUIntNode(0)));
292
293 root->insertStatement(0, decl);
294 }
295
296 if (mDrawableWidthVar != nullptr)
297 {
298 TIntermDeclaration *decl = new TIntermDeclaration();
299 decl->appendDeclarator(
300 new TIntermBinary(EOpInitialize, getDrawableWidth(), CreateFloatNode(0)));
301 root->insertStatement(0, decl);
302 }
303
304 if (mDrawableHeightVar != nullptr)
305 {
306 TIntermDeclaration *decl = new TIntermDeclaration();
307 decl->appendDeclarator(
308 new TIntermBinary(EOpInitialize, getDrawableHeight(), CreateFloatNode(0)));
309 root->insertStatement(1, decl);
310 }
311 }
312
getLineRasterEmulation()313 TIntermSymbol *SpecConst::getLineRasterEmulation()
314 {
315 if ((mCompileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION) == 0)
316 {
317 return nullptr;
318 }
319 if (mLineRasterEmulationVar == nullptr)
320 {
321 const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool>(),
322 vk::SpecializationConstantId::LineRasterEmulation);
323
324 mLineRasterEmulationVar = new TVariable(mSymbolTable, kLineRasterEmulationSpecConstVarName,
325 type, SymbolType::AngleInternal);
326 mUsageBits.set(vk::SpecConstUsage::LineRasterEmulation);
327 }
328 return new TIntermSymbol(mLineRasterEmulationVar);
329 }
330
getFlipRotation()331 TIntermSymbol *SpecConst::getFlipRotation()
332 {
333 if (mSurfaceRotationVar == nullptr)
334 {
335 const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt>(),
336 vk::SpecializationConstantId::SurfaceRotation);
337
338 mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type,
339 SymbolType::AngleInternal);
340 }
341 return new TIntermSymbol(mSurfaceRotationVar);
342 }
343
getMultiplierXForDFdx()344 TIntermTyped *SpecConst::getMultiplierXForDFdx()
345 {
346 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
347 {
348 return nullptr;
349 }
350 mUsageBits.set(vk::SpecConstUsage::YFlip);
351 mUsageBits.set(vk::SpecConstUsage::Rotation);
352 return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdx, 0, 1, getFlipRotation());
353 }
354
getMultiplierYForDFdx()355 TIntermTyped *SpecConst::getMultiplierYForDFdx()
356 {
357 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
358 {
359 return nullptr;
360 }
361 mUsageBits.set(vk::SpecConstUsage::YFlip);
362 mUsageBits.set(vk::SpecConstUsage::Rotation);
363 return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdx, 1, 1, getFlipRotation());
364 }
365
getMultiplierXForDFdy()366 TIntermTyped *SpecConst::getMultiplierXForDFdy()
367 {
368 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
369 {
370 return nullptr;
371 }
372 mUsageBits.set(vk::SpecConstUsage::YFlip);
373 mUsageBits.set(vk::SpecConstUsage::Rotation);
374 return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdy, 0, 1, getFlipRotation());
375 }
376
getMultiplierYForDFdy()377 TIntermTyped *SpecConst::getMultiplierYForDFdy()
378 {
379 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
380 {
381 return nullptr;
382 }
383 mUsageBits.set(vk::SpecConstUsage::YFlip);
384 mUsageBits.set(vk::SpecConstUsage::Rotation);
385 return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdy, 1, 1, getFlipRotation());
386 }
387
getPreRotationMatrix()388 TIntermTyped *SpecConst::getPreRotationMatrix()
389 {
390 if (!(mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT))
391 {
392 return nullptr;
393 }
394 mUsageBits.set(vk::SpecConstUsage::Rotation);
395 return GenerateMat2x2ArrayWithIndex(kPreRotationMatrices, getFlipRotation());
396 }
397
getFragRotationMatrix()398 TIntermTyped *SpecConst::getFragRotationMatrix()
399 {
400 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
401 {
402 return nullptr;
403 }
404 mUsageBits.set(vk::SpecConstUsage::Rotation);
405 return GenerateMat2x2ArrayWithIndex(kFragRotationMatrices, getFlipRotation());
406 }
407
getHalfRenderAreaRotationMatrix()408 TIntermTyped *SpecConst::getHalfRenderAreaRotationMatrix()
409 {
410 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
411 {
412 return nullptr;
413 }
414 mUsageBits.set(vk::SpecConstUsage::Rotation);
415 return GenerateMat2x2ArrayWithIndex(kHalfRenderAreaRotationMatrices, getFlipRotation());
416 }
417
getFlipXY()418 TIntermTyped *SpecConst::getFlipXY()
419 {
420 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
421 {
422 return nullptr;
423 }
424 mUsageBits.set(vk::SpecConstUsage::YFlip);
425 return CreateVec2ArrayWithIndex(kFlipXYValue, 1.0, getFlipRotation());
426 }
427
getNegFlipXY()428 TIntermTyped *SpecConst::getNegFlipXY()
429 {
430 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
431 {
432 return nullptr;
433 }
434 mUsageBits.set(vk::SpecConstUsage::YFlip);
435 return CreateVec2ArrayWithIndex(kFlipXYValue, -1.0, getFlipRotation());
436 }
437
getFlipY()438 TIntermTyped *SpecConst::getFlipY()
439 {
440 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
441 {
442 return nullptr;
443 }
444 mUsageBits.set(vk::SpecConstUsage::YFlip);
445 return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, 1, getFlipRotation());
446 }
447
getNegFlipY()448 TIntermTyped *SpecConst::getNegFlipY()
449 {
450 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
451 {
452 return nullptr;
453 }
454 mUsageBits.set(vk::SpecConstUsage::YFlip);
455 return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, -1, getFlipRotation());
456 }
457
getFragRotationMultiplyFlipXY()458 TIntermTyped *SpecConst::getFragRotationMultiplyFlipXY()
459 {
460 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
461 {
462 return nullptr;
463 }
464
465 constexpr Vec2EnumMap kFragRotationMultiplyFlipXY = {
466 {{vk::SurfaceRotation::Identity,
467 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Identity)},
468 {vk::SurfaceRotation::Rotated90Degrees,
469 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Rotated90Degrees)},
470 {vk::SurfaceRotation::Rotated180Degrees,
471 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Rotated180Degrees)},
472 {vk::SurfaceRotation::Rotated270Degrees,
473 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Rotated270Degrees)},
474 {vk::SurfaceRotation::FlippedIdentity,
475 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedIdentity)},
476 {vk::SurfaceRotation::FlippedRotated90Degrees,
477 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedRotated90Degrees)},
478 {vk::SurfaceRotation::FlippedRotated180Degrees,
479 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedRotated180Degrees)},
480 {vk::SurfaceRotation::FlippedRotated270Degrees,
481 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
482
483 mUsageBits.set(vk::SpecConstUsage::YFlip);
484 mUsageBits.set(vk::SpecConstUsage::Rotation);
485 return CreateVec2ArrayWithIndex(kFragRotationMultiplyFlipXY, 1.0, getFlipRotation());
486 }
487
getDrawableWidth()488 TIntermSymbol *SpecConst::getDrawableWidth()
489 {
490 if (mDrawableWidthVar == nullptr)
491 {
492 const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
493 vk::SpecializationConstantId::DrawableWidth);
494
495 mDrawableWidthVar = new TVariable(mSymbolTable, kDrawableWidthSpecConstVarName, type,
496 SymbolType::AngleInternal);
497 }
498 return new TIntermSymbol(mDrawableWidthVar);
499 }
500
getDrawableHeight()501 TIntermSymbol *SpecConst::getDrawableHeight()
502 {
503 if (mDrawableHeightVar == nullptr)
504 {
505 const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
506 vk::SpecializationConstantId::DrawableHeight);
507
508 mDrawableHeightVar = new TVariable(mSymbolTable, kDrawableHeightSpecConstVarName, type,
509 SymbolType::AngleInternal);
510 }
511 return new TIntermSymbol(mDrawableHeightVar);
512 }
513
getHalfRenderArea()514 TIntermBinary *SpecConst::getHalfRenderArea()
515 {
516 if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
517 {
518 return nullptr;
519 }
520
521 // vec2 drawableSize(drawableWidth, drawableHeight)
522 auto vec2Type = new TType(EbtFloat, 2);
523 TIntermSequence widthHeightArgs;
524 widthHeightArgs.push_back(getDrawableWidth());
525 widthHeightArgs.push_back(getDrawableHeight());
526 TIntermAggregate *drawableSize =
527 TIntermAggregate::CreateConstructor(*vec2Type, &widthHeightArgs);
528
529 // drawableSize * 0.5f
530 TIntermBinary *halfRenderArea =
531 new TIntermBinary(EOpVectorTimesScalar, drawableSize, CreateFloatNode(0.5));
532 mUsageBits.set(vk::SpecConstUsage::DrawableSize);
533
534 // drawableSize * 0.5f * halfRenderAreaRotationMatrix (See comment in
535 // kHalfRenderAreaRotationMatrices)
536 TIntermBinary *rotatedHalfRenderArea =
537 new TIntermBinary(EOpMatrixTimesVector, getHalfRenderAreaRotationMatrix(), halfRenderArea);
538
539 return rotatedHalfRenderArea;
540 }
541 } // namespace sh
542