Commit 3a1838a1 by Charlie Lao Committed by Commit Bot

Vulkan: Let RewriteInterpolateAtOffset use FlipRotateSpecConst

Instead of using uniform, use flip/rotation specialization constant when available. This allows matrix multiplication calculated at compile time instead of shader execution time. Bug: angleproject:4901 Bug: angleproject:3589 Change-Id: I5a8a82b1cffbbbeba2617cb7e9a0ec38f9984d50 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2530457 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com>
parent 65ee5168
......@@ -914,15 +914,11 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
return false;
}
if (!RewriteInterpolateAtOffset(this, compileOptions, root, getSymbolTable(),
getShaderVersion(), &surfaceRotationSpecConst,
driverUniforms))
{
TIntermBinary *flipXY = driverUniforms->getFlipXYRef();
TIntermBinary *fragRotation =
usePreRotation ? driverUniforms->getFragRotationMatrixRef() : nullptr;
if (!RewriteInterpolateAtOffset(this, root, getSymbolTable(), getShaderVersion(),
flipXY, fragRotation))
{
return false;
}
return false;
}
EmitEarlyFragmentTestsGLSL(*this, sink);
......
......@@ -55,7 +55,7 @@ Traverser::Traverser(TSymbolTable *symbolTable,
: TIntermTraverser(true, false, false, symbolTable),
mRotationSpecConst(rotationSpecConst),
mDriverUniforms(driverUniforms),
mUsePreRotation(compileOptions & SH_ADD_PRE_ROTATION)
mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0)
{}
// static
......
......@@ -11,6 +11,9 @@
#include "common/angleutils.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/TranslatorVulkan.h"
#include "compiler/translator/tree_util/DriverUniform.h"
#include "compiler/translator/tree_util/FlipRotateSpecConst.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
......@@ -24,46 +27,53 @@ class Traverser : public TIntermTraverser
{
public:
ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root,
const TSymbolTable &symbolTable,
TIntermBinary *flipXY,
TIntermTyped *fragRotation,
int ShaderVersion);
int ShaderVersion,
FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
private:
Traverser(TIntermBinary *flipXY,
TIntermTyped *fragRotation,
TSymbolTable *symbolTable,
int shaderVersion);
Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions,
int shaderVersion,
FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
TIntermBinary *mFlipXY = nullptr;
TIntermTyped *mFragRotation = nullptr;
const TSymbolTable *symbolTable = nullptr;
const int shaderVersion;
FlipRotateSpecConst *mRotationSpecConst = nullptr;
const DriverUniform *mDriverUniforms = nullptr;
bool mUsePreRotation = false;
};
Traverser::Traverser(TIntermBinary *flipXY,
TIntermTyped *fragRotation,
TSymbolTable *symbolTable,
int shaderVersion)
Traverser::Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions,
int shaderVersion,
FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
: TIntermTraverser(true, false, false, symbolTable),
mFlipXY(flipXY),
mFragRotation(fragRotation),
symbolTable(symbolTable),
shaderVersion(shaderVersion)
shaderVersion(shaderVersion),
mRotationSpecConst(rotationSpecConst),
mDriverUniforms(driverUniforms),
mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0)
{}
// static
bool Traverser::Apply(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root,
const TSymbolTable &symbolTable,
TIntermBinary *flipXY,
TIntermTyped *fragRotation,
int shaderVersion)
int shaderVersion,
FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
{
TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable);
Traverser traverser(flipXY, fragRotation, pSymbolTable, shaderVersion);
Traverser traverser(pSymbolTable, compileOptions, shaderVersion, rotationSpecConst,
driverUniforms);
root->traverse(&traverser);
return traverser.updateTree(compiler, root);
}
......@@ -94,14 +104,23 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
// If pre-rotation is enabled apply the transformation else just flip the Y-coordinate
TIntermTyped *rotatedXY;
if (mFragRotation)
if (mUsePreRotation)
{
rotatedXY =
new TIntermBinary(EOpMatrixTimesVector, mFragRotation->deepCopy(), mFlipXY->deepCopy());
rotatedXY = mRotationSpecConst->getFragRotationMultiplyFlipXY();
if (!rotatedXY)
{
TIntermTyped *flipXY = mDriverUniforms->getFlipXYRef();
TIntermTyped *fragRotation = mDriverUniforms->getFragRotationMatrixRef();
rotatedXY = new TIntermBinary(EOpMatrixTimesVector, fragRotation, flipXY);
}
}
else
{
rotatedXY = mFlipXY->deepCopy();
rotatedXY = mRotationSpecConst->getFlipXY();
if (!rotatedXY)
{
rotatedXY = mDriverUniforms->getFlipXYRef();
}
}
TIntermBinary *correctedOffset = new TIntermBinary(EOpMul, offsetNode, rotatedXY);
......@@ -121,11 +140,12 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
} // anonymous namespace
bool RewriteInterpolateAtOffset(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root,
const TSymbolTable &symbolTable,
int shaderVersion,
TIntermBinary *flipXY,
TIntermTyped *fragRotation)
FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
{
// interpolateAtOffset is only valid in GLSL 3.0 and later.
if (shaderVersion < 300)
......@@ -133,7 +153,8 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler,
return true;
}
return Traverser::Apply(compiler, root, symbolTable, flipXY, fragRotation, shaderVersion);
return Traverser::Apply(compiler, compileOptions, root, symbolTable, shaderVersion,
rotationSpecConst, driverUniforms);
}
} // namespace sh
......@@ -27,11 +27,12 @@ class TSymbolTable;
// If fragRotation = nullptr, no rotation will be applied.
ANGLE_NO_DISCARD bool RewriteInterpolateAtOffset(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root,
const TSymbolTable &symbolTable,
int shaderVersion,
TIntermBinary *flipXY,
TIntermTyped *fragRotation);
FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
} // namespace sh
......
......@@ -100,86 +100,96 @@ constexpr Vec2EnumMap kFlipXYValue = {
{vk::SurfaceRotation::FlippedRotated180Degrees, {{1.0f, 1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{-1.0f, -1.0f}}}}};
// Returns vec2(flip.x, flip.y) or vec2(flip.x, -flip.y) if negFlipY is true
TIntermAggregate *CreateFlipXY(vk::SurfaceRotation rotation, float yscale)
// 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 = new TIntermSequence();
vec2Args->push_back(CreateFloatNode(kFlipXYValue[rotation][0]));
vec2Args->push_back(CreateFloatNode(kFlipXYValue[rotation][1] * yscale));
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 *CreateFlipXYWithIndex(TIntermSymbol *rotationSpecConst, float yscale)
TIntermTyped *CreateVec2ArrayWithIndex(Vec2EnumMap vec2Values,
float yscale,
TIntermSymbol *rotationSpecConst)
{
auto vec2Type = new TType(EbtFloat, 2);
TType *typeVec2Array = new TType(*vec2Type);
typeVec2Array->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
TIntermSequence *sequences;
sequences =
new TIntermSequence({CreateFlipXY(vk::SurfaceRotation::Identity, yscale),
CreateFlipXY(vk::SurfaceRotation::Rotated90Degrees, yscale),
CreateFlipXY(vk::SurfaceRotation::Rotated180Degrees, yscale),
CreateFlipXY(vk::SurfaceRotation::Rotated270Degrees, yscale),
CreateFlipXY(vk::SurfaceRotation::FlippedIdentity, yscale),
CreateFlipXY(vk::SurfaceRotation::FlippedRotated90Degrees, yscale),
CreateFlipXY(vk::SurfaceRotation::FlippedRotated180Degrees, yscale),
CreateFlipXY(vk::SurfaceRotation::FlippedRotated270Degrees, yscale)});
sequences = new TIntermSequence(
{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(EOpIndexDirect, vec2Array, rotationSpecConst->deepCopy());
}
// Returns [flipX*m0, flipY*m1], where [m0 m1] is the first column of kFragRotation matrix.
constexpr Vec2 CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation rotation)
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,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Identity)},
{{vk::SurfaceRotation::Identity, CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Identity)},
{vk::SurfaceRotation::Rotated90Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated90Degrees)},
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated180Degrees)},
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated270Degrees)},
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedIdentity)},
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated90Degrees)},
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated180Degrees)},
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
CalcRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
// Returns [flipX*m2, flipY*m3], where [m2 m3] is the second column of kFragRotation matrix.
constexpr Vec2 CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation rotation)
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,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Identity)},
{{vk::SurfaceRotation::Identity, CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Identity)},
{vk::SurfaceRotation::Rotated90Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated90Degrees)},
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated180Degrees)},
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated270Degrees)},
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedIdentity)},
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated90Degrees)},
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated180Degrees)},
CalcRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CreateRotatedFlipXYValueForDFdy(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,
......@@ -306,7 +316,7 @@ TIntermTyped *FlipRotateSpecConst::getFlipXY()
return nullptr;
}
mReferenced = true;
return CreateFlipXYWithIndex(mSpecConstSymbol, 1.0);
return CreateVec2ArrayWithIndex(kFlipXYValue, 1.0, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getNegFlipXY()
......@@ -316,7 +326,7 @@ TIntermTyped *FlipRotateSpecConst::getNegFlipXY()
return nullptr;
}
mReferenced = true;
return CreateFlipXYWithIndex(mSpecConstSymbol, -1.0);
return CreateVec2ArrayWithIndex(kFlipXYValue, -1.0, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getFlipY()
......@@ -339,4 +349,33 @@ TIntermTyped *FlipRotateSpecConst::getNegFlipY()
return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, -1, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getFragRotationMultiplyFlipXY()
{
if (!mSpecConstSymbol)
{
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)}}};
mReferenced = true;
return CreateVec2ArrayWithIndex(kFragRotationMultiplyFlipXY, 1.0, mSpecConstSymbol);
}
} // namespace sh
......@@ -36,6 +36,7 @@ class FlipRotateSpecConst
TIntermTyped *getNegFlipXY();
TIntermTyped *getFlipY();
TIntermTyped *getNegFlipY();
TIntermTyped *getFragRotationMultiplyFlipXY();
void generateSymbol(TSymbolTable *symbolTable);
void outputLayoutString(TInfoSinkBase &sink) const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment