Commit 995493cc by Charlie Lao Committed by Commit Bot

Revert "Vulkan: Remove rotation related data from driver uniform"

This reverts commit fd97c334. Reason for revert: The specialization constant for rotation causes performance regression with older qualcomm driver. We need to keep the driver uniform code path for the older driver. Original change's description: > Vulkan: Remove rotation related data from driver uniform > > Rotation is now handled in the shader compiler with specialization > constant, it should be removed from driver uniforms. Since Metal is > using the flipXY, flipXY/negFlipXY are still kept in the shader side > implementation, but have moved to TranslatorMetal in this CL. > > Bug: b/171750979 > Change-Id: Ie8d15ef227cb52a6e19e4319ecc9f09bda42e667 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2519863 > Reviewed-by: Ian Elliott <ianelliott@google.com> > Reviewed-by: Tim Van Patten <timvp@google.com> > Reviewed-by: Jamie Madill <jmadill@chromium.org> > Commit-Queue: Charlie Lao <cclao@google.com> TBR=ianelliott@google.com,timvp@google.com,jmadill@chromium.org,cclao@google.com Bug: b/171750979 Change-Id: Iff9cffb28851ade1d9c5cd23fde73910a19867ce Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2547808Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
parent 82e25682
...@@ -343,6 +343,9 @@ const ShCompileOptions SH_ADD_PRE_ROTATION = UINT64_C(1) << 56; ...@@ -343,6 +343,9 @@ const ShCompileOptions SH_ADD_PRE_ROTATION = UINT64_C(1) << 56;
const ShCompileOptions SH_FORCE_SHADER_PRECISION_HIGHP_TO_MEDIUMP = UINT64_C(1) << 57; const ShCompileOptions SH_FORCE_SHADER_PRECISION_HIGHP_TO_MEDIUMP = UINT64_C(1) << 57;
// Allow compiler to use specialization constant to do pre-rotation and y flip.
const ShCompileOptions SH_USE_ROTATION_SPECIALIZATION_CONSTANT = UINT64_C(1) << 58;
// Defines alternate strategies for implementing array index clamping. // Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy enum ShArrayIndexClampingStrategy
{ {
......
...@@ -42,16 +42,10 @@ const char kRasterizerDiscardEnabledConstName[] = "ANGLERasterizerDisabled"; ...@@ -42,16 +42,10 @@ const char kRasterizerDiscardEnabledConstName[] = "ANGLERasterizerDisabled";
namespace namespace
{ {
// Metal specific driver uniforms // Metal specific driver uniforms
constexpr const char kFlipXY[] = "flipXY";
constexpr const char kNegFlipXY[] = "negFlipXY";
constexpr const char kCoverageMask[] = "coverageMask"; constexpr const char kCoverageMask[] = "coverageMask";
constexpr ImmutableString kSampleMaskWriteFuncName = ImmutableString("ANGLEWriteSampleMask"); constexpr ImmutableString kSampleMaskWriteFuncName = ImmutableString("ANGLEWriteSampleMask");
constexpr size_t kNumMetalGraphicsDriverUniforms = 3;
constexpr std::array<const char *, kNumMetalGraphicsDriverUniforms>
kMetalGraphicsDriverUniformNames = {{kFlipXY, kNegFlipXY, kCoverageMask}};
// Unlike Vulkan having auto viewport flipping extension, in Metal we have to flip gl_Position.y // Unlike Vulkan having auto viewport flipping extension, in Metal we have to flip gl_Position.y
// manually. // manually.
// This operation performs flipping the gl_Position.y using this expression: // This operation performs flipping the gl_Position.y using this expression:
...@@ -117,73 +111,25 @@ ANGLE_NO_DISCARD bool InitializeUnusedOutputs(TIntermBlock *root, ...@@ -117,73 +111,25 @@ ANGLE_NO_DISCARD bool InitializeUnusedOutputs(TIntermBlock *root,
} }
} // anonymous namespace } // anonymous namespace
// class DriverUniformMetal
TFieldList *DriverUniformMetal::createUniformFields(TSymbolTable *symbolTable) const TFieldList *DriverUniformMetal::createUniformFields(TSymbolTable *symbolTable) const
{ {
TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable); TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable);
const std::array<TType *, kNumMetalGraphicsDriverUniforms> kMetalDriverUniformTypes = {{ // Add coverage mask to driver uniform. Metal doesn't have built-in GL_SAMPLE_COVERAGE_VALUE
new TType(EbtFloat, 2), // flipXY // equivalent functionality, needs to emulate it using fragment shader's [[sample_mask]] output
new TType(EbtFloat, 2), // negFlipXY // value.
new TType(EbtUInt), // kCoverageMask TField *coverageMaskField = new TField(new TType(EbtUInt), ImmutableString(kCoverageMask),
}}; TSourceLoc(), SymbolType::AngleInternal);
driverFieldList->push_back(coverageMaskField);
for (size_t uniformIndex = 0; uniformIndex < kNumMetalGraphicsDriverUniforms; ++uniformIndex)
{
TField *driverUniformField =
new TField(kMetalDriverUniformTypes[uniformIndex],
ImmutableString(kMetalGraphicsDriverUniformNames[uniformIndex]),
TSourceLoc(), SymbolType::AngleInternal);
driverFieldList->push_back(driverUniformField);
}
return driverFieldList; return driverFieldList;
} }
TIntermBinary *DriverUniformMetal::getFlipXYRef() const
{
return createDriverUniformRef(kFlipXY);
}
TIntermBinary *DriverUniformMetal::getNegFlipXYRef() const
{
return createDriverUniformRef(kNegFlipXY);
}
TIntermBinary *DriverUniformMetal::getCoverageMaskFieldRef() const TIntermBinary *DriverUniformMetal::getCoverageMaskFieldRef() const
{ {
return createDriverUniformRef(kCoverageMask); return createDriverUniformRef(kCoverageMask);
} }
TIntermSwizzle *DriverUniformMetal::getNegFlipYRef() const
{
// Create a swizzle to "negFlipXY.y"
TIntermBinary *negFlipXY = createDriverUniformRef(kNegFlipXY);
TVector<int> swizzleOffsetY = {1};
TIntermSwizzle *negFlipY = new TIntermSwizzle(negFlipXY, swizzleOffsetY);
return negFlipY;
}
// class FlipRotateSpecConstMetal
TIntermTyped *FlipRotateSpecConstMetal::getFlipXY()
{
return mDriverUniform->getFlipXYRef();
}
TIntermTyped *FlipRotateSpecConstMetal::getNegFlipXY()
{
return mDriverUniform->getNegFlipXYRef();
}
TIntermTyped *FlipRotateSpecConstMetal::getFlipY()
{
TIntermTyped *flipXY = mDriverUniform->getFlipXYRef();
return new TIntermBinary(EOpIndexDirect, flipXY, CreateIndexNode(1));
}
TIntermTyped *FlipRotateSpecConstMetal::getNegFlipY()
{
return mDriverUniform->getNegFlipYRef();
}
// class TranslaterMetal
TranslatorMetal::TranslatorMetal(sh::GLenum type, ShShaderSpec spec) : TranslatorVulkan(type, spec) TranslatorMetal::TranslatorMetal(sh::GLenum type, ShShaderSpec spec) : TranslatorVulkan(type, spec)
{} {}
...@@ -198,9 +144,8 @@ bool TranslatorMetal::translate(TIntermBlock *root, ...@@ -198,9 +144,8 @@ bool TranslatorMetal::translate(TIntermBlock *root,
getShaderVersion(), getOutputType(), false, true, compileOptions); getShaderVersion(), getOutputType(), false, true, compileOptions);
DriverUniformMetal driverUniforms; DriverUniformMetal driverUniforms;
FlipRotateSpecConstMetal flipRotateSpecConst(&driverUniforms); if (!TranslatorVulkan::translateImpl(root, compileOptions, perfDiagnostics, &driverUniforms,
if (!TranslatorVulkan::translateImpl(root, compileOptions, perfDiagnostics, &outputGLSL))
&flipRotateSpecConst, &driverUniforms, &outputGLSL))
{ {
return false; return false;
} }
...@@ -393,4 +338,5 @@ ANGLE_NO_DISCARD bool TranslatorMetal::insertRasterizerDiscardLogic(TIntermBlock ...@@ -393,4 +338,5 @@ ANGLE_NO_DISCARD bool TranslatorMetal::insertRasterizerDiscardLogic(TIntermBlock
return RunAtTheEndOfShader(this, root, ifCall, symbolTable); return RunAtTheEndOfShader(this, root, ifCall, symbolTable);
} }
} // namespace sh } // namespace sh
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "compiler/translator/TranslatorVulkan.h" #include "compiler/translator/TranslatorVulkan.h"
#include "compiler/translator/tree_util/DriverUniform.h" #include "compiler/translator/tree_util/DriverUniform.h"
#include "compiler/translator/tree_util/FlipRotateSpecConst.h"
namespace sh namespace sh
{ {
...@@ -28,37 +27,12 @@ class DriverUniformMetal : public DriverUniform ...@@ -28,37 +27,12 @@ class DriverUniformMetal : public DriverUniform
DriverUniformMetal() : DriverUniform() {} DriverUniformMetal() : DriverUniform() {}
~DriverUniformMetal() override {} ~DriverUniformMetal() override {}
TIntermBinary *getFlipXYRef() const;
TIntermBinary *getNegFlipXYRef() const;
TIntermSwizzle *getNegFlipYRef() const;
TIntermBinary *getCoverageMaskFieldRef() const; TIntermBinary *getCoverageMaskFieldRef() const;
protected: protected:
TFieldList *createUniformFields(TSymbolTable *symbolTable) const override; TFieldList *createUniformFields(TSymbolTable *symbolTable) const override;
}; };
// TODO: http://anglebug.com/5339 Implement it using actual specialization constant. For now we are
// redirecting to driver uniforms
class FlipRotateSpecConstMetal : public FlipRotateSpecConst
{
public:
FlipRotateSpecConstMetal(DriverUniformMetal *driverUniform)
: FlipRotateSpecConst(), mDriverUniform(driverUniform)
{}
~FlipRotateSpecConstMetal() override {}
TIntermTyped *getFlipXY() override;
TIntermTyped *getNegFlipXY() override;
TIntermTyped *getFlipY() override;
TIntermTyped *getNegFlipY() override;
void generateSymbol(TSymbolTable *symbolTable) override {}
void outputLayoutString(TInfoSinkBase &sink) const override {}
private:
DriverUniformMetal *mDriverUniform;
};
class TranslatorMetal : public TranslatorVulkan class TranslatorMetal : public TranslatorVulkan
{ {
public: public:
......
...@@ -317,9 +317,14 @@ ANGLE_NO_DISCARD bool AppendVertexShaderDepthCorrectionToMain(TCompiler *compile ...@@ -317,9 +317,14 @@ 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) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
{ {
TIntermTyped *preRotationRef = rotationSpecConst->getPreRotationMatrix(); TIntermTyped *preRotationRef = rotationSpecConst->getPreRotationMatrix();
if (!preRotationRef)
{
preRotationRef = driverUniforms->getPreRotationMatrixRef();
}
TIntermSymbol *glPos = new TIntermSymbol(BuiltInVariable::gl_Position()); TIntermSymbol *glPos = new TIntermSymbol(BuiltInVariable::gl_Position());
TVector<int> swizzleOffsetXY = {0, 1}; TVector<int> swizzleOffsetXY = {0, 1};
TIntermSwizzle *glPosXY = new TIntermSwizzle(glPos, swizzleOffsetXY); TIntermSwizzle *glPosXY = new TIntermSwizzle(glPos, swizzleOffsetXY);
...@@ -456,11 +461,21 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler, ...@@ -456,11 +461,21 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
FlipRotateSpecConst *rotationSpecConst, FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms) const DriverUniform *driverUniforms)
{ {
TIntermTyped *flipXY = rotationSpecConst->getFlipXY(); TIntermTyped *flipXY = rotationSpecConst->getFlipXY();
if (!flipXY)
{
flipXY = driverUniforms->getFlipXYRef();
}
TIntermBinary *pivot = driverUniforms->getHalfRenderAreaRef(); TIntermBinary *pivot = driverUniforms->getHalfRenderAreaRef();
TIntermTyped *fragRotation = (compileOptions & SH_ADD_PRE_ROTATION) TIntermTyped *fragRotation = nullptr;
? rotationSpecConst->getFragRotationMatrix() if (compileOptions & SH_ADD_PRE_ROTATION)
: nullptr; {
fragRotation = rotationSpecConst->getFragRotationMatrix();
if (!fragRotation)
{
fragRotation = driverUniforms->getFragRotationMatrixRef();
}
}
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);
...@@ -620,7 +635,6 @@ TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec) ...@@ -620,7 +635,6 @@ TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
bool TranslatorVulkan::translateImpl(TIntermBlock *root, bool TranslatorVulkan::translateImpl(TIntermBlock *root,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
PerformanceDiagnostics * /*perfDiagnostics*/, PerformanceDiagnostics * /*perfDiagnostics*/,
FlipRotateSpecConst *flipRotateSpecConst,
DriverUniform *driverUniforms, DriverUniform *driverUniforms,
TOutputVulkanGLSL *outputGLSL) TOutputVulkanGLSL *outputGLSL)
{ {
...@@ -740,9 +754,11 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -740,9 +754,11 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
sink << "};\n"; sink << "};\n";
} }
if (getShaderType() != GL_COMPUTE_SHADER) FlipRotateSpecConst surfaceRotationSpecConst;
if (getShaderType() != GL_COMPUTE_SHADER &&
(compileOptions & SH_USE_ROTATION_SPECIALIZATION_CONSTANT))
{ {
flipRotateSpecConst->generateSymbol(&getSymbolTable()); surfaceRotationSpecConst.generateSymbol(&getSymbolTable());
} }
if (getShaderType() == GL_COMPUTE_SHADER) if (getShaderType() == GL_COMPUTE_SHADER)
...@@ -822,7 +838,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -822,7 +838,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(),
flipRotateSpecConst, driverUniforms, usesFragCoord)) &surfaceRotationSpecConst, driverUniforms, usesFragCoord))
{ {
return false; return false;
} }
...@@ -859,10 +875,21 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -859,10 +875,21 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (usesPointCoord) if (usesPointCoord)
{ {
TIntermTyped *flipNegXY = flipRotateSpecConst->getNegFlipXY(); TIntermTyped *flipNegXY = surfaceRotationSpecConst.getNegFlipXY();
if (!flipNegXY)
{
flipNegXY = driverUniforms->getNegFlipXYRef();
}
TIntermConstantUnion *pivot = CreateFloatNode(0.5f); TIntermConstantUnion *pivot = CreateFloatNode(0.5f);
TIntermTyped *fragRotation = TIntermTyped *fragRotation = nullptr;
usePreRotation ? flipRotateSpecConst->getFragRotationMatrix() : nullptr; if (usePreRotation)
{
fragRotation = surfaceRotationSpecConst.getFragRotationMatrix();
if (!fragRotation)
{
fragRotation = driverUniforms->getFragRotationMatrixRef();
}
}
if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipNegXY, if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipNegXY,
&getSymbolTable(), BuiltInVariable::gl_PointCoord(), &getSymbolTable(), BuiltInVariable::gl_PointCoord(),
kFlippedPointCoordName, pivot, fragRotation)) kFlippedPointCoordName, pivot, fragRotation))
...@@ -874,20 +901,22 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -874,20 +901,22 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (usesFragCoord) if (usesFragCoord)
{ {
if (!InsertFragCoordCorrection(this, compileOptions, root, GetMainSequence(root), if (!InsertFragCoordCorrection(this, compileOptions, root, GetMainSequence(root),
&getSymbolTable(), flipRotateSpecConst, driverUniforms)) &getSymbolTable(), &surfaceRotationSpecConst,
driverUniforms))
{ {
return false; return false;
} }
} }
if (!RewriteDfdy(this, compileOptions, root, getSymbolTable(), getShaderVersion(), if (!RewriteDfdy(this, compileOptions, root, getSymbolTable(), getShaderVersion(),
flipRotateSpecConst)) &surfaceRotationSpecConst, driverUniforms))
{ {
return false; return false;
} }
if (!RewriteInterpolateAtOffset(this, compileOptions, root, getSymbolTable(), if (!RewriteInterpolateAtOffset(this, compileOptions, root, getSymbolTable(),
getShaderVersion(), flipRotateSpecConst)) getShaderVersion(), &surfaceRotationSpecConst,
driverUniforms))
{ {
return false; return false;
} }
...@@ -940,7 +969,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -940,7 +969,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(), flipRotateSpecConst)) !AppendPreRotation(this, root, &getSymbolTable(), &surfaceRotationSpecConst,
driverUniforms))
{ {
return false; return false;
} }
...@@ -957,7 +987,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -957,7 +987,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
EmitWorkGroupSizeGLSL(*this, sink); EmitWorkGroupSizeGLSL(*this, sink);
} }
flipRotateSpecConst->outputLayoutString(sink); surfaceRotationSpecConst.outputLayoutString(sink);
if (!validateAST(root)) if (!validateAST(root))
{ {
...@@ -986,9 +1016,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root, ...@@ -986,9 +1016,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
enablePrecision, compileOptions); enablePrecision, compileOptions);
DriverUniform driverUniforms; DriverUniform driverUniforms;
FlipRotateSpecConst flipRotateSpecConst; if (!translateImpl(root, compileOptions, perfDiagnostics, &driverUniforms, &outputGLSL))
if (!translateImpl(root, compileOptions, perfDiagnostics, &flipRotateSpecConst, &driverUniforms,
&outputGLSL))
{ {
return false; return false;
} }
......
...@@ -19,7 +19,6 @@ namespace sh ...@@ -19,7 +19,6 @@ namespace sh
class TOutputVulkanGLSL; class TOutputVulkanGLSL;
class DriverUniform; class DriverUniform;
class FlipRotateSpecConst;
class TranslatorVulkan : public TCompiler class TranslatorVulkan : public TCompiler
{ {
...@@ -37,7 +36,6 @@ class TranslatorVulkan : public TCompiler ...@@ -37,7 +36,6 @@ class TranslatorVulkan : public TCompiler
ANGLE_NO_DISCARD bool translateImpl(TIntermBlock *root, ANGLE_NO_DISCARD bool translateImpl(TIntermBlock *root,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
PerformanceDiagnostics *perfDiagnostics, PerformanceDiagnostics *perfDiagnostics,
FlipRotateSpecConst *flipRotateSpecConst,
DriverUniform *driverUniforms, DriverUniform *driverUniforms,
TOutputVulkanGLSL *outputGLSL); TOutputVulkanGLSL *outputGLSL);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#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/DriverUniform.h" #include "compiler/translator/tree_util/DriverUniform.h"
#include "compiler/translator/tree_util/FlipRotateSpecConst.h" #include "compiler/translator/tree_util/FlipRotateSpecConst.h"
#include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
...@@ -29,26 +30,31 @@ class Traverser : public TIntermTraverser ...@@ -29,26 +30,31 @@ class Traverser : public TIntermTraverser
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
FlipRotateSpecConst *rotationSpecConst); FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
private: private:
Traverser(TSymbolTable *symbolTable, Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
FlipRotateSpecConst *rotationSpecConst); FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *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);
FlipRotateSpecConst *mRotationSpecConst = nullptr; FlipRotateSpecConst *mRotationSpecConst = nullptr;
const DriverUniform *mDriverUniforms = nullptr;
bool mUsePreRotation = false; bool mUsePreRotation = false;
}; };
Traverser::Traverser(TSymbolTable *symbolTable, Traverser::Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
FlipRotateSpecConst *rotationSpecConst) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
: TIntermTraverser(true, false, false, symbolTable), : TIntermTraverser(true, false, false, symbolTable),
mRotationSpecConst(rotationSpecConst), mRotationSpecConst(rotationSpecConst),
mDriverUniforms(driverUniforms),
mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0) mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0)
{} {}
...@@ -57,10 +63,11 @@ bool Traverser::Apply(TCompiler *compiler, ...@@ -57,10 +63,11 @@ bool Traverser::Apply(TCompiler *compiler,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
FlipRotateSpecConst *rotationSpecConst) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
{ {
TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable); TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable);
Traverser traverser(pSymbolTable, compileOptions, rotationSpecConst); Traverser traverser(pSymbolTable, compileOptions, rotationSpecConst, driverUniforms);
root->traverse(&traverser); root->traverse(&traverser);
return traverser.updateTree(compiler, root); return traverser.updateTree(compiler, root);
} }
...@@ -122,6 +129,38 @@ bool Traverser::visitUnaryWithRotation(Visit visit, TIntermUnary *node) ...@@ -122,6 +129,38 @@ bool Traverser::visitUnaryWithRotation(Visit visit, TIntermUnary *node)
multiplierY = mRotationSpecConst->getMultiplierYForDFdy(); multiplierY = mRotationSpecConst->getMultiplierYForDFdy();
} }
if (!multiplierX)
{
ASSERT(!multiplierY);
TIntermTyped *flipXY = mDriverUniforms->getFlipXYRef();
TIntermTyped *fragRotation = mDriverUniforms->getFragRotationMatrixRef();
// Get a vec2 with the correct half of ANGLEUniforms.fragRotation
TIntermBinary *halfRotationMat = nullptr;
if (node->getOp() == EOpDFdx)
{
halfRotationMat = new TIntermBinary(EOpIndexDirect, fragRotation, CreateIndexNode(0));
}
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();
TIntermUnary *dFdx = new TIntermUnary(EOpDFdx, operand->deepCopy(), node->getFunction()); TIntermUnary *dFdx = new TIntermUnary(EOpDFdx, operand->deepCopy(), node->getFunction());
...@@ -156,6 +195,11 @@ bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node) ...@@ -156,6 +195,11 @@ bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node)
TOperator multiplyOp = (objectSize == 1) ? EOpMul : EOpVectorTimesScalar; TOperator multiplyOp = (objectSize == 1) ? EOpMul : EOpVectorTimesScalar;
TIntermTyped *flipY = mRotationSpecConst->getFlipY(); TIntermTyped *flipY = mRotationSpecConst->getFlipY();
if (!flipY)
{
TIntermTyped *flipXY = mDriverUniforms->getFlipXYRef();
flipY = new TIntermBinary(EOpIndexDirect, flipXY, CreateIndexNode(1));
}
// Correct dFdy()'s value: // Correct dFdy()'s value:
// (dFdy() * mFlipXY.y) // (dFdy() * mFlipXY.y)
...@@ -173,13 +217,15 @@ bool RewriteDfdy(TCompiler *compiler, ...@@ -173,13 +217,15 @@ bool RewriteDfdy(TCompiler *compiler,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *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, compileOptions, root, symbolTable, rotationSpecConst); return Traverser::Apply(compiler, compileOptions, root, symbolTable, rotationSpecConst,
driverUniforms);
} }
} // namespace sh } // namespace sh
...@@ -35,7 +35,8 @@ ANGLE_NO_DISCARD bool RewriteDfdy(TCompiler *compiler, ...@@ -35,7 +35,8 @@ ANGLE_NO_DISCARD bool RewriteDfdy(TCompiler *compiler,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst); FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
} // namespace sh } // namespace sh
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#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/DriverUniform.h" #include "compiler/translator/tree_util/DriverUniform.h"
#include "compiler/translator/tree_util/FlipRotateSpecConst.h" #include "compiler/translator/tree_util/FlipRotateSpecConst.h"
#include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
...@@ -30,29 +31,34 @@ class Traverser : public TIntermTraverser ...@@ -30,29 +31,34 @@ class Traverser : public TIntermTraverser
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int ShaderVersion, int ShaderVersion,
FlipRotateSpecConst *rotationSpecConst); FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
private: private:
Traverser(TSymbolTable *symbolTable, Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst); FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
const TSymbolTable *symbolTable = nullptr; const TSymbolTable *symbolTable = nullptr;
const int shaderVersion; const int shaderVersion;
FlipRotateSpecConst *mRotationSpecConst = nullptr; FlipRotateSpecConst *mRotationSpecConst = nullptr;
const DriverUniform *mDriverUniforms = nullptr;
bool mUsePreRotation = false; bool mUsePreRotation = false;
}; };
Traverser::Traverser(TSymbolTable *symbolTable, Traverser::Traverser(TSymbolTable *symbolTable,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
: TIntermTraverser(true, false, false, symbolTable), : TIntermTraverser(true, false, false, symbolTable),
symbolTable(symbolTable), symbolTable(symbolTable),
shaderVersion(shaderVersion), shaderVersion(shaderVersion),
mRotationSpecConst(rotationSpecConst), mRotationSpecConst(rotationSpecConst),
mDriverUniforms(driverUniforms),
mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0) mUsePreRotation((compileOptions & SH_ADD_PRE_ROTATION) != 0)
{} {}
...@@ -62,10 +68,12 @@ bool Traverser::Apply(TCompiler *compiler, ...@@ -62,10 +68,12 @@ bool Traverser::Apply(TCompiler *compiler,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
{ {
TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable); TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable);
Traverser traverser(pSymbolTable, compileOptions, shaderVersion, rotationSpecConst); Traverser traverser(pSymbolTable, compileOptions, shaderVersion, rotationSpecConst,
driverUniforms);
root->traverse(&traverser); root->traverse(&traverser);
return traverser.updateTree(compiler, root); return traverser.updateTree(compiler, root);
} }
...@@ -95,8 +103,25 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -95,8 +103,25 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
ASSERT(offsetNode->getType() == *(StaticType::GetBasic<EbtFloat, 2>())); ASSERT(offsetNode->getType() == *(StaticType::GetBasic<EbtFloat, 2>()));
// If pre-rotation is enabled apply the transformation else just flip the Y-coordinate // If pre-rotation is enabled apply the transformation else just flip the Y-coordinate
TIntermTyped *rotatedXY = mUsePreRotation ? mRotationSpecConst->getFragRotationMultiplyFlipXY() TIntermTyped *rotatedXY;
: mRotationSpecConst->getFlipXY(); if (mUsePreRotation)
{
rotatedXY = mRotationSpecConst->getFragRotationMultiplyFlipXY();
if (!rotatedXY)
{
TIntermTyped *flipXY = mDriverUniforms->getFlipXYRef();
TIntermTyped *fragRotation = mDriverUniforms->getFragRotationMatrixRef();
rotatedXY = new TIntermBinary(EOpMatrixTimesVector, fragRotation, flipXY);
}
}
else
{
rotatedXY = mRotationSpecConst->getFlipXY();
if (!rotatedXY)
{
rotatedXY = mDriverUniforms->getFlipXYRef();
}
}
TIntermBinary *correctedOffset = new TIntermBinary(EOpMul, offsetNode, rotatedXY); TIntermBinary *correctedOffset = new TIntermBinary(EOpMul, offsetNode, rotatedXY);
correctedOffset->setLine(offsetNode->getLine()); correctedOffset->setLine(offsetNode->getLine());
...@@ -119,7 +144,8 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler, ...@@ -119,7 +144,8 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst) FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms)
{ {
// interpolateAtOffset is only valid in GLSL 3.0 and later. // interpolateAtOffset is only valid in GLSL 3.0 and later.
if (shaderVersion < 300) if (shaderVersion < 300)
...@@ -128,7 +154,7 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler, ...@@ -128,7 +154,7 @@ bool RewriteInterpolateAtOffset(TCompiler *compiler,
} }
return Traverser::Apply(compiler, compileOptions, root, symbolTable, shaderVersion, return Traverser::Apply(compiler, compileOptions, root, symbolTable, shaderVersion,
rotationSpecConst); rotationSpecConst, driverUniforms);
} }
} // namespace sh } // namespace sh
...@@ -31,7 +31,8 @@ ANGLE_NO_DISCARD bool RewriteInterpolateAtOffset(TCompiler *compiler, ...@@ -31,7 +31,8 @@ ANGLE_NO_DISCARD bool RewriteInterpolateAtOffset(TCompiler *compiler,
TIntermNode *root, TIntermNode *root,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
FlipRotateSpecConst *rotationSpecConst); FlipRotateSpecConst *rotationSpecConst,
const DriverUniform *driverUniforms);
} // namespace sh } // namespace sh
......
...@@ -26,17 +26,22 @@ constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDept ...@@ -26,17 +26,22 @@ constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDept
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 kNegFlipXY[] = "negFlipXY";
constexpr const char kClipDistancesEnabled[] = "clipDistancesEnabled"; constexpr const char kClipDistancesEnabled[] = "clipDistancesEnabled";
constexpr const char kXfbActiveUnpaused[] = "xfbActiveUnpaused"; constexpr const char kXfbActiveUnpaused[] = "xfbActiveUnpaused";
constexpr const char kXfbVerticesPerDraw[] = "xfbVerticesPerDraw"; constexpr const char kXfbVerticesPerDraw[] = "xfbVerticesPerDraw";
constexpr const char kXfbBufferOffsets[] = "xfbBufferOffsets"; constexpr const char kXfbBufferOffsets[] = "xfbBufferOffsets";
constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets"; constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets";
constexpr const char kDepthRange[] = "depthRange"; constexpr const char kDepthRange[] = "depthRange";
constexpr const char kPreRotation[] = "preRotation";
constexpr const char kFragRotation[] = "fragRotation";
constexpr size_t kNumGraphicsDriverUniforms = 8; constexpr size_t kNumGraphicsDriverUniforms = 12;
constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = { constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {
{kViewport, kHalfRenderArea, kClipDistancesEnabled, kXfbActiveUnpaused, kXfbVerticesPerDraw, {kViewport, kHalfRenderArea, kFlipXY, kNegFlipXY, kClipDistancesEnabled, kXfbActiveUnpaused,
kXfbBufferOffsets, kAcbBufferOffsets, kDepthRange}}; kXfbVerticesPerDraw, kXfbBufferOffsets, kAcbBufferOffsets, kDepthRange, kPreRotation,
kFragRotation}};
constexpr size_t kNumComputeDriverUniforms = 1; constexpr size_t kNumComputeDriverUniforms = 1;
constexpr std::array<const char *, kNumComputeDriverUniforms> kComputeDriverUniformNames = { constexpr std::array<const char *, kNumComputeDriverUniforms> kComputeDriverUniformNames = {
...@@ -75,12 +80,21 @@ TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable) const ...@@ -75,12 +80,21 @@ TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable) const
// This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp. // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp.
TFieldList *driverFieldList = new TFieldList; TFieldList *driverFieldList = new TFieldList;
const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = { const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
{new TType(EbtFloat, 4), new TType(EbtFloat, 2), new TType(EbtFloat, 4),
new TType(EbtUInt), // uint clipDistancesEnabled; // 32 bits for 32 clip distances max new TType(EbtFloat, 2),
new TType(EbtUInt), new TType(EbtUInt), new TType(EbtFloat, 2),
// NOTE: There's a vec3 gap here that can be used in the future new TType(EbtFloat, 2),
new TType(EbtInt, 4), new TType(EbtUInt, 4), createEmulatedDepthRangeType(symbolTable)}}; new TType(EbtUInt), // uint clipDistancesEnabled; // 32 bits for 32 clip distances max
new TType(EbtUInt),
new TType(EbtUInt),
// NOTE: There's a vec3 gap here that can be used in the future
new TType(EbtInt, 4),
new TType(EbtUInt, 4),
createEmulatedDepthRangeType(symbolTable),
new TType(EbtFloat, 2, 2),
new TType(EbtFloat, 2, 2),
}};
for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex) for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex)
{ {
...@@ -159,6 +173,26 @@ TIntermBinary *DriverUniform::createDriverUniformRef(const char *fieldName) cons ...@@ -159,6 +173,26 @@ TIntermBinary *DriverUniform::createDriverUniformRef(const char *fieldName) cons
return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef); return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef);
} }
TIntermBinary *DriverUniform::getFlipXYRef() const
{
return createDriverUniformRef(kFlipXY);
}
TIntermBinary *DriverUniform::getNegFlipXYRef() const
{
return createDriverUniformRef(kNegFlipXY);
}
TIntermBinary *DriverUniform::getFragRotationMatrixRef() const
{
return createDriverUniformRef(kFragRotation);
}
TIntermBinary *DriverUniform::getPreRotationMatrixRef() const
{
return createDriverUniformRef(kPreRotation);
}
TIntermBinary *DriverUniform::getViewportRef() const TIntermBinary *DriverUniform::getViewportRef() const
{ {
return createDriverUniformRef(kViewport); return createDriverUniformRef(kViewport);
...@@ -184,6 +218,15 @@ TIntermBinary *DriverUniform::getDepthRangeRef() const ...@@ -184,6 +218,15 @@ TIntermBinary *DriverUniform::getDepthRangeRef() const
return createDriverUniformRef(kDepthRange); return createDriverUniformRef(kDepthRange);
} }
TIntermSwizzle *DriverUniform::getNegFlipYRef() const
{
// Create a swizzle to "negFlipXY.y"
TIntermBinary *negFlipXY = createDriverUniformRef(kNegFlipXY);
TVector<int> swizzleOffsetY = {1};
TIntermSwizzle *negFlipY = new TIntermSwizzle(negFlipXY, swizzleOffsetY);
return negFlipY;
}
TIntermBinary *DriverUniform::getDepthRangeReservedFieldRef() const TIntermBinary *DriverUniform::getDepthRangeReservedFieldRef() const
{ {
TIntermBinary *depthRange = createDriverUniformRef(kDepthRange); TIntermBinary *depthRange = createDriverUniformRef(kDepthRange);
......
...@@ -32,10 +32,15 @@ class DriverUniform ...@@ -32,10 +32,15 @@ class DriverUniform
bool addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable); bool addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable);
bool addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable); bool addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable);
TIntermBinary *getFlipXYRef() const;
TIntermBinary *getNegFlipXYRef() const;
TIntermBinary *getFragRotationMatrixRef() const;
TIntermBinary *getPreRotationMatrixRef() const;
TIntermBinary *getViewportRef() const; TIntermBinary *getViewportRef() const;
TIntermBinary *getHalfRenderAreaRef() const; TIntermBinary *getHalfRenderAreaRef() const;
TIntermBinary *getAbcBufferOffsets() const; TIntermBinary *getAbcBufferOffsets() const;
TIntermBinary *getClipDistancesEnabled() const; TIntermBinary *getClipDistancesEnabled() const;
TIntermSwizzle *getNegFlipYRef() const;
TIntermBinary *getDepthRangeRef() const; TIntermBinary *getDepthRangeRef() const;
TIntermBinary *getDepthRangeReservedFieldRef() const; TIntermBinary *getDepthRangeReservedFieldRef() const;
......
...@@ -32,7 +32,6 @@ using Mat2x2 = std::array<float, 4>; ...@@ -32,7 +32,6 @@ using Mat2x2 = std::array<float, 4>;
using Mat2x2EnumMap = using Mat2x2EnumMap =
angle::PackedEnumMap<vk::SurfaceRotation, Mat2x2, angle::EnumSize<vk::SurfaceRotation>()>; angle::PackedEnumMap<vk::SurfaceRotation, Mat2x2, angle::EnumSize<vk::SurfaceRotation>()>;
// Used to pre-rotate gl_Position for swapchain images on Android.
constexpr Mat2x2EnumMap kPreRotationMatrices = { constexpr Mat2x2EnumMap kPreRotationMatrices = {
{{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}}, {{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{0.0f, -1.0f, 1.0f, 0.0f}}}, {vk::SurfaceRotation::Rotated90Degrees, {{0.0f, -1.0f, 1.0f, 0.0f}}},
...@@ -43,7 +42,6 @@ constexpr Mat2x2EnumMap kPreRotationMatrices = { ...@@ -43,7 +42,6 @@ constexpr Mat2x2EnumMap kPreRotationMatrices = {
{vk::SurfaceRotation::FlippedRotated180Degrees, {{-1.0f, 0.0f, 0.0f, -1.0f}}}, {vk::SurfaceRotation::FlippedRotated180Degrees, {{-1.0f, 0.0f, 0.0f, -1.0f}}},
{vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, -1.0f, 0.0f}}}}}; {vk::SurfaceRotation::FlippedRotated270Degrees, {{0.0f, 1.0f, -1.0f, 0.0f}}}}};
// Used to pre-rotate gl_FragCoord for swapchain images on Android.
constexpr Mat2x2EnumMap kFragRotationMatrices = { constexpr Mat2x2EnumMap kFragRotationMatrices = {
{{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}}, {{vk::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}}, {vk::SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 1.0f, 0.0f}}},
...@@ -92,12 +90,6 @@ TIntermTyped *GenerateMat2x2ArrayWithIndex(const Mat2x2EnumMap &matrix, TIntermS ...@@ -92,12 +90,6 @@ TIntermTyped *GenerateMat2x2ArrayWithIndex(const Mat2x2EnumMap &matrix, TIntermS
using Vec2 = std::array<float, 2>; using Vec2 = std::array<float, 2>;
using Vec2EnumMap = using Vec2EnumMap =
angle::PackedEnumMap<vk::SurfaceRotation, Vec2, angle::EnumSize<vk::SurfaceRotation>()>; angle::PackedEnumMap<vk::SurfaceRotation, Vec2, angle::EnumSize<vk::SurfaceRotation>()>;
// Y-axis flipping only comes into play with the default framebuffer (i.e. a swapchain image).
// For 0-degree rotation, an FBO or pbuffer could be the draw framebuffer, and so we must check
// whether flipY should be positive or negative. All other rotations, will be to the default
// framebuffer, and so the value of isViewportFlipEnabledForDrawFBO() is assumed true; the
// appropriate flipY value is chosen such that gl_FragCoord is positioned at the lower-left
// corner of the window.
constexpr Vec2EnumMap kFlipXYValue = { constexpr Vec2EnumMap kFlipXYValue = {
{{vk::SurfaceRotation::Identity, {{1.0f, 1.0f}}}, {{vk::SurfaceRotation::Identity, {{1.0f, 1.0f}}},
{vk::SurfaceRotation::Rotated90Degrees, {{1.0f, 1.0f}}}, {vk::SurfaceRotation::Rotated90Degrees, {{1.0f, 1.0f}}},
......
...@@ -24,7 +24,7 @@ class FlipRotateSpecConst ...@@ -24,7 +24,7 @@ class FlipRotateSpecConst
{ {
public: public:
FlipRotateSpecConst(); FlipRotateSpecConst();
virtual ~FlipRotateSpecConst(); ~FlipRotateSpecConst();
TIntermTyped *getMultiplierXForDFdx(); TIntermTyped *getMultiplierXForDFdx();
TIntermTyped *getMultiplierYForDFdx(); TIntermTyped *getMultiplierYForDFdx();
...@@ -32,16 +32,14 @@ class FlipRotateSpecConst ...@@ -32,16 +32,14 @@ class FlipRotateSpecConst
TIntermTyped *getMultiplierYForDFdy(); TIntermTyped *getMultiplierYForDFdy();
TIntermTyped *getPreRotationMatrix(); TIntermTyped *getPreRotationMatrix();
TIntermTyped *getFragRotationMatrix(); TIntermTyped *getFragRotationMatrix();
TIntermTyped *getFlipXY();
TIntermTyped *getNegFlipXY();
TIntermTyped *getFlipY();
TIntermTyped *getNegFlipY();
TIntermTyped *getFragRotationMultiplyFlipXY(); TIntermTyped *getFragRotationMultiplyFlipXY();
// Let Metal override until they provide specialized constant support void generateSymbol(TSymbolTable *symbolTable);
virtual TIntermTyped *getFlipXY(); void outputLayoutString(TInfoSinkBase &sink) const;
virtual TIntermTyped *getNegFlipXY();
virtual TIntermTyped *getFlipY();
virtual TIntermTyped *getNegFlipY();
virtual void generateSymbol(TSymbolTable *symbolTable);
virtual void outputLayoutString(TInfoSinkBase &sink) const;
private: private:
TIntermSymbol *mSpecConstSymbol; TIntermSymbol *mSpecConstSymbol;
......
...@@ -479,6 +479,8 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -479,6 +479,8 @@ class ContextMtl : public ContextImpl, public mtl::Context
float viewport[4]; float viewport[4];
float halfRenderArea[2]; float halfRenderArea[2];
float flipXY[2];
float negFlipXY[2];
// 32 bits for 32 clip distances // 32 bits for 32 clip distances
uint32_t enabledClipDistances; uint32_t enabledClipDistances;
...@@ -494,8 +496,16 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -494,8 +496,16 @@ class ContextMtl : public ContextImpl, public mtl::Context
// We'll use x, y, z, w for near / far / diff / zscale respectively. // We'll use x, y, z, w for near / far / diff / zscale respectively.
float depthRange[4]; float depthRange[4];
float flipXY[2]; // Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is
float negFlipXY[2]; // padded to the size of two vec4's).
// Unused in Metal.
float preRotation[8] = {};
// Used to pre-rotate gl_FragCoord for Vulkan swapchain images on Android (a mat2, which is
// padded to the size of two vec4's).
// Unused in Metal.
float fragRotation[8] = {};
uint32_t coverageMask; uint32_t coverageMask;
float padding2[3]; float padding2[3];
......
...@@ -2092,6 +2092,10 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context, ...@@ -2092,6 +2092,10 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context,
static_cast<float>(mDrawFramebuffer->getState().getDimensions().width) * 0.5f; static_cast<float>(mDrawFramebuffer->getState().getDimensions().width) * 0.5f;
mDriverUniforms.halfRenderArea[1] = mDriverUniforms.halfRenderArea[1] =
static_cast<float>(mDrawFramebuffer->getState().getDimensions().height) * 0.5f; static_cast<float>(mDrawFramebuffer->getState().getDimensions().height) * 0.5f;
mDriverUniforms.flipXY[0] = 1.0f;
mDriverUniforms.flipXY[1] = mDrawFramebuffer->flipY() ? -1.0f : 1.0f;
mDriverUniforms.negFlipXY[0] = mDriverUniforms.flipXY[0];
mDriverUniforms.negFlipXY[1] = -mDriverUniforms.flipXY[1];
// gl_ClipDistance // gl_ClipDistance
mDriverUniforms.enabledClipDistances = mState.getEnabledClipDistances().bits(); mDriverUniforms.enabledClipDistances = mState.getEnabledClipDistances().bits();
...@@ -2101,10 +2105,7 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context, ...@@ -2101,10 +2105,7 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context,
mDriverUniforms.depthRange[2] = depthRangeDiff; mDriverUniforms.depthRange[2] = depthRangeDiff;
mDriverUniforms.depthRange[3] = NeedToInvertDepthRange(depthRangeNear, depthRangeFar) ? -1 : 1; mDriverUniforms.depthRange[3] = NeedToInvertDepthRange(depthRangeNear, depthRangeFar) ? -1 : 1;
mDriverUniforms.flipXY[0] = 1.0f; // NOTE(hqle): preRotation & fragRotation are unused.
mDriverUniforms.flipXY[1] = mDrawFramebuffer->flipY() ? -1.0f : 1.0f;
mDriverUniforms.negFlipXY[0] = mDriverUniforms.flipXY[0];
mDriverUniforms.negFlipXY[1] = -mDriverUniforms.flipXY[1];
// Sample coverage mask // Sample coverage mask
uint32_t sampleBitCount = mDrawFramebuffer->getSamples(); uint32_t sampleBitCount = mDrawFramebuffer->getSamples();
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <limits> #include <limits>
#include <map> #include <map>
#include "GLSLANG/ShaderLang.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
...@@ -45,21 +44,20 @@ namespace rx ...@@ -45,21 +44,20 @@ namespace rx
class ContextImpl; class ContextImpl;
// The possible rotations of the surface/draw framebuffer, particularly for the Vulkan back-end on // The possible rotations of the surface/draw framebuffer, particularly for the Vulkan back-end on
// Android. This is duplicate of ShaderLang.h declaration to avoid having to litter the renderer // Android.
// code with sh::vk namespace string. enum class SurfaceRotation
enum class SurfaceRotation : uint32_t
{ {
Identity = ToUnderlying(sh::vk::SurfaceRotation::Identity), Identity,
Rotated90Degrees = ToUnderlying(sh::vk::SurfaceRotation::Rotated90Degrees), Rotated90Degrees,
Rotated180Degrees = ToUnderlying(sh::vk::SurfaceRotation::Rotated180Degrees), Rotated180Degrees,
Rotated270Degrees = ToUnderlying(sh::vk::SurfaceRotation::Rotated270Degrees), Rotated270Degrees,
FlippedIdentity = ToUnderlying(sh::vk::SurfaceRotation::FlippedIdentity), FlippedIdentity,
FlippedRotated90Degrees = ToUnderlying(sh::vk::SurfaceRotation::FlippedRotated90Degrees), FlippedRotated90Degrees,
FlippedRotated180Degrees = ToUnderlying(sh::vk::SurfaceRotation::FlippedRotated180Degrees), FlippedRotated180Degrees,
FlippedRotated270Degrees = ToUnderlying(sh::vk::SurfaceRotation::FlippedRotated270Degrees), FlippedRotated270Degrees,
InvalidEnum = ToUnderlying(sh::vk::SurfaceRotation::InvalidEnum), InvalidEnum,
EnumCount = InvalidEnum, EnumCount = InvalidEnum,
}; };
void RotateRectangle(const SurfaceRotation rotation, void RotateRectangle(const SurfaceRotation rotation,
......
...@@ -62,6 +62,8 @@ struct GraphicsDriverUniforms ...@@ -62,6 +62,8 @@ struct GraphicsDriverUniforms
// Used to flip gl_FragCoord (both .xy for Android pre-rotation; only .y for desktop) // Used to flip gl_FragCoord (both .xy for Android pre-rotation; only .y for desktop)
std::array<float, 2> halfRenderArea; std::array<float, 2> halfRenderArea;
std::array<float, 2> flipXY;
std::array<float, 2> negFlipXY;
// 32 bits for 32 clip planes // 32 bits for 32 clip planes
uint32_t enabledClipPlanes; uint32_t enabledClipPlanes;
...@@ -81,6 +83,13 @@ struct GraphicsDriverUniforms ...@@ -81,6 +83,13 @@ struct GraphicsDriverUniforms
// We'll use x, y, z for near / far / diff respectively. // We'll use x, y, z for near / far / diff respectively.
std::array<float, 4> depthRange; std::array<float, 4> depthRange;
// Used to pre-rotate gl_Position for swapchain images on Android (a mat2, which is padded to
// the size of two vec4's).
std::array<float, 8> preRotation;
// Used to pre-rotate gl_FragCoord for swapchain images on Android (a mat2, which is padded to
// the size of two vec4's).
std::array<float, 8> fragRotation;
}; };
struct ComputeDriverUniforms struct ComputeDriverUniforms
...@@ -170,6 +179,51 @@ bool IsRenderPassStartedAndUsesImage(const vk::CommandBufferHelper &renderPassCo ...@@ -170,6 +179,51 @@ bool IsRenderPassStartedAndUsesImage(const vk::CommandBufferHelper &renderPassCo
return renderPassCommands.started() && renderPassCommands.usesImageInRenderPass(image); return renderPassCommands.started() && renderPassCommands.usesImageInRenderPass(image);
} }
// 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.
//
// Note: these are mat2's that are appropriately padded (4 floats per row).
using PreRotationMatrixValues = std::array<float, 8>;
constexpr angle::PackedEnumMap<rx::SurfaceRotation,
PreRotationMatrixValues,
angle::EnumSize<rx::SurfaceRotation>()>
kPreRotationMatrices = {
{{rx::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::Rotated90Degrees,
{{0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::Rotated180Degrees,
{{-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::Rotated270Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedIdentity,
{{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedRotated90Degrees,
{{0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedRotated180Degrees,
{{-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedRotated270Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
constexpr angle::PackedEnumMap<rx::SurfaceRotation,
PreRotationMatrixValues,
angle::EnumSize<rx::SurfaceRotation>()>
kFragRotationMatrices = {
{{rx::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::Rotated90Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::Rotated180Degrees,
{{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::Rotated270Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedRotated90Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedRotated180Degrees,
{{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
{rx::SurfaceRotation::FlippedRotated270Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
bool IsRotatedAspectRatio(SurfaceRotation rotation) bool IsRotatedAspectRatio(SurfaceRotation rotation)
{ {
return ((rotation == SurfaceRotation::Rotated90Degrees) || return ((rotation == SurfaceRotation::Rotated90Degrees) ||
...@@ -3564,11 +3618,46 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co ...@@ -3564,11 +3618,46 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
std::swap(glViewport.x, glViewport.y); std::swap(glViewport.x, glViewport.y);
std::swap(glViewport.width, glViewport.height); std::swap(glViewport.width, glViewport.height);
} }
float flipX = 1.0f;
float flipY = -1.0f;
// Y-axis flipping only comes into play with the default framebuffer (i.e. a swapchain image).
// For 0-degree rotation, an FBO or pbuffer could be the draw framebuffer, and so we must check
// whether flipY should be positive or negative. All other rotations, will be to the default
// framebuffer, and so the value of isViewportFlipEnabledForDrawFBO() is assumed true; the
// appropriate flipY value is chosen such that gl_FragCoord is positioned at the lower-left
// corner of the window.
switch (mCurrentRotationDrawFramebuffer)
{
case SurfaceRotation::Identity:
flipX = 1.0f;
flipY = isViewportFlipEnabledForDrawFBO() ? -1.0f : 1.0f;
break;
case SurfaceRotation::Rotated90Degrees:
ASSERT(isViewportFlipEnabledForDrawFBO());
flipX = 1.0f;
flipY = 1.0f;
std::swap(halfRenderAreaWidth, halfRenderAreaHeight);
break;
case SurfaceRotation::Rotated180Degrees:
ASSERT(isViewportFlipEnabledForDrawFBO());
flipX = -1.0f;
flipY = 1.0f;
break;
case SurfaceRotation::Rotated270Degrees:
ASSERT(isViewportFlipEnabledForDrawFBO());
flipX = -1.0f;
flipY = -1.0f;
break;
default:
UNREACHABLE();
break;
}
uint32_t xfbActiveUnpaused = mState.isTransformFeedbackActiveUnpaused(); uint32_t xfbActiveUnpaused = mState.isTransformFeedbackActiveUnpaused();
float depthRangeNear = mState.getNearPlane();
float depthRangeFar = mState.getFarPlane(); float depthRangeNear = mState.getNearPlane();
float depthRangeDiff = depthRangeFar - depthRangeNear; float depthRangeFar = mState.getFarPlane();
float depthRangeDiff = depthRangeFar - depthRangeNear;
// Copy and flush to the device. // Copy and flush to the device.
GraphicsDriverUniforms *driverUniforms = reinterpret_cast<GraphicsDriverUniforms *>(ptr); GraphicsDriverUniforms *driverUniforms = reinterpret_cast<GraphicsDriverUniforms *>(ptr);
...@@ -3576,13 +3665,21 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co ...@@ -3576,13 +3665,21 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
{static_cast<float>(glViewport.x), static_cast<float>(glViewport.y), {static_cast<float>(glViewport.x), static_cast<float>(glViewport.y),
static_cast<float>(glViewport.width), static_cast<float>(glViewport.height)}, static_cast<float>(glViewport.width), static_cast<float>(glViewport.height)},
{halfRenderAreaWidth, halfRenderAreaHeight}, {halfRenderAreaWidth, halfRenderAreaHeight},
{flipX, flipY},
{flipX, -flipY},
mState.getEnabledClipDistances().bits(), mState.getEnabledClipDistances().bits(),
xfbActiveUnpaused, xfbActiveUnpaused,
mXfbVertexCountPerInstance, mXfbVertexCountPerInstance,
{}, {},
{}, {},
{}, {},
{depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f}}; {depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f},
{},
{}};
memcpy(&driverUniforms->preRotation, &kPreRotationMatrices[mCurrentRotationDrawFramebuffer],
sizeof(PreRotationMatrixValues));
memcpy(&driverUniforms->fragRotation, &kFragRotationMatrices[mCurrentRotationDrawFramebuffer],
sizeof(PreRotationMatrixValues));
if (xfbActiveUnpaused) if (xfbActiveUnpaused)
{ {
......
...@@ -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 ||
......
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