Commit 901045cc by Ian Elliott Committed by Commit Bot

Vulkan: Rotate gl_FragCoord for Android pre-rotation

This extends the current y-flip that's done for gl_FragCoord. Now, gl_FragCoord is rotated and then flips both the x and y-axis. Bug: angleproject:4643 Bug: b/156395519 Change-Id: Iada8680eda8322f7382ff242e4a9422a66114f05 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2210936Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Ian Elliott <ianelliott@google.com>
parent 218a6835
...@@ -35,7 +35,7 @@ namespace ...@@ -35,7 +35,7 @@ namespace
ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler, ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler,
TIntermBlock *root, TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
TIntermBinary *negViewportYScale) TIntermBinary *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();
...@@ -46,8 +46,8 @@ ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *com ...@@ -46,8 +46,8 @@ ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *com
swizzleOffsetY.push_back(1); swizzleOffsetY.push_back(1);
TIntermSwizzle *positionY = new TIntermSwizzle(positionRef, swizzleOffsetY); TIntermSwizzle *positionY = new TIntermSwizzle(positionRef, swizzleOffsetY);
// Create the expression "gl_Position.y * negViewportScaleY" // Create the expression "gl_Position.y * negFlipY"
TIntermBinary *inverseY = new TIntermBinary(EOpMul, positionY->deepCopy(), negViewportYScale); TIntermBinary *inverseY = new TIntermBinary(EOpMul, positionY->deepCopy(), negFlipY);
// Create the assignment "gl_Position.y = gl_Position.y * negViewportScaleY // Create the assignment "gl_Position.y = gl_Position.y * negViewportScaleY
TIntermTyped *positionYLHS = positionY->deepCopy(); TIntermTyped *positionYLHS = positionY->deepCopy();
...@@ -81,11 +81,10 @@ bool TranslatorMetal::translate(TIntermBlock *root, ...@@ -81,11 +81,10 @@ bool TranslatorMetal::translate(TIntermBlock *root,
if (getShaderType() == GL_VERTEX_SHADER) if (getShaderType() == GL_VERTEX_SHADER)
{ {
auto negViewportYScale = getDriverUniformNegViewportYScaleRef(driverUniforms); auto negFlipY = getDriverUniformNegFlipYRef(driverUniforms);
// Append gl_Position.y correction to main // Append gl_Position.y correction to main
if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(), if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(), negFlipY))
negViewportYScale))
{ {
return false; return false;
} }
......
...@@ -174,9 +174,10 @@ constexpr ImmutableString kLineRasterEmulationSpecConstVarName = ...@@ -174,9 +174,10 @@ constexpr ImmutableString kLineRasterEmulationSpecConstVarName =
ImmutableString("ANGLELineRasterEmulation"); ImmutableString("ANGLELineRasterEmulation");
constexpr const char kViewport[] = "viewport"; constexpr const char kViewport[] = "viewport";
constexpr const char kHalfRenderAreaHeight[] = "halfRenderAreaHeight"; constexpr const char kHalfRenderArea[] = "halfRenderArea";
constexpr const char kFlipXY[] = "flipXY";
constexpr const char kViewportYScale[] = "viewportYScale"; constexpr const char kViewportYScale[] = "viewportYScale";
constexpr const char kNegViewportYScale[] = "negViewportYScale"; constexpr const char kNegFlipY[] = "negFlipY";
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";
...@@ -184,12 +185,13 @@ constexpr const char kXfbBufferOffsets[] = "xfbBufferOffsets"; ...@@ -184,12 +185,13 @@ 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 kPreRotation[] = "preRotation";
constexpr const char kFragRotation[] = "fragRotation";
constexpr size_t kNumGraphicsDriverUniforms = 11; constexpr size_t kNumGraphicsDriverUniforms = 13;
constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = { constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {
{kViewport, kHalfRenderAreaHeight, kViewportYScale, kNegViewportYScale, kClipDistancesEnabled, {kViewport, kHalfRenderArea, kFlipXY, kViewportYScale, kNegFlipY, kClipDistancesEnabled,
kXfbActiveUnpaused, kXfbVerticesPerDraw, kXfbBufferOffsets, kAcbBufferOffsets, kDepthRange, kXfbActiveUnpaused, kXfbVerticesPerDraw, kXfbBufferOffsets, kAcbBufferOffsets, kDepthRange,
kPreRotation}}; 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 = {
...@@ -274,6 +276,65 @@ ANGLE_NO_DISCARD bool FlipBuiltinVariable(TCompiler *compiler, ...@@ -274,6 +276,65 @@ ANGLE_NO_DISCARD bool FlipBuiltinVariable(TCompiler *compiler,
return compiler->validateAST(root); return compiler->validateAST(root);
} }
// Replaces a builtin variable with a version that is rotated and corrects the X and Y coordinates.
ANGLE_NO_DISCARD bool RotateAndFlipBuiltinVariable(TCompiler *compiler,
TIntermBlock *root,
TIntermSequence *insertSequence,
TIntermTyped *flipXY,
TSymbolTable *symbolTable,
const TVariable *builtin,
const ImmutableString &flippedVariableName,
TIntermTyped *pivot,
TIntermTyped *fragRotation)
{
// Create a symbol reference to 'builtin'.
TIntermSymbol *builtinRef = new TIntermSymbol(builtin);
// Create a swizzle to "builtin.xy"
TVector<int> swizzleOffsetXY = {0, 1};
TIntermSwizzle *builtinXY = new TIntermSwizzle(builtinRef, swizzleOffsetXY);
// Create a symbol reference to our new variable that will hold the modified builtin.
const TType *type = StaticType::GetForVec<EbtFloat>(
EvqGlobal, static_cast<unsigned char>(builtin->getType().getNominalSize()));
TVariable *replacementVar =
new TVariable(symbolTable, flippedVariableName, type, SymbolType::AngleInternal);
DeclareGlobalVariable(root, replacementVar);
TIntermSymbol *flippedBuiltinRef = new TIntermSymbol(replacementVar);
// Use this new variable instead of 'builtin' everywhere.
if (!ReplaceVariable(compiler, root, builtin, replacementVar))
{
return false;
}
// Create the expression "(builtin.xy * fragRotation)"
TIntermBinary *rotatedXY =
new TIntermBinary(EOpMatrixTimesVector, fragRotation->deepCopy(), builtinXY->deepCopy());
// Create the expression "(builtin.xy - pivot) * flipXY + pivot
TIntermBinary *removePivot = new TIntermBinary(EOpSub, rotatedXY, pivot);
TIntermBinary *inverseXY = new TIntermBinary(EOpMul, removePivot, flipXY);
TIntermBinary *plusPivot = new TIntermBinary(EOpAdd, inverseXY, pivot->deepCopy());
// Create the corrected variable and copy the value of the original builtin.
TIntermSequence *sequence = new TIntermSequence();
sequence->push_back(builtinRef->deepCopy());
TIntermAggregate *aggregate = TIntermAggregate::CreateConstructor(builtin->getType(), sequence);
TIntermBinary *assignment = new TIntermBinary(EOpInitialize, flippedBuiltinRef, aggregate);
// Create an assignment to the replaced variable's .xy.
TIntermSwizzle *correctedXY =
new TIntermSwizzle(flippedBuiltinRef->deepCopy(), swizzleOffsetXY);
TIntermBinary *assignToY = new TIntermBinary(EOpAssign, correctedXY, plusPivot);
// Add this assigment at the beginning of the main function
insertSequence->insert(insertSequence->begin(), assignToY);
insertSequence->insert(insertSequence->begin(), assignment);
return compiler->validateAST(root);
}
TIntermSequence *GetMainSequence(TIntermBlock *root) TIntermSequence *GetMainSequence(TIntermBlock *root)
{ {
TIntermFunctionDefinition *main = FindMain(root); TIntermFunctionDefinition *main = FindMain(root);
...@@ -415,7 +476,8 @@ const TVariable *AddGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTa ...@@ -415,7 +476,8 @@ const TVariable *AddGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTa
const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{ const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{
new TType(EbtFloat, 4), new TType(EbtFloat, 4),
new TType(EbtFloat), new TType(EbtFloat, 2),
new TType(EbtFloat, 2),
new TType(EbtFloat), new TType(EbtFloat),
new TType(EbtFloat), new TType(EbtFloat),
new TType(EbtUInt), // uint clipDistancesEnabled; // 32 bits for 32 clip distances max new TType(EbtUInt), // uint clipDistancesEnabled; // 32 bits for 32 clip distances max
...@@ -426,6 +488,7 @@ const TVariable *AddGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTa ...@@ -426,6 +488,7 @@ const TVariable *AddGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTa
new TType(EbtUInt, 4), new TType(EbtUInt, 4),
emulatedDepthRangeType, emulatedDepthRangeType,
new TType(EbtFloat, 2, 2), 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)
...@@ -575,10 +638,12 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler, ...@@ -575,10 +638,12 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
const TVariable *driverUniforms) const TVariable *driverUniforms)
{ {
TIntermBinary *viewportYScale = CreateDriverUniformRef(driverUniforms, kViewportYScale); TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY);
TIntermBinary *pivot = CreateDriverUniformRef(driverUniforms, kHalfRenderAreaHeight); TIntermBinary *pivot = CreateDriverUniformRef(driverUniforms, kHalfRenderArea);
return FlipBuiltinVariable(compiler, root, insertSequence, viewportYScale, symbolTable, TIntermBinary *fragRotation = CreateDriverUniformRef(driverUniforms, kFragRotation);
BuiltInVariable::gl_FragCoord(), kFlippedFragCoordName, pivot); return RotateAndFlipBuiltinVariable(compiler, root, insertSequence, flipXY, symbolTable,
BuiltInVariable::gl_FragCoord(), kFlippedFragCoordName,
pivot, fragRotation);
} }
// This block adds OpenGL line segment rasterization emulation behind a specialization constant // This block adds OpenGL line segment rasterization emulation behind a specialization constant
...@@ -964,9 +1029,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -964,9 +1029,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (usesPointCoord) if (usesPointCoord)
{ {
TIntermBinary *viewportYScale = TIntermBinary *viewportYScale = CreateDriverUniformRef(driverUniforms, kNegFlipY);
CreateDriverUniformRef(driverUniforms, kNegViewportYScale); TIntermConstantUnion *pivot = CreateFloatNode(0.5f);
TIntermConstantUnion *pivot = CreateFloatNode(0.5f);
if (!FlipBuiltinVariable(this, root, GetMainSequence(root), viewportYScale, if (!FlipBuiltinVariable(this, root, GetMainSequence(root), viewportYScale,
&getSymbolTable(), BuiltInVariable::gl_PointCoord(), &getSymbolTable(), BuiltInVariable::gl_PointCoord(),
kFlippedPointCoordName, pivot)) kFlippedPointCoordName, pivot))
...@@ -1104,10 +1168,9 @@ bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll() ...@@ -1104,10 +1168,9 @@ bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
return false; return false;
} }
TIntermBinary *TranslatorVulkan::getDriverUniformNegViewportYScaleRef( TIntermBinary *TranslatorVulkan::getDriverUniformNegFlipYRef(const TVariable *driverUniforms) const
const TVariable *driverUniforms) const
{ {
return CreateDriverUniformRef(driverUniforms, kNegViewportYScale); return CreateDriverUniformRef(driverUniforms, kNegFlipY);
} }
TIntermBinary *TranslatorVulkan::getDriverUniformDepthRangeReservedFieldRef( TIntermBinary *TranslatorVulkan::getDriverUniformDepthRangeReservedFieldRef(
......
...@@ -30,7 +30,7 @@ class TranslatorVulkan : public TCompiler ...@@ -30,7 +30,7 @@ class TranslatorVulkan : public TCompiler
PerformanceDiagnostics *perfDiagnostics) override; PerformanceDiagnostics *perfDiagnostics) override;
bool shouldFlattenPragmaStdglInvariantAll() override; bool shouldFlattenPragmaStdglInvariantAll() override;
TIntermBinary *getDriverUniformNegViewportYScaleRef(const TVariable *driverUniforms) const; TIntermBinary *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.
......
...@@ -377,7 +377,8 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -377,7 +377,8 @@ class ContextMtl : public ContextImpl, public mtl::Context
{ {
float viewport[4]; float viewport[4];
float halfRenderAreaHeight; float halfRenderArea[2];
float flipXY[2];
float viewportYScale; float viewportYScale;
float negViewportYScale; float negViewportYScale;
...@@ -388,7 +389,7 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -388,7 +389,7 @@ class ContextMtl : public ContextImpl, public mtl::Context
uint32_t xfbActiveUnpaused; uint32_t xfbActiveUnpaused;
uint32_t xfbVerticesPerDraw; uint32_t xfbVerticesPerDraw;
// NOTE: Explicit padding. Fill in with useful data when needed in the future. // NOTE: Explicit padding. Fill in with useful data when needed in the future.
int32_t padding[2]; int32_t padding[3];
int32_t xfbBufferOffsets[4]; int32_t xfbBufferOffsets[4];
uint32_t acbBufferOffsets[4]; uint32_t acbBufferOffsets[4];
...@@ -399,6 +400,10 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -399,6 +400,10 @@ class ContextMtl : public ContextImpl, public mtl::Context
// Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is // Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is
// padded to the size of two vec4's). // padded to the size of two vec4's).
float preRotation[8]; 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).
float fragRotation[8];
}; };
struct DefaultAttribute struct DefaultAttribute
......
...@@ -1594,8 +1594,12 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context) ...@@ -1594,8 +1594,12 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context)
mDriverUniforms.viewport[2] = glViewport.width; mDriverUniforms.viewport[2] = glViewport.width;
mDriverUniforms.viewport[3] = glViewport.height; mDriverUniforms.viewport[3] = glViewport.height;
mDriverUniforms.halfRenderAreaHeight = mDriverUniforms.halfRenderArea[0] =
static_cast<float>(mDrawFramebuffer->getState().getDimensions().width) * 0.5f;
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.viewportYScale = mDrawFramebuffer->flipY() ? -1.0f : 1.0f; mDriverUniforms.viewportYScale = mDrawFramebuffer->flipY() ? -1.0f : 1.0f;
mDriverUniforms.negViewportYScale = -mDriverUniforms.viewportYScale; mDriverUniforms.negViewportYScale = -mDriverUniforms.viewportYScale;
...@@ -1616,6 +1620,16 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context) ...@@ -1616,6 +1620,16 @@ angle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context)
mDriverUniforms.preRotation[6] = 0.0f; mDriverUniforms.preRotation[6] = 0.0f;
mDriverUniforms.preRotation[7] = 0.0f; mDriverUniforms.preRotation[7] = 0.0f;
// Fill in a mat2 identity matrix, plus padding
mDriverUniforms.fragRotation[0] = 1.0f;
mDriverUniforms.fragRotation[1] = 0.0f;
mDriverUniforms.fragRotation[2] = 0.0f;
mDriverUniforms.fragRotation[3] = 0.0f;
mDriverUniforms.fragRotation[4] = 0.0f;
mDriverUniforms.fragRotation[5] = 1.0f;
mDriverUniforms.fragRotation[6] = 0.0f;
mDriverUniforms.fragRotation[7] = 0.0f;
ASSERT(mRenderEncoder.valid()); ASSERT(mRenderEncoder.valid());
mRenderEncoder.setFragmentData(mDriverUniforms, mtl::kDriverUniformsBindingIndex); mRenderEncoder.setFragmentData(mDriverUniforms, mtl::kDriverUniformsBindingIndex);
mRenderEncoder.setVertexData(mDriverUniforms, mtl::kDriverUniformsBindingIndex); mRenderEncoder.setVertexData(mDriverUniforms, mtl::kDriverUniformsBindingIndex);
......
...@@ -52,17 +52,25 @@ struct GraphicsDriverUniforms ...@@ -52,17 +52,25 @@ struct GraphicsDriverUniforms
{ {
std::array<float, 4> viewport; std::array<float, 4> viewport;
float halfRenderAreaHeight; // Used to flip gl_FragCoord (both .xy for Android pre-rotation; only .y for desktop)
std::array<float, 2> halfRenderArea;
std::array<float, 2> flipXY;
// TODO(ianelliott): Remove the following while doing pre-rotation for gl_PointCoord & dFdy()
// https://issuetracker.google.com/issues/157476696
// https://issuetracker.google.com/issues/157476241
float viewportYScale; float viewportYScale;
float negViewportYScale; float negFlipY;
// 32 bits for 32 clip planes // 32 bits for 32 clip planes
uint32_t enabledClipPlanes; uint32_t enabledClipPlanes;
uint32_t xfbActiveUnpaused; uint32_t xfbActiveUnpaused;
uint32_t xfbVerticesPerDraw; uint32_t xfbVerticesPerDraw;
// TODO(ianelliott): Remove the following while doing pre-rotation for gl_PointCoord
// https://issuetracker.google.com/issues/157476696
// https://issuetracker.google.com/issues/157476241
// NOTE: Explicit padding. Fill in with useful data when needed in the future. // NOTE: Explicit padding. Fill in with useful data when needed in the future.
std::array<int32_t, 2> padding; std::array<int32_t, 3> padding;
std::array<int32_t, 4> xfbBufferOffsets; std::array<int32_t, 4> xfbBufferOffsets;
...@@ -79,6 +87,9 @@ struct GraphicsDriverUniforms ...@@ -79,6 +87,9 @@ struct GraphicsDriverUniforms
// Used to pre-rotate gl_Position for swapchain images on Android (a mat2, which is padded to // Used to pre-rotate gl_Position for swapchain images on Android (a mat2, which is padded to
// the size of two vec4's). // the size of two vec4's).
std::array<float, 8> preRotation; 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
...@@ -189,7 +200,8 @@ void ApplySampleCoverage(const gl::State &glState, ...@@ -189,7 +200,8 @@ void ApplySampleCoverage(const gl::State &glState,
} }
// When an Android surface is rotated differently than the device's native orientation, ANGLE must // When an Android surface is rotated differently than the device's native orientation, ANGLE must
// rotate gl_Position in the vertex shader. The following are the rotation matrices used. // 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). // Note: these are mat2's that are appropriately padded (4 floats per row).
using PreRotationMatrixValues = std::array<float, 8>; using PreRotationMatrixValues = std::array<float, 8>;
...@@ -213,6 +225,25 @@ constexpr angle::PackedEnumMap<rx::SurfaceRotation, ...@@ -213,6 +225,25 @@ constexpr angle::PackedEnumMap<rx::SurfaceRotation,
{rx::SurfaceRotation::FlippedRotated270Degrees, {rx::SurfaceRotation::FlippedRotated270Degrees,
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}}; {{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) ||
...@@ -3368,17 +3399,50 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co ...@@ -3368,17 +3399,50 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
&newBuffer)); &newBuffer));
gl::Rectangle glViewport = mState.getViewport(); gl::Rectangle glViewport = mState.getViewport();
float halfRenderAreaWidth =
static_cast<float>(mDrawFramebuffer->getState().getDimensions().width) * 0.5f;
float halfRenderAreaHeight = float halfRenderAreaHeight =
static_cast<float>(mDrawFramebuffer->getState().getDimensions().height) * 0.5f; static_cast<float>(mDrawFramebuffer->getState().getDimensions().height) * 0.5f;
if (isRotatedAspectRatioForDrawFBO()) if (isRotatedAspectRatioForDrawFBO())
{ {
// The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface. // The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface.
// TODO(ianelliott): handle small viewport/scissor cases. http://anglebug.com/4431 std::swap(glViewport.x, glViewport.y);
std::swap(glViewport.width, glViewport.height); std::swap(glViewport.width, glViewport.height);
halfRenderAreaHeight =
static_cast<float>(mDrawFramebuffer->getState().getDimensions().width) * 0.5f;
} }
float scaleY = isViewportFlipEnabledForDrawFBO() ? -1.0f : 1.0f; 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();
...@@ -3391,9 +3455,10 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co ...@@ -3391,9 +3455,10 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
*driverUniforms = { *driverUniforms = {
{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)},
halfRenderAreaHeight, {halfRenderAreaWidth, halfRenderAreaHeight},
scaleY, {flipX, flipY},
-scaleY, flipY,
-flipY,
mState.getEnabledClipDistances().bits(), mState.getEnabledClipDistances().bits(),
xfbActiveUnpaused, xfbActiveUnpaused,
mXfbVertexCountPerInstance, mXfbVertexCountPerInstance,
...@@ -3401,9 +3466,12 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co ...@@ -3401,9 +3466,12 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
{}, {},
{}, {},
{depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f}, {depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f},
{},
{}}; {}};
memcpy(&driverUniforms->preRotation, &kPreRotationMatrices[mCurrentRotationDrawFramebuffer], memcpy(&driverUniforms->preRotation, &kPreRotationMatrices[mCurrentRotationDrawFramebuffer],
sizeof(PreRotationMatrixValues)); sizeof(PreRotationMatrixValues));
memcpy(&driverUniforms->fragRotation, &kFragRotationMatrices[mCurrentRotationDrawFramebuffer],
sizeof(PreRotationMatrixValues));
if (xfbActiveUnpaused) if (xfbActiveUnpaused)
{ {
......
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