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