Commit 47b3db22 by Charlie Lao Committed by Commit Bot

Vulkan: Let shader use rotation specialized constant

If use rotation specialized constant is enabled via compiler options, this CL will use rotation specialized constant to generate flipXY, rotation matrix and negFlipXY. This allows the driver to optimize for the minimum instructions for rotation. Bug: b/171750979 Change-Id: I9851ac999d4d35b9f230f796e5445bca0dcb1e77 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2514773 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 8a90378c
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 239 #define ANGLE_SH_VERSION 240
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -341,6 +341,9 @@ const ShCompileOptions SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION = UINT64_C(1) << 55; ...@@ -341,6 +341,9 @@ const ShCompileOptions SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION = UINT64_C(1) << 55;
// Allow compiler to insert Android pre-rotation code. // Allow compiler to insert Android pre-rotation code.
const ShCompileOptions SH_ADD_PRE_ROTATION = UINT64_C(1) << 56; const ShCompileOptions SH_ADD_PRE_ROTATION = UINT64_C(1) << 56;
// Allow compiler to use specialization constant to do pre-rotation and y flip.
const ShCompileOptions SH_USE_ROTATION_SPECIALIZATION_CONSTANT = UINT64_C(1) << 57;
// Defines alternate strategies for implementing array index clamping. // Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy enum ShArrayIndexClampingStrategy
{ {
...@@ -780,6 +783,21 @@ enum class SpecializationConstantId : uint32_t ...@@ -780,6 +783,21 @@ enum class SpecializationConstantId : uint32_t
EnumCount = InvalidEnum, EnumCount = InvalidEnum,
}; };
enum class SurfaceRotation : uint32_t
{
Identity,
Rotated90Degrees,
Rotated180Degrees,
Rotated270Degrees,
FlippedIdentity,
FlippedRotated90Degrees,
FlippedRotated180Degrees,
FlippedRotated270Degrees,
InvalidEnum,
EnumCount = InvalidEnum,
};
// Interface block name containing the aggregate default uniforms // Interface block name containing the aggregate default uniforms
extern const char kDefaultUniformsNameVS[]; extern const char kDefaultUniformsNameVS[];
extern const char kDefaultUniformsNameTCS[]; extern const char kDefaultUniformsNameTCS[];
......
...@@ -216,6 +216,8 @@ angle_translator_sources = [ ...@@ -216,6 +216,8 @@ angle_translator_sources = [
"src/compiler/translator/tree_util/FindMain.h", "src/compiler/translator/tree_util/FindMain.h",
"src/compiler/translator/tree_util/FindSymbolNode.cpp", "src/compiler/translator/tree_util/FindSymbolNode.cpp",
"src/compiler/translator/tree_util/FindSymbolNode.h", "src/compiler/translator/tree_util/FindSymbolNode.h",
"src/compiler/translator/tree_util/FlipRotateSpecConst.cpp",
"src/compiler/translator/tree_util/FlipRotateSpecConst.h",
"src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp", "src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp",
"src/compiler/translator/tree_util/IntermNodePatternMatcher.h", "src/compiler/translator/tree_util/IntermNodePatternMatcher.h",
"src/compiler/translator/tree_util/IntermNode_util.cpp", "src/compiler/translator/tree_util/IntermNode_util.cpp",
......
...@@ -64,7 +64,7 @@ TIntermBinary *CreateDriverUniformRef(const TVariable *driverUniforms, const cha ...@@ -64,7 +64,7 @@ TIntermBinary *CreateDriverUniformRef(const TVariable *driverUniforms, const cha
ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler, ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler,
TIntermBlock *root, TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
TIntermSwizzle *negFlipY) TIntermTyped *negFlipY)
{ {
// Create a symbol reference to "gl_Position" // Create a symbol reference to "gl_Position"
const TVariable *position = BuiltInVariable::gl_Position(); const TVariable *position = BuiltInVariable::gl_Position();
...@@ -151,7 +151,7 @@ bool TranslatorMetal::translate(TIntermBlock *root, ...@@ -151,7 +151,7 @@ bool TranslatorMetal::translate(TIntermBlock *root,
if (getShaderType() == GL_VERTEX_SHADER) if (getShaderType() == GL_VERTEX_SHADER)
{ {
auto negFlipY = getDriverUniformNegFlipYRef(driverUniforms); TIntermTyped *negFlipY = GetDriverUniformNegFlipYRef(driverUniforms);
// Append gl_Position.y correction to main // Append gl_Position.y correction to main
if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(), negFlipY)) if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(), negFlipY))
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "compiler/translator/BuiltinsWorkaroundGLSL.h" #include "compiler/translator/BuiltinsWorkaroundGLSL.h"
#include "compiler/translator/ImmutableStringBuilder.h" #include "compiler/translator/ImmutableStringBuilder.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/OutputVulkanGLSL.h" #include "compiler/translator/OutputVulkanGLSL.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/tree_ops/FlagSamplersWithTexelFetch.h" #include "compiler/translator/tree_ops/FlagSamplersWithTexelFetch.h"
...@@ -30,6 +31,7 @@ ...@@ -30,6 +31,7 @@
#include "compiler/translator/tree_util/BuiltIn.h" #include "compiler/translator/tree_util/BuiltIn.h"
#include "compiler/translator/tree_util/FindFunction.h" #include "compiler/translator/tree_util/FindFunction.h"
#include "compiler/translator/tree_util/FindMain.h" #include "compiler/translator/tree_util/FindMain.h"
#include "compiler/translator/tree_util/FlipRotateSpecConst.h"
#include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/ReplaceClipDistanceVariable.h" #include "compiler/translator/tree_util/ReplaceClipDistanceVariable.h"
#include "compiler/translator/tree_util/ReplaceVariable.h" #include "compiler/translator/tree_util/ReplaceVariable.h"
...@@ -175,6 +177,7 @@ constexpr gl::ShaderMap<const char *> kDefaultUniformNames = { ...@@ -175,6 +177,7 @@ constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
constexpr ImmutableString kLineRasterEmulationSpecConstVarName = constexpr ImmutableString kLineRasterEmulationSpecConstVarName =
ImmutableString("ANGLELineRasterEmulation"); ImmutableString("ANGLELineRasterEmulation");
/* Driver uniforms */
constexpr const char kViewport[] = "viewport"; constexpr const char kViewport[] = "viewport";
constexpr const char kHalfRenderArea[] = "halfRenderArea"; constexpr const char kHalfRenderArea[] = "halfRenderArea";
constexpr const char kFlipXY[] = "flipXY"; constexpr const char kFlipXY[] = "flipXY";
...@@ -247,13 +250,12 @@ ANGLE_NO_DISCARD bool RotateAndFlipBuiltinVariable(TCompiler *compiler, ...@@ -247,13 +250,12 @@ ANGLE_NO_DISCARD bool RotateAndFlipBuiltinVariable(TCompiler *compiler,
TIntermTyped *rotatedXY; TIntermTyped *rotatedXY;
if (fragRotation) if (fragRotation)
{ {
rotatedXY = new TIntermBinary(EOpMatrixTimesVector, fragRotation->deepCopy(), rotatedXY = new TIntermBinary(EOpMatrixTimesVector, fragRotation, builtinXY);
builtinXY->deepCopy());
} }
else else
{ {
// No rotation applied, use original variable. // No rotation applied, use original variable.
rotatedXY = builtinXY->deepCopy(); rotatedXY = builtinXY;
} }
// Create the expression "(builtin.xy - pivot) * flipXY + pivot // Create the expression "(builtin.xy - pivot) * flipXY + pivot
...@@ -331,8 +333,8 @@ ANGLE_NO_DISCARD bool AppendVertexShaderDepthCorrectionToMain(TCompiler *compile ...@@ -331,8 +333,8 @@ ANGLE_NO_DISCARD bool AppendVertexShaderDepthCorrectionToMain(TCompiler *compile
TIntermSwizzle *positionW = new TIntermSwizzle(positionRef->deepCopy(), swizzleOffsetW); TIntermSwizzle *positionW = new TIntermSwizzle(positionRef->deepCopy(), swizzleOffsetW);
// Create the expression "(gl_Position.z + gl_Position.w) * 0.5". // Create the expression "(gl_Position.z + gl_Position.w) * 0.5".
TIntermBinary *zPlusW = new TIntermBinary(EOpAdd, positionZ->deepCopy(), positionW->deepCopy()); TIntermBinary *zPlusW = new TIntermBinary(EOpAdd, positionZ, positionW);
TIntermBinary *halfZPlusW = new TIntermBinary(EOpMul, zPlusW, oneHalf->deepCopy()); TIntermBinary *halfZPlusW = new TIntermBinary(EOpMul, zPlusW, oneHalf);
// Create the assignment "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5" // Create the assignment "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5"
TIntermTyped *positionZLHS = positionZ->deepCopy(); TIntermTyped *positionZLHS = positionZ->deepCopy();
...@@ -352,16 +354,20 @@ ANGLE_NO_DISCARD bool AppendVertexShaderDepthCorrectionToMain(TCompiler *compile ...@@ -352,16 +354,20 @@ ANGLE_NO_DISCARD bool AppendVertexShaderDepthCorrectionToMain(TCompiler *compile
ANGLE_NO_DISCARD bool AppendPreRotation(TCompiler *compiler, ANGLE_NO_DISCARD bool AppendPreRotation(TCompiler *compiler,
TIntermBlock *root, TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
FlipRotateSpecConst *rotationSpecConst,
const TVariable *driverUniforms) const TVariable *driverUniforms)
{ {
TIntermBinary *preRotationRef = CreateDriverUniformRef(driverUniforms, kPreRotation); TIntermTyped *preRotationRef = rotationSpecConst->getPreRotationMatrix();
TIntermSymbol *glPos = new TIntermSymbol(BuiltInVariable::gl_Position()); if (!preRotationRef)
TVector<int> swizzleOffsetXY = {0, 1}; {
TIntermSwizzle *glPosXY = new TIntermSwizzle(glPos, swizzleOffsetXY); preRotationRef = TranslatorVulkan::GetDriverUniformPreRotationMatrixRef(driverUniforms);
}
TIntermSymbol *glPos = new TIntermSymbol(BuiltInVariable::gl_Position());
TVector<int> swizzleOffsetXY = {0, 1};
TIntermSwizzle *glPosXY = new TIntermSwizzle(glPos, swizzleOffsetXY);
// Create the expression "(gl_Position.xy * preRotation)" // Create the expression "(gl_Position.xy * preRotation)"
TIntermBinary *zRotated = TIntermBinary *zRotated = new TIntermBinary(EOpMatrixTimesVector, preRotationRef, glPosXY);
new TIntermBinary(EOpMatrixTimesVector, preRotationRef->deepCopy(), glPosXY->deepCopy());
// Create the assignment "gl_Position.xy = (gl_Position.xy * preRotation)" // Create the assignment "gl_Position.xy = (gl_Position.xy * preRotation)"
TIntermBinary *assignment = TIntermBinary *assignment =
...@@ -586,13 +592,24 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler, ...@@ -586,13 +592,24 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
TIntermBlock *root, TIntermBlock *root,
TIntermSequence *insertSequence, TIntermSequence *insertSequence,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
FlipRotateSpecConst *rotationSpecConst,
const TVariable *driverUniforms) const TVariable *driverUniforms)
{ {
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY); TIntermTyped *flipXY = rotationSpecConst->getFlipXY();
TIntermBinary *pivot = CreateDriverUniformRef(driverUniforms, kHalfRenderArea); if (!flipXY)
TIntermBinary *fragRotation = (compileOptions & SH_ADD_PRE_ROTATION) {
? CreateDriverUniformRef(driverUniforms, kFragRotation) flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY);
: nullptr; }
TIntermBinary *pivot = CreateDriverUniformRef(driverUniforms, kHalfRenderArea);
TIntermTyped *fragRotation = nullptr;
if (compileOptions & SH_ADD_PRE_ROTATION)
{
fragRotation = rotationSpecConst->getFragRotationMatrix();
if (!fragRotation)
{
fragRotation = CreateDriverUniformRef(driverUniforms, kFragRotation);
}
}
return RotateAndFlipBuiltinVariable(compiler, root, insertSequence, flipXY, symbolTable, return RotateAndFlipBuiltinVariable(compiler, root, insertSequence, flipXY, symbolTable,
BuiltInVariable::gl_FragCoord(), kFlippedFragCoordName, BuiltInVariable::gl_FragCoord(), kFlippedFragCoordName,
pivot, fragRotation); pivot, fragRotation);
...@@ -636,6 +653,7 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler, ...@@ -636,6 +653,7 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
TInfoSinkBase &sink, TInfoSinkBase &sink,
TIntermBlock *root, TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
FlipRotateSpecConst *rotationSpecConst,
const TVariable *driverUniforms, const TVariable *driverUniforms,
bool usesFragCoord) bool usesFragCoord)
{ {
...@@ -734,7 +752,7 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler, ...@@ -734,7 +752,7 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
if (!usesFragCoord) if (!usesFragCoord)
{ {
if (!InsertFragCoordCorrection(compiler, compileOptions, root, emulationSequence, if (!InsertFragCoordCorrection(compiler, compileOptions, root, emulationSequence,
symbolTable, driverUniforms)) symbolTable, rotationSpecConst, driverUniforms))
{ {
return false; return false;
} }
...@@ -742,7 +760,6 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler, ...@@ -742,7 +760,6 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
return compiler->validateAST(root); return compiler->validateAST(root);
} }
} // anonymous namespace } // anonymous namespace
TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec) TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
...@@ -871,6 +888,13 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -871,6 +888,13 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
sink << "};\n"; sink << "};\n";
} }
FlipRotateSpecConst surfaceRotationSpecConst;
if (getShaderType() != GL_COMPUTE_SHADER &&
(compileOptions & SH_USE_ROTATION_SPECIALIZATION_CONSTANT))
{
surfaceRotationSpecConst.generateSymbol(&getSymbolTable());
}
const TVariable *driverUniforms; const TVariable *driverUniforms;
if (getShaderType() == GL_COMPUTE_SHADER) if (getShaderType() == GL_COMPUTE_SHADER)
{ {
...@@ -954,7 +978,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -954,7 +978,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION) if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION)
{ {
if (!AddBresenhamEmulationFS(this, compileOptions, sink, root, &getSymbolTable(), if (!AddBresenhamEmulationFS(this, compileOptions, sink, root, &getSymbolTable(),
driverUniforms, usesFragCoord)) &surfaceRotationSpecConst, driverUniforms, usesFragCoord))
{ {
return false; return false;
} }
...@@ -991,11 +1015,22 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -991,11 +1015,22 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (usesPointCoord) if (usesPointCoord)
{ {
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kNegFlipXY); TIntermTyped *flipNegXY = surfaceRotationSpecConst.getNegFlipXY();
if (!flipNegXY)
{
flipNegXY = CreateDriverUniformRef(driverUniforms, kNegFlipXY);
}
TIntermConstantUnion *pivot = CreateFloatNode(0.5f); TIntermConstantUnion *pivot = CreateFloatNode(0.5f);
TIntermBinary *fragRotation = TIntermTyped *fragRotation = nullptr;
usePreRotation ? CreateDriverUniformRef(driverUniforms, kFragRotation) : nullptr; if (usePreRotation)
if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipXY, {
fragRotation = surfaceRotationSpecConst.getFragRotationMatrix();
if (!fragRotation)
{
fragRotation = CreateDriverUniformRef(driverUniforms, kFragRotation);
}
}
if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipNegXY,
&getSymbolTable(), BuiltInVariable::gl_PointCoord(), &getSymbolTable(), BuiltInVariable::gl_PointCoord(),
kFlippedPointCoordName, pivot, fragRotation)) kFlippedPointCoordName, pivot, fragRotation))
{ {
...@@ -1006,21 +1041,17 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -1006,21 +1041,17 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (usesFragCoord) if (usesFragCoord)
{ {
if (!InsertFragCoordCorrection(this, compileOptions, root, GetMainSequence(root), if (!InsertFragCoordCorrection(this, compileOptions, root, GetMainSequence(root),
&getSymbolTable(), driverUniforms)) &getSymbolTable(), &surfaceRotationSpecConst,
driverUniforms))
{ {
return false; return false;
} }
} }
if (!RewriteDfdy(this, compileOptions, root, getSymbolTable(), getShaderVersion(),
&surfaceRotationSpecConst, driverUniforms))
{ {
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY); return false;
TIntermBinary *fragRotation =
usePreRotation ? CreateDriverUniformRef(driverUniforms, kFragRotation) : nullptr;
if (!RewriteDfdy(this, root, getSymbolTable(), getShaderVersion(), flipXY,
fragRotation))
{
return false;
}
} }
{ {
...@@ -1082,7 +1113,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -1082,7 +1113,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
return false; return false;
} }
if ((compileOptions & SH_ADD_PRE_ROTATION) != 0 && if ((compileOptions & SH_ADD_PRE_ROTATION) != 0 &&
!AppendPreRotation(this, root, &getSymbolTable(), driverUniforms)) !AppendPreRotation(this, root, &getSymbolTable(), &surfaceRotationSpecConst,
driverUniforms))
{ {
return false; return false;
} }
...@@ -1099,6 +1131,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -1099,6 +1131,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
EmitWorkGroupSizeGLSL(*this, sink); EmitWorkGroupSizeGLSL(*this, sink);
} }
surfaceRotationSpecConst.outputLayoutString(sink);
if (!validateAST(root)) if (!validateAST(root))
{ {
return false; return false;
...@@ -1147,7 +1181,7 @@ bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll() ...@@ -1147,7 +1181,7 @@ bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
return false; return false;
} }
TIntermSwizzle *TranslatorVulkan::getDriverUniformNegFlipYRef(const TVariable *driverUniforms) const TIntermTyped *TranslatorVulkan::GetDriverUniformNegFlipYRef(const TVariable *driverUniforms)
{ {
// Create a swizzle to "negFlipXY.y" // Create a swizzle to "negFlipXY.y"
TIntermBinary *negFlipXY = CreateDriverUniformRef(driverUniforms, kNegFlipXY); TIntermBinary *negFlipXY = CreateDriverUniformRef(driverUniforms, kNegFlipXY);
...@@ -1164,4 +1198,21 @@ TIntermBinary *TranslatorVulkan::getDriverUniformDepthRangeReservedFieldRef( ...@@ -1164,4 +1198,21 @@ TIntermBinary *TranslatorVulkan::getDriverUniformDepthRangeReservedFieldRef(
return new TIntermBinary(EOpIndexDirectStruct, depthRange, CreateIndexNode(3)); return new TIntermBinary(EOpIndexDirectStruct, depthRange, CreateIndexNode(3));
} }
TIntermTyped *TranslatorVulkan::GetDriverUniformFlipXYRef(const TVariable *driverUniforms)
{
return CreateDriverUniformRef(driverUniforms, kFlipXY);
}
TIntermTyped *TranslatorVulkan::GetDriverUniformFragRotationMatrixRef(
const TVariable *driverUniforms)
{
return CreateDriverUniformRef(driverUniforms, kFragRotation);
}
TIntermTyped *TranslatorVulkan::GetDriverUniformPreRotationMatrixRef(
const TVariable *driverUniforms)
{
return CreateDriverUniformRef(driverUniforms, kPreRotation);
}
} // namespace sh } // namespace sh
...@@ -24,15 +24,20 @@ class TranslatorVulkan : public TCompiler ...@@ -24,15 +24,20 @@ class TranslatorVulkan : public TCompiler
public: public:
TranslatorVulkan(sh::GLenum type, ShShaderSpec spec); TranslatorVulkan(sh::GLenum type, ShShaderSpec spec);
static TIntermTyped *GetDriverUniformFlipXYRef(const TVariable *driverUniforms);
static TIntermTyped *GetDriverUniformNegFlipYRef(const TVariable *driverUniforms);
static TIntermTyped *GetDriverUniformFragRotationMatrixRef(const TVariable *driverUniforms);
static TIntermTyped *GetDriverUniformPreRotationMatrixRef(const TVariable *driverUniforms);
protected: protected:
ANGLE_NO_DISCARD bool translate(TIntermBlock *root, ANGLE_NO_DISCARD bool translate(TIntermBlock *root,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
PerformanceDiagnostics *perfDiagnostics) override; PerformanceDiagnostics *perfDiagnostics) override;
bool shouldFlattenPragmaStdglInvariantAll() override; bool shouldFlattenPragmaStdglInvariantAll() override;
TIntermSwizzle *getDriverUniformNegFlipYRef(const TVariable *driverUniforms) const;
TIntermBinary *getDriverUniformDepthRangeReservedFieldRef( TIntermBinary *getDriverUniformDepthRangeReservedFieldRef(
const TVariable *driverUniforms) const; const TVariable *driverUniforms) const;
// Subclass can call this method to transform the AST before writing the final output. // Subclass can call this method to transform the AST before writing the final output.
// See TranslatorMetal.cpp. // See TranslatorMetal.cpp.
ANGLE_NO_DISCARD bool translateImpl(TIntermBlock *root, ANGLE_NO_DISCARD bool translateImpl(TIntermBlock *root,
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/TranslatorVulkan.h"
#include "compiler/translator/tree_util/FlipRotateSpecConst.h"
#include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
...@@ -24,44 +26,54 @@ class Traverser : public TIntermTraverser ...@@ -24,44 +26,54 @@ class Traverser : public TIntermTraverser
{ {
public: public:
ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler, ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
TIntermBinary *flipXY, FlipRotateSpecConst *rotationSpecConst,
TIntermTyped *fragRotation); const TVariable *driverUniforms);
private: private:
Traverser(TIntermBinary *flipXY, TIntermTyped *fragRotation, TSymbolTable *symbolTable); Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions,
FlipRotateSpecConst *rotationSpecConst,
const TVariable *driverUniforms);
bool visitUnary(Visit visit, TIntermUnary *node) override; bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitUnaryWithRotation(Visit visit, TIntermUnary *node); bool visitUnaryWithRotation(Visit visit, TIntermUnary *node);
bool visitUnaryWithoutRotation(Visit visit, TIntermUnary *node); bool visitUnaryWithoutRotation(Visit visit, TIntermUnary *node);
TIntermBinary *mFlipXY = nullptr; FlipRotateSpecConst *mRotationSpecConst = nullptr;
TIntermTyped *mFragRotation = nullptr; const TVariable *mDriverUniforms = nullptr;
bool mUsePreRotation = false;
}; };
Traverser::Traverser(TIntermBinary *flipXY, TIntermTyped *fragRotation, TSymbolTable *symbolTable) Traverser::Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions,
FlipRotateSpecConst *rotationSpecConst,
const TVariable *driverUniforms)
: TIntermTraverser(true, false, false, symbolTable), : TIntermTraverser(true, false, false, symbolTable),
mFlipXY(flipXY), mRotationSpecConst(rotationSpecConst),
mFragRotation(fragRotation) mDriverUniforms(driverUniforms),
mUsePreRotation(compileOptions & SH_ADD_PRE_ROTATION)
{} {}
// static // static
bool Traverser::Apply(TCompiler *compiler, bool Traverser::Apply(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
TIntermBinary *flipXY, FlipRotateSpecConst *rotationSpecConst,
TIntermTyped *fragRotation) const TVariable *driverUniforms)
{ {
TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable); TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable);
Traverser traverser(flipXY, fragRotation, pSymbolTable); Traverser traverser(pSymbolTable, compileOptions, rotationSpecConst, driverUniforms);
root->traverse(&traverser); root->traverse(&traverser);
return traverser.updateTree(compiler, root); return traverser.updateTree(compiler, root);
} }
bool Traverser::visitUnary(Visit visit, TIntermUnary *node) bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
{ {
if (mFragRotation) if (mUsePreRotation)
{ {
return visitUnaryWithRotation(visit, node); return visitUnaryWithRotation(visit, node);
} }
...@@ -102,36 +114,52 @@ bool Traverser::visitUnaryWithRotation(Visit visit, TIntermUnary *node) ...@@ -102,36 +114,52 @@ bool Traverser::visitUnaryWithRotation(Visit visit, TIntermUnary *node)
// //
// correctedDfdx(operand) = dFdy(operand) * mFlipXY.y // correctedDfdx(operand) = dFdy(operand) * mFlipXY.y
// correctedDfdy(operand) = dFdx(operand) * mFlipXY.x // correctedDfdy(operand) = dFdx(operand) * mFlipXY.x
//
// TODO(ianelliott): Look at the performance of this approach and potentially optimize it
// http://anglebug.com/4678
// Get a vec2 with the correct half of ANGLEUniforms.fragRotation TIntermTyped *multiplierX;
TIntermBinary *halfRotationMat = nullptr; TIntermTyped *multiplierY;
if (node->getOp() == EOpDFdx) if (node->getOp() == EOpDFdx)
{ {
halfRotationMat = multiplierX = mRotationSpecConst->getMultiplierXForDFdx();
new TIntermBinary(EOpIndexDirect, mFragRotation->deepCopy(), CreateIndexNode(0)); multiplierY = mRotationSpecConst->getMultiplierYForDFdx();
} }
else else
{ {
halfRotationMat = multiplierX = mRotationSpecConst->getMultiplierXForDFdy();
new TIntermBinary(EOpIndexDirect, mFragRotation->deepCopy(), CreateIndexNode(1)); multiplierY = mRotationSpecConst->getMultiplierYForDFdy();
} }
// Multiply halfRotationMat by ANGLEUniforms.flipXY and store in a temporary variable if (!multiplierX)
TIntermBinary *rotatedFlipXY = new TIntermBinary(EOpMul, mFlipXY->deepCopy(), halfRotationMat); {
const TType *vec2Type = StaticType::GetBasic<EbtFloat, 2>(); ASSERT(!multiplierY);
TIntermSymbol *tmpRotFlipXY = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec2Type)); TIntermTyped *flipXY = TranslatorVulkan::GetDriverUniformFlipXYRef(mDriverUniforms);
TIntermSequence *tmpDecl = new TIntermSequence; TIntermTyped *fragRotation =
tmpDecl->push_back(CreateTempInitDeclarationNode(&tmpRotFlipXY->variable(), rotatedFlipXY)); TranslatorVulkan::GetDriverUniformFragRotationMatrixRef(mDriverUniforms);
insertStatementsInParentBlock(*tmpDecl);
// Get a vec2 with the correct half of ANGLEUniforms.fragRotation
// Get the .x and .y swizzles to use as multipliers TIntermBinary *halfRotationMat = nullptr;
TVector<int> swizzleOffsetX = {0}; if (node->getOp() == EOpDFdx)
TVector<int> swizzleOffsetY = {1}; {
TIntermSwizzle *multiplierX = new TIntermSwizzle(tmpRotFlipXY, swizzleOffsetX); halfRotationMat = new TIntermBinary(EOpIndexDirect, fragRotation, CreateIndexNode(0));
TIntermSwizzle *multiplierY = new TIntermSwizzle(tmpRotFlipXY->deepCopy(), swizzleOffsetY); }
else
{
halfRotationMat = new TIntermBinary(EOpIndexDirect, fragRotation, CreateIndexNode(1));
}
// Multiply halfRotationMat by ANGLEUniforms.flipXY and store in a temporary variable
TIntermBinary *rotatedFlipXY = new TIntermBinary(EOpMul, flipXY, halfRotationMat);
const TType *vec2Type = StaticType::GetBasic<EbtFloat, 2>();
TIntermSymbol *tmpRotFlipXY = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec2Type));
TIntermSequence *tmpDecl = new TIntermSequence;
tmpDecl->push_back(CreateTempInitDeclarationNode(&tmpRotFlipXY->variable(), rotatedFlipXY));
insertStatementsInParentBlock(*tmpDecl);
// Get the .x and .y swizzles to use as multipliers
TVector<int> swizzleOffsetX = {0};
TVector<int> swizzleOffsetY = {1};
multiplierX = new TIntermSwizzle(tmpRotFlipXY, swizzleOffsetX);
multiplierY = new TIntermSwizzle(tmpRotFlipXY->deepCopy(), swizzleOffsetY);
}
// Get the results of dFdx(operand) and dFdy(operand), and multiply them by the swizzles // Get the results of dFdx(operand) and dFdy(operand), and multiply them by the swizzles
TIntermTyped *operand = node->getOperand(); TIntermTyped *operand = node->getOperand();
...@@ -166,8 +194,13 @@ bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node) ...@@ -166,8 +194,13 @@ bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node)
size_t objectSize = node->getType().getObjectSize(); size_t objectSize = node->getType().getObjectSize();
TOperator multiplyOp = (objectSize == 1) ? EOpMul : EOpVectorTimesScalar; TOperator multiplyOp = (objectSize == 1) ? EOpMul : EOpVectorTimesScalar;
TIntermBinary *flipY = TIntermTyped *flipY = mRotationSpecConst->getFlipY();
new TIntermBinary(EOpIndexDirect, mFlipXY->deepCopy(), CreateIndexNode(1)); if (!flipY)
{
TIntermTyped *flipXY = TranslatorVulkan::GetDriverUniformFlipXYRef(mDriverUniforms);
flipY = new TIntermBinary(EOpIndexDirect, flipXY, CreateIndexNode(1));
}
// Correct dFdy()'s value: // Correct dFdy()'s value:
// (dFdy() * mFlipXY.y) // (dFdy() * mFlipXY.y)
TIntermBinary *correctedDfdy = new TIntermBinary(multiplyOp, newDfdy, flipY); TIntermBinary *correctedDfdy = new TIntermBinary(multiplyOp, newDfdy, flipY);
...@@ -177,21 +210,22 @@ bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node) ...@@ -177,21 +210,22 @@ bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node)
return true; return true;
} }
} // anonymous namespace } // anonymous namespace
bool RewriteDfdy(TCompiler *compiler, bool RewriteDfdy(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
TIntermBinary *flipXY, FlipRotateSpecConst *rotationSpecConst,
TIntermTyped *fragRotation) const TVariable *driverUniforms)
{ {
// dFdy is only valid in GLSL 3.0 and later. // dFdy is only valid in GLSL 3.0 and later.
if (shaderVersion < 300) if (shaderVersion < 300)
return true; return true;
return Traverser::Apply(compiler, root, symbolTable, flipXY, fragRotation); return Traverser::Apply(compiler, compileOptions, root, symbolTable, rotationSpecConst,
driverUniforms);
} }
} // namespace sh } // namespace sh
...@@ -14,23 +14,28 @@ ...@@ -14,23 +14,28 @@
#define COMPILER_TRANSLATOR_TREEOPS_FLIP_DFDY_H_ #define COMPILER_TRANSLATOR_TREEOPS_FLIP_DFDY_H_
#include "common/angleutils.h" #include "common/angleutils.h"
#include "compiler/translator/Compiler.h"
namespace sh namespace sh
{ {
class TCompiler; class TCompiler;
class TIntermNode; class TIntermNode;
class TIntermSymbol;
class TIntermBinary; class TIntermBinary;
class TIntermTyped; class TIntermTyped;
class TSymbolTable; class TSymbolTable;
class TVariable;
class FlipRotateSpecConst;
// If fragRotation = nullptr, no rotation will be applied. // If fragRotation = nullptr, no rotation will be applied.
ANGLE_NO_DISCARD bool RewriteDfdy(TCompiler *compiler, ANGLE_NO_DISCARD bool RewriteDfdy(TCompiler *compiler,
ShCompileOptions compileOptions,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
TIntermBinary *flipXY, FlipRotateSpecConst *rotationSpecConst,
TIntermTyped *fragRotation); const TVariable *driverUniforms);
} // namespace sh } // namespace sh
......
//
// 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.
//
// FlipRotationSpecConst.cpp: Add code to generate AST node for flip and rotation matrices and
// vectors.
//
#include "compiler/translator/tree_util/FlipRotateSpecConst.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
{
constexpr ImmutableString kSurfaceRotationSpecConstVarName =
ImmutableString("ANGLESurfaceRotation");
// 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}}}}};
// Returns mat2(m0, m1, m2, m3)
TIntermAggregate *CreateMat2x2(const Mat2x2EnumMap &matrix, vk::SurfaceRotation rotation)
{
auto mat2Type = new TType(EbtFloat, 2, 2);
TIntermSequence *mat2Args = new TIntermSequence();
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 *specConst)
{
auto mat2Type = new TType(EbtFloat, 2, 2);
TType *typeMat2Array = new TType(*mat2Type);
typeMat2Array->makeArray(static_cast<unsigned int>(vk::SurfaceRotation::EnumCount));
TIntermSequence *sequences;
sequences =
new TIntermSequence({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(EOpIndexDirect, array, specConst->deepCopy());
}
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 vec2(flip.x, flip.y) or vec2(flip.x, -flip.y) if negFlipY is true
TIntermAggregate *CreateFlipXY(vk::SurfaceRotation rotation, float yscale)
{
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));
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)
{
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)});
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)
{
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::Rotated90Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CreateRotatedFlipXYValueForDFdx(vk::SurfaceRotation::FlippedRotated270Degrees)}}};
// Returns [flipX*m2, flipY*m3], where [m2 m3] is the second column of kFragRotation matrix.
constexpr Vec2 CreateRotatedFlipXYValueForDFdy(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::Rotated90Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated90Degrees)},
{vk::SurfaceRotation::Rotated180Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated180Degrees)},
{vk::SurfaceRotation::Rotated270Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::Rotated270Degrees)},
{vk::SurfaceRotation::FlippedIdentity,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedIdentity)},
{vk::SurfaceRotation::FlippedRotated90Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated90Degrees)},
{vk::SurfaceRotation::FlippedRotated180Degrees,
CreateRotatedFlipXYValueForDFdy(vk::SurfaceRotation::FlippedRotated180Degrees)},
{vk::SurfaceRotation::FlippedRotated270Degrees,
CreateRotatedFlipXYValueForDFdy(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;
sequences = new TIntermSequence(
{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(EOpIndexDirect, array, rotation->deepCopy());
}
} // anonymous namespace
FlipRotateSpecConst::FlipRotateSpecConst() : mSpecConstSymbol(nullptr), mReferenced(false) {}
FlipRotateSpecConst::~FlipRotateSpecConst()
{
if (mSpecConstSymbol)
{
delete mSpecConstSymbol;
}
}
void FlipRotateSpecConst::generateSymbol(TSymbolTable *symbolTable)
{
TVariable *specConstVar =
new TVariable(symbolTable, kSurfaceRotationSpecConstVarName,
StaticType::GetBasic<EbtUInt>(), SymbolType::AngleInternal);
mSpecConstSymbol = new TIntermSymbol(specConstVar);
}
void FlipRotateSpecConst::outputLayoutString(TInfoSinkBase &sink) const
{
// Only emit specialized const layout string if it has been referenced.
if (mReferenced)
{
sink << "layout(constant_id="
<< static_cast<uint32_t>(vk::SpecializationConstantId::SurfaceRotation)
<< ") const uint " << kSurfaceRotationSpecConstVarName << " = 0;\n\n";
}
}
TIntermTyped *FlipRotateSpecConst::getMultiplierXForDFdx()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdx, 0, 1, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getMultiplierYForDFdx()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdx, 1, 1, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getMultiplierXForDFdy()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdy, 0, 1, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getMultiplierYForDFdy()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFloatArrayWithRotationIndex(kRotatedFlipXYForDFdy, 1, 1, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getPreRotationMatrix()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return GenerateMat2x2ArrayWithIndex(kPreRotationMatrices, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getFragRotationMatrix()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return GenerateMat2x2ArrayWithIndex(kFragRotationMatrices, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getFlipXY()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFlipXYWithIndex(mSpecConstSymbol, 1.0);
}
TIntermTyped *FlipRotateSpecConst::getNegFlipXY()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFlipXYWithIndex(mSpecConstSymbol, -1.0);
}
TIntermTyped *FlipRotateSpecConst::getFlipY()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, 1, mSpecConstSymbol);
}
TIntermTyped *FlipRotateSpecConst::getNegFlipY()
{
if (!mSpecConstSymbol)
{
return nullptr;
}
mReferenced = true;
return CreateFloatArrayWithRotationIndex(kFlipXYValue, 1, -1, mSpecConstSymbol);
}
} // namespace sh
//
// 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.
//
// FlipRotationSpecConst.h: Add code to generate AST node for flip and rotation matrices and
// vectors.
//
#ifndef COMPILER_TRANSLATOR_TREEUTIL_FLIPROTATESPECCONST_H_
#define COMPILER_TRANSLATOR_TREEUTIL_FLIPROTATESPECCONST_H_
#include "common/angleutils.h"
#include "compiler/translator/SymbolTable.h"
class TIntermTyped;
class TIntermSymbol;
class TVariable;
namespace sh
{
class FlipRotateSpecConst
{
public:
FlipRotateSpecConst();
~FlipRotateSpecConst();
TIntermTyped *getMultiplierXForDFdx();
TIntermTyped *getMultiplierYForDFdx();
TIntermTyped *getMultiplierXForDFdy();
TIntermTyped *getMultiplierYForDFdy();
TIntermTyped *getPreRotationMatrix();
TIntermTyped *getFragRotationMatrix();
TIntermTyped *getFlipXY();
TIntermTyped *getNegFlipXY();
TIntermTyped *getFlipY();
TIntermTyped *getNegFlipY();
void generateSymbol(TSymbolTable *symbolTable);
void outputLayoutString(TInfoSinkBase &sink) const;
private:
TIntermSymbol *mSpecConstSymbol;
// True if mSpecConstSymbol has been used
bool mReferenced;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEUTIL_FLIPROTATESPECCONST_H_
...@@ -3127,13 +3127,23 @@ void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState) ...@@ -3127,13 +3127,23 @@ void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState)
mCurrentRotationDrawFramebuffer = mCurrentRotationDrawFramebuffer =
DetermineSurfaceRotation(drawFramebuffer, mCurrentWindowSurface); DetermineSurfaceRotation(drawFramebuffer, mCurrentWindowSurface);
if (mCurrentRotationDrawFramebuffer != mGraphicsPipelineDesc->getSurfaceRotation()) // DetermineSurfaceRotation() does not encode yflip information. Shader code uses
// SurfaceRotation specialization constant to determine yflip as well. We add yflip information
// to the SurfaceRotation here so the shader does yflip properly.
SurfaceRotation rotationAndFlip = mCurrentRotationDrawFramebuffer;
if (isViewportFlipEnabledForDrawFBO())
{
ASSERT(ToUnderlying(rotationAndFlip) < ToUnderlying(SurfaceRotation::FlippedIdentity));
rotationAndFlip = static_cast<SurfaceRotation>(
ToUnderlying(SurfaceRotation::FlippedIdentity) + ToUnderlying(rotationAndFlip));
}
if (rotationAndFlip != mGraphicsPipelineDesc->getSurfaceRotation())
{ {
// surface rotation are specialization constants, which affects program compilation. When // surface rotation are specialization constants, which affects program compilation. When
// rotation changes, we need to update GraphicsPipelineDesc so that the correct pipeline // rotation changes, we need to update GraphicsPipelineDesc so that the correct pipeline
// program object will be retrieved. // program object will be retrieved.
mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition, rotationAndFlip);
mCurrentRotationDrawFramebuffer);
} }
} }
......
...@@ -72,6 +72,9 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte ...@@ -72,6 +72,9 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte
// context state does not allow it // context state does not allow it
compileOptions |= SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION; compileOptions |= SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION;
// Let compiler use specialized constant for pre-rotation.
compileOptions |= SH_USE_ROTATION_SPECIALIZATION_CONSTANT;
if (contextVk->getFeatures().enablePreRotateSurfaces.enabled || if (contextVk->getFeatures().enablePreRotateSurfaces.enabled ||
contextVk->getFeatures().emulatedPrerotation90.enabled || contextVk->getFeatures().emulatedPrerotation90.enabled ||
contextVk->getFeatures().emulatedPrerotation180.enabled || contextVk->getFeatures().emulatedPrerotation180.enabled ||
......
...@@ -359,6 +359,12 @@ ...@@ -359,6 +359,12 @@
4344 VULKAN ANDROID : dEQP-GLES2.functional.fragment_ops.random.62 = FAIL 4344 VULKAN ANDROID : dEQP-GLES2.functional.fragment_ops.random.62 = FAIL
4344 VULKAN ANDROID : dEQP-GLES2.functional.fragment_ops.random.78 = FAIL 4344 VULKAN ANDROID : dEQP-GLES2.functional.fragment_ops.random.78 = FAIL
// Failing on the Pixel2.
172932466 VULKAN PIXEL2ORXL : dEQP-GLES2.functional.shaders.indexing.tmp_array.float_const_write_dynamic_read_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES2.functional.shaders.indexing.tmp_array.vec2_const_write_dynamic_read_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES2.functional.shaders.indexing.tmp_array.vec3_const_write_dynamic_read_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES2.functional.shaders.indexing.tmp_array.vec4_const_write_dynamic_read_vertex = FAIL
// These tests also fail on AMD windows driver as it is not allowed to use emulation due to errors. // These tests also fail on AMD windows driver as it is not allowed to use emulation due to errors.
3243 VULKAN WIN AMD : dEQP-GLES2.functional.shaders.texture_functions.vertex.texturecubelod = FAIL 3243 VULKAN WIN AMD : dEQP-GLES2.functional.shaders.texture_functions.vertex.texturecubelod = FAIL
3243 VULKAN WIN AMD : dEQP-GLES2.functional.texture.mipmap.cube.basic.linear_nearest = FAIL 3243 VULKAN WIN AMD : dEQP-GLES2.functional.texture.mipmap.cube.basic.linear_nearest = FAIL
......
...@@ -292,3 +292,7 @@ ...@@ -292,3 +292,7 @@
// Vulkan Android failures with these formats // Vulkan Android failures with these formats
5277 VULKAN ANDROID : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rgb10_a2* = FAIL 5277 VULKAN ANDROID : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rgb10_a2* = FAIL
5277 VULKAN ANDROID : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rgb9_e5* = FAIL 5277 VULKAN ANDROID : dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_snorm_rgb9_e5* = FAIL
// Skip on Pixel2 to reduce the bots test time so that it won't timeout
172936025 VULKAN PIXEL2ORXL : dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.*.* = SKIP
172936025 VULKAN PIXEL2ORXL : dEQP-GLES31.functional.copy_image.compressed.viewclass_astc*.*.* = SKIP
...@@ -642,6 +642,13 @@ ...@@ -642,6 +642,13 @@
// 161540999 PIXEL2ORXL VULKAN : dEQP-GLES3.functional.fragment_ops.random.35 = FAIL // 161540999 PIXEL2ORXL VULKAN : dEQP-GLES3.functional.fragment_ops.random.35 = FAIL
4344 VULKAN ANDROID : dEQP-GLES3.functional.fragment_ops.random.73 = FAIL 4344 VULKAN ANDROID : dEQP-GLES3.functional.fragment_ops.random.73 = FAIL
// Failing on the Pixel2.
172932466 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.float_128_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.float_64_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.vec4_128_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.vec4_16_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.vec4_32_vertex = FAIL
172932466 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.vec4_64_vertex = FAIL
// Fails only with SwiftShader: // Fails only with SwiftShader:
......
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