blob: a23aa989e0dc50dc09ce7fd7027a79d41b87aa94 [file] [log] [blame]
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SpecializationConst.cpp: Add code to generate AST node for various specialization constants.
//
#include "compiler/translator/tree_util/SpecializationConstant.h"
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
namespace sh
{
namespace
{
// Specialization constant names
constexpr ImmutableString kLineRasterEmulationSpecConstVarName =
ImmutableString("ANGLELineRasterEmulation");
constexpr ImmutableString kSurfaceRotationSpecConstVarName =
ImmutableString("ANGLESurfaceRotation");
constexpr ImmutableString kDrawableWidthSpecConstVarName = ImmutableString("ANGLEDrawableWidth");
constexpr ImmutableString kDrawableHeightSpecConstVarName = ImmutableString("ANGLEDrawableHeight");
// When an Android surface is rotated differently than the device's native orientation, ANGLE must
// rotate gl_Position in the vertex shader and gl_FragCoord in the fragment shader. The following
// are the rotation matrices used.
//
// This is 2x2 matrix in column major. The first column is for dFdx and second column is for dFdy.
using Mat2x2 = std::array<float, 4>;
using Mat2x2EnumMap =
angle::PackedEnumMap<vk::SurfaceRotation, Mat2x2, angle::EnumSize<vk::SurfaceRotation>()>;
constexpr Mat2x2EnumMap kPreRotationMatrices = {
{{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{0.0f, -1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::Rotated180Degrees, {{-1.0f, 0.0f, 0.0f, -1.0f}}},
{vk::SurfaceRotation::Rotated270Degrees, {{0.0f, 1.0f, -1.0f, 0.0f}}},
{vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, -1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::FlippedRotated180Degrees, {{-1.0f, 0.0f, 0.0f, -1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, -1.0f, 0.0f}}}}};
constexpr Mat2x2EnumMap kFragRotationMatrices = {
{{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated270Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}}}};
// TODO: https://issuetracker.google.com/174066134. This is to make sure the specialization constant
// code path behaves exactly the same as driver uniform code path. Not sure why this has to be
// different from kFragRotationMatrices.
constexpr Mat2x2EnumMap kHalfRenderAreaRotationMatrices = {
{{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated270Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
{vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{1.0f, 0.0f, 0.0f, 1.0f}}}}};
// Returns mat2(m0, m1, m2, m3)
TIntermAggregate *CreateMat2x2(const Mat2x2EnumMap &matrix, vk::SurfaceRotation rotation)
{
auto mat2Type = new TType(EbtFloat, 2, 2);
TIntermSequence mat2Args;
mat2Args.push_back(CreateFloatNode(matrix[rotation][0]));
mat2Args.push_back(CreateFloatNode(matrix[rotation][1]));
mat2Args.push_back(CreateFloatNode(matrix[rotation][2]));
mat2Args.push_back(CreateFloatNode(matrix[rotation][3]));
TIntermAggregate *constVarConstructor =
TIntermAggregate::CreateConstructor(*mat2Type, &mat2Args);
return constVarConstructor;
}
// Generates an array of vec2 and then use rotation to retrieve the desired flipXY out.
TIntermTyped *GenerateMat2x2ArrayWithIndex(const Mat2x2EnumMap &matrix, TIntermSymbol *rotation)
{
auto mat2Type = new TType(EbtFloat, 2, 2);
TType *typeMat2Array = new TType(*mat2Type);
typeMat2Array->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
TIntermSequence sequences = {
CreateMat2x2(matrix, vk::SurfaceRotation::Identity),
CreateMat2x2(matrix, vk::SurfaceRotation::Rotated90Degrees),
CreateMat2x2(matrix, vk::SurfaceRotation::Rotated180Degrees),
CreateMat2x2(matrix, vk::SurfaceRotation::Rotated270Degrees),
CreateMat2x2(matrix, vk::SurfaceRotation::FlippedIdentity),
CreateMat2x2(matrix, vk::SurfaceRotation::FlippedRotated90Degrees),
CreateMat2x2(matrix, vk::SurfaceRotation::FlippedRotated180Degrees),
CreateMat2x2(matrix, vk::SurfaceRotation::FlippedRotated270Degrees)};
TIntermTyped *array = TIntermAggregate::CreateConstructor(*typeMat2Array, &sequences);
return new TIntermBinary(EOpIndexIndirect, array, rotation);
}
using Vec2 = std::array<float, 2>;
using Vec2EnumMap =
angle::PackedEnumMap<vk::SurfaceRotation, Vec2, angle::EnumSize<vk::SurfaceRotation>()>;
constexpr Vec2EnumMap kFlipXYValue = {
{{vk::SurfaceRotation::Identity, {{1.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{1.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated180Degrees, {{-1.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated270Degrees, {{-1.0f, -1.0f}}},
{vk::SurfaceRotation::FlippedIdentity, {{1.0f, -1.0f}}},
{vk::SurfaceRotation::FlippedRotated90Degrees, {{1.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated180Degrees, {{-1.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{-1.0f, -1.0f}}}}};
// Returns [[flipX*m0+flipY*m1] [flipX*m2+flipY*m3]] where [m0 m1] is the first column of
// kFragRotation matrix and [m2 m3] is the second column of kFragRotation matrix.
constexpr Vec2 CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation rotation)
{
return Vec2({kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][0] +
kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][1],
kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][2] +
kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][3]});
}
// Returns vec2(vec2Values.x, vec2Values.y*yscale)
TIntermAggregate *CreateVec2(Vec2EnumMap vec2Values, float yscale, vk::SurfaceRotation rotation)
{
auto vec2Type = new TType(EbtFloat, 2);
TIntermSequence vec2Args;
vec2Args.push_back(CreateFloatNode(vec2Values[rotation][0]));
vec2Args.push_back(CreateFloatNode(vec2Values[rotation][1] * yscale));
TIntermAggregate *constVarConstructor =
TIntermAggregate::CreateConstructor(*vec2Type, &vec2Args);
return constVarConstructor;
}
// Generates an array of vec2 and then use rotation to retrieve the desired flipXY out.
TIntermTyped *CreateVec2ArrayWithIndex(Vec2EnumMap vec2Values,
float yscale,
TIntermSymbol *rotation)
{
auto vec2Type = new TType(EbtFloat, 2);
TType *typeVec2Array = new TType(*vec2Type);
typeVec2Array->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
TIntermSequence sequences = {
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Identity),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Rotated90Degrees),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Rotated180Degrees),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::Rotated270Degrees),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedIdentity),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedRotated90Degrees),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedRotated180Degrees),
CreateVec2(vec2Values, yscale, vk::SurfaceRotation::FlippedRotated270Degrees)};
TIntermTyped *vec2Array = TIntermAggregate::CreateConstructor(*typeVec2Array, &sequences);
return new TIntermBinary(EOpIndexIndirect, vec2Array, rotation);
}
// Returns [flipX*m0, flipY*m1], where [m0 m1] is the first column of kFragRotation matrix.
constexpr Vec2 CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation rotation)
{
return Vec2({kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][0],
kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][1]});
}
constexpr Vec2EnumMap kRotatedFlipXYForDFdx = {
{{vk::SurfaceRotation::Identity, CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Identity)},
{vk::SurfaceRotation::Rotated90Degrees,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
// Returns [flipX*m2, flipY*m3], where [m2 m3] is the second column of kFragRotation matrix.
constexpr Vec2 CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation rotation)
{
return Vec2({kFlipXYValue[rotation][0] * kFragRotationMatrices[rotation][2],
kFlipXYValue[rotation][1] * kFragRotationMatrices[rotation][3]});
}
constexpr Vec2EnumMap kRotatedFlipXYForDFdy = {
{{vk::SurfaceRotation::Identity, CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Identity)},
{vk::SurfaceRotation::Rotated90Degrees,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
// Returns an array of float and then use rotation to retrieve the desired float value out.
TIntermTyped *CreateFloatArrayWithRotationIndex(const Vec2EnumMap &valuesEnumMap,
int subscript,
float scale,
TIntermSymbol *rotation)
{
const TType *floatType = StaticType::GetBasic<EbtFloat>();
TType *typeFloat8 = new TType(*floatType);
typeFloat8->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
TIntermSequence sequences = {
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Identity][subscript] * scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Rotated90Degrees][subscript] * scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Rotated180Degrees][subscript] * scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::Rotated270Degrees][subscript] * scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedIdentity][subscript] * scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedRotated90Degrees][subscript] *
scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedRotated180Degrees][subscript] *
scale),
CreateFloatNode(valuesEnumMap[vk::SurfaceRotation::FlippedRotated270Degrees][subscript] *
scale)};
TIntermTyped *array = TIntermAggregate::CreateConstructor(*typeFloat8, &sequences);
return new TIntermBinary(EOpIndexIndirect, array, rotation);
}
const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id)
{
// Create a new type with the EvqSpecConst qualifier
TType *specConstType = new TType(type);
specConstType->setQualifier(EvqSpecConst);
// Set the constant_id of the spec const
TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
layoutQualifier.location = static_cast<int>(id);
specConstType->setLayoutQualifier(layoutQualifier);
return specConstType;
}
} // anonymous namespace
SpecConst::SpecConst(TSymbolTable *symbolTable, ShCompileOptions compileOptions, GLenum shaderType)
: mSymbolTable(symbolTable),
mCompileOptions(compileOptions),
mLineRasterEmulationVar(nullptr),
mSurfaceRotationVar(nullptr),
mDrawableWidthVar(nullptr),
mDrawableHeightVar(nullptr)
{
if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER)
{
return;
}
// Mark SpecConstUsage::Rotation unconditionally. gl_Position is always rotated.
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) != 0 &&
(mCompileOptions & SH_ADD_PRE_ROTATION) != 0)
{
mUsageBits.set(vk::SpecConstUsage::Rotation);
}
}
SpecConst::~SpecConst() {}
void SpecConst::declareSpecConsts(TIntermBlock *root)
{
// Add specialization constant declarations. The default value of the specialization
// constant is irrelevant, as it will be set when creating the pipeline.
// Only emit specialized const declaration if it has been referenced.
if (mLineRasterEmulationVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(
new TIntermBinary(EOpInitialize, getLineRasterEmulation(), CreateBoolNode(false)));
root->insertStatement(0, decl);
}
if (mSurfaceRotationVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(
new TIntermBinary(EOpInitialize, getFlipRotation(), CreateUIntNode(0)));
root->insertStatement(0, decl);
}
if (mDrawableWidthVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(
new TIntermBinary(EOpInitialize, getDrawableWidth(), CreateFloatNode(0)));
root->insertStatement(0, decl);
}
if (mDrawableHeightVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(
new TIntermBinary(EOpInitialize, getDrawableHeight(), CreateFloatNode(0)));
root->insertStatement(1, decl);
}
}
TIntermSymbol *SpecConst::getLineRasterEmulation()
{
if ((mCompileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION) == 0)
{
return nullptr;
}
if (mLineRasterEmulationVar == nullptr)
{
const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool>(),
vk::SpecializationConstantId::LineRasterEmulation);
mLineRasterEmulationVar = new TVariable(mSymbolTable, kLineRasterEmulationSpecConstVarName,
type, SymbolType::AngleInternal);
mUsageBits.set(vk::SpecConstUsage::LineRasterEmulation);
}
return new TIntermSymbol(mLineRasterEmulationVar);
}
TIntermSymbol *SpecConst::getFlipRotation()
{
if (mSurfaceRotationVar == nullptr)
{
const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt>(),
vk::SpecializationConstantId::SurfaceRotation);
mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mSurfaceRotationVar);
}
TIntermTyped *SpecConst::getMultiplierXForDFdx()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
mUsageBits.set(vk::SpecConstUsage::Rotation);
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdx, 0, 1, getFlipRotation());
}
TIntermTyped *SpecConst::getMultiplierYForDFdx()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
mUsageBits.set(vk::SpecConstUsage::Rotation);
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdx, 1, 1, getFlipRotation());
}
TIntermTyped *SpecConst::getMultiplierXForDFdy()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
mUsageBits.set(vk::SpecConstUsage::Rotation);
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdy, 0, 1, getFlipRotation());
}
TIntermTyped *SpecConst::getMultiplierYForDFdy()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
mUsageBits.set(vk::SpecConstUsage::Rotation);
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdy, 1, 1, getFlipRotation());
}
TIntermTyped *SpecConst::getPreRotationMatrix()
{
if (!(mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT))
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::Rotation);
return GenerateMat2x2ArrayWithIndex(kPreRotationMatrices, getFlipRotation());
}
TIntermTyped *SpecConst::getFragRotationMatrix()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::Rotation);
return GenerateMat2x2ArrayWithIndex(kFragRotationMatrices, getFlipRotation());
}
TIntermTyped *SpecConst::getHalfRenderAreaRotationMatrix()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::Rotation);
return GenerateMat2x2ArrayWithIndex(kHalfRenderAreaRotationMatrices, getFlipRotation());
}
TIntermTyped *SpecConst::getFlipXY()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
return CreateVec2ArrayWithIndex(kFlipXYValue, 1.0, getFlipRotation());
}
TIntermTyped *SpecConst::getNegFlipXY()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
return CreateVec2ArrayWithIndex(kFlipXYValue, -1.0, getFlipRotation());
}
TIntermTyped *SpecConst::getFlipY()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, 1, getFlipRotation());
}
TIntermTyped *SpecConst::getNegFlipY()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::YFlip);
return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, -1, getFlipRotation());
}
TIntermTyped *SpecConst::getFragRotationMultiplyFlipXY()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
constexpr Vec2EnumMap kFragRotationMultiplyFlipXY = {
{{vk::SurfaceRotation::Identity,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Identity)},
{vk::SurfaceRotation::Rotated90Degrees,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CalcFragRotationMultiplyFlipXY(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
mUsageBits.set(vk::SpecConstUsage::YFlip);
mUsageBits.set(vk::SpecConstUsage::Rotation);
return CreateVec2ArrayWithIndex(kFragRotationMultiplyFlipXY, 1.0, getFlipRotation());
}
TIntermSymbol *SpecConst::getDrawableWidth()
{
if (mDrawableWidthVar == nullptr)
{
const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
vk::SpecializationConstantId::DrawableWidth);
mDrawableWidthVar = new TVariable(mSymbolTable, kDrawableWidthSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mDrawableWidthVar);
}
TIntermSymbol *SpecConst::getDrawableHeight()
{
if (mDrawableHeightVar == nullptr)
{
const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
vk::SpecializationConstantId::DrawableHeight);
mDrawableHeightVar = new TVariable(mSymbolTable, kDrawableHeightSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mDrawableHeightVar);
}
TIntermBinary *SpecConst::getHalfRenderArea()
{
if ((mCompileOptions & SH_USE_SPECIALIZATION_CONSTANT) == 0)
{
return nullptr;
}
// vec2 drawableSize(drawableWidth, drawableHeight)
auto vec2Type = new TType(EbtFloat, 2);
TIntermSequence widthHeightArgs;
widthHeightArgs.push_back(getDrawableWidth());
widthHeightArgs.push_back(getDrawableHeight());
TIntermAggregate *drawableSize =
TIntermAggregate::CreateConstructor(*vec2Type, &widthHeightArgs);
// drawableSize * 0.5f
TIntermBinary *halfRenderArea =
new TIntermBinary(EOpVectorTimesScalar, drawableSize, CreateFloatNode(0.5));
mUsageBits.set(vk::SpecConstUsage::DrawableSize);
// drawableSize * 0.5f * halfRenderAreaRotationMatrix (See comment in
// kHalfRenderAreaRotationMatrices)
TIntermBinary *rotatedHalfRenderArea =
new TIntermBinary(EOpMatrixTimesVector, getHalfRenderAreaRotationMatrix(), halfRenderArea);
return rotatedHalfRenderArea;
}
} // namespace sh