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