Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit cbd5bee

Browse files
kakashidinhoCommit Bot
authored and
Commit Bot
committed
Disable shader's pre-rotation code on Metal & non-Android.
Pre-rotation code were added to transform gl_Position, gl_FragCoords, gl_PointCoords, dFdX, dFdY in shader. However, it is only useful for android's surface pre-rotation and completely un-needed in Metal back-end. This CL disables these pre-rotation code if the platform is not android. Bug: angleproject:4678 Change-Id: I89c42fcf24b49896f4ed9c2f9465da521beaf25f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2295000 Commit-Queue: Shahbaz Youssefi <[email protected]> Reviewed-by: Jamie Madill <[email protected]> Reviewed-by: Shahbaz Youssefi <[email protected]> Reviewed-by: Ian Elliott <[email protected]>
1 parent 19a1943 commit cbd5bee

File tree

8 files changed

+152
-52
lines changed

8 files changed

+152
-52
lines changed

include/GLSLANG/ShaderLang.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
// Version number for shader translation API.
2828
// It is incremented every time the API changes.
29-
#define ANGLE_SH_VERSION 231
29+
#define ANGLE_SH_VERSION 232
3030

3131
enum ShShaderSpec
3232
{
@@ -339,6 +339,9 @@ const ShCompileOptions SH_IGNORE_PRECISION_QUALIFIERS = UINT64_C(1) << 54;
339339
// Allow compiler to do early fragment tests as an optimization.
340340
const ShCompileOptions SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION = UINT64_C(1) << 55;
341341

342+
// Allow compiler to insert Android pre-rotation code.
343+
const ShCompileOptions SH_ADD_PRE_ROTATION = UINT64_C(1) << 56;
344+
342345
// Defines alternate strategies for implementing array index clamping.
343346
enum ShArrayIndexClampingStrategy
344347
{

src/compiler/translator/TranslatorVulkan.cpp

+30-13
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,17 @@ ANGLE_NO_DISCARD bool RotateAndFlipBuiltinVariable(TCompiler *compiler,
242242
}
243243

244244
// Create the expression "(builtin.xy * fragRotation)"
245-
TIntermBinary *rotatedXY =
246-
new TIntermBinary(EOpMatrixTimesVector, fragRotation->deepCopy(), builtinXY->deepCopy());
245+
TIntermTyped *rotatedXY;
246+
if (fragRotation)
247+
{
248+
rotatedXY = new TIntermBinary(EOpMatrixTimesVector, fragRotation->deepCopy(),
249+
builtinXY->deepCopy());
250+
}
251+
else
252+
{
253+
// No rotation applied, use original variable.
254+
rotatedXY = builtinXY->deepCopy();
255+
}
247256

248257
// Create the expression "(builtin.xy - pivot) * flipXY + pivot
249258
TIntermBinary *removePivot = new TIntermBinary(EOpSub, rotatedXY, pivot);
@@ -571,14 +580,17 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationVS(TCompiler *compiler,
571580
}
572581

573582
ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
583+
ShCompileOptions compileOptions,
574584
TIntermBlock *root,
575585
TIntermSequence *insertSequence,
576586
TSymbolTable *symbolTable,
577587
const TVariable *driverUniforms)
578588
{
579589
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY);
580590
TIntermBinary *pivot = CreateDriverUniformRef(driverUniforms, kHalfRenderArea);
581-
TIntermBinary *fragRotation = CreateDriverUniformRef(driverUniforms, kFragRotation);
591+
TIntermBinary *fragRotation = (compileOptions & SH_ADD_PRE_ROTATION)
592+
? CreateDriverUniformRef(driverUniforms, kFragRotation)
593+
: nullptr;
582594
return RotateAndFlipBuiltinVariable(compiler, root, insertSequence, flipXY, symbolTable,
583595
BuiltInVariable::gl_FragCoord(), kFlippedFragCoordName,
584596
pivot, fragRotation);
@@ -618,6 +630,7 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
618630
// Note this emulation can not provide fully correct rasterization. See the docs more more info.
619631

620632
ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
633+
ShCompileOptions compileOptions,
621634
TInfoSinkBase &sink,
622635
TIntermBlock *root,
623636
TSymbolTable *symbolTable,
@@ -718,8 +731,8 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
718731
// If the shader does not use frag coord, we should insert it inside the emulation if.
719732
if (!usesFragCoord)
720733
{
721-
if (!InsertFragCoordCorrection(compiler, root, emulationSequence, symbolTable,
722-
driverUniforms))
734+
if (!InsertFragCoordCorrection(compiler, compileOptions, root, emulationSequence,
735+
symbolTable, driverUniforms))
723736
{
724737
return false;
725738
}
@@ -933,15 +946,16 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
933946

934947
if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION)
935948
{
936-
if (!AddBresenhamEmulationFS(this, sink, root, &getSymbolTable(), driverUniforms,
937-
usesFragCoord))
949+
if (!AddBresenhamEmulationFS(this, compileOptions, sink, root, &getSymbolTable(),
950+
driverUniforms, usesFragCoord))
938951
{
939952
return false;
940953
}
941954
}
942955

943956
bool hasGLFragColor = false;
944957
bool hasGLFragData = false;
958+
bool usePreRotation = compileOptions & SH_ADD_PRE_ROTATION;
945959

946960
for (const ShaderVariable &outputVar : mOutputVariables)
947961
{
@@ -972,7 +986,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
972986
{
973987
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kNegFlipXY);
974988
TIntermConstantUnion *pivot = CreateFloatNode(0.5f);
975-
TIntermBinary *fragRotation = CreateDriverUniformRef(driverUniforms, kFragRotation);
989+
TIntermBinary *fragRotation =
990+
usePreRotation ? CreateDriverUniformRef(driverUniforms, kFragRotation) : nullptr;
976991
if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipXY,
977992
&getSymbolTable(), BuiltInVariable::gl_PointCoord(),
978993
kFlippedPointCoordName, pivot, fragRotation))
@@ -983,16 +998,17 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
983998

984999
if (usesFragCoord)
9851000
{
986-
if (!InsertFragCoordCorrection(this, root, GetMainSequence(root), &getSymbolTable(),
987-
driverUniforms))
1001+
if (!InsertFragCoordCorrection(this, compileOptions, root, GetMainSequence(root),
1002+
&getSymbolTable(), driverUniforms))
9881003
{
9891004
return false;
9901005
}
9911006
}
9921007

9931008
{
994-
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY);
995-
TIntermBinary *fragRotation = CreateDriverUniformRef(driverUniforms, kFragRotation);
1009+
TIntermBinary *flipXY = CreateDriverUniformRef(driverUniforms, kFlipXY);
1010+
TIntermBinary *fragRotation =
1011+
usePreRotation ? CreateDriverUniformRef(driverUniforms, kFragRotation) : nullptr;
9961012
if (!RewriteDfdy(this, root, getSymbolTable(), getShaderVersion(), flipXY,
9971013
fragRotation))
9981014
{
@@ -1047,7 +1063,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
10471063
{
10481064
return false;
10491065
}
1050-
if (!AppendPreRotation(this, root, &getSymbolTable(), driverUniforms))
1066+
if ((compileOptions & SH_ADD_PRE_ROTATION) != 0 &&
1067+
!AppendPreRotation(this, root, &getSymbolTable(), driverUniforms))
10511068
{
10521069
return false;
10531070
}

src/compiler/translator/tree_ops/RewriteDfdy.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class Traverser : public TIntermTraverser
3333
Traverser(TIntermBinary *flipXY, TIntermTyped *fragRotation, TSymbolTable *symbolTable);
3434
bool visitUnary(Visit visit, TIntermUnary *node) override;
3535

36+
bool visitUnaryWithRotation(Visit visit, TIntermUnary *node);
37+
bool visitUnaryWithoutRotation(Visit visit, TIntermUnary *node);
38+
3639
TIntermBinary *mFlipXY = nullptr;
3740
TIntermTyped *mFragRotation = nullptr;
3841
};
@@ -57,6 +60,15 @@ bool Traverser::Apply(TCompiler *compiler,
5760
}
5861

5962
bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
63+
{
64+
if (mFragRotation)
65+
{
66+
return visitUnaryWithRotation(visit, node);
67+
}
68+
return visitUnaryWithoutRotation(visit, node);
69+
}
70+
71+
bool Traverser::visitUnaryWithRotation(Visit visit, TIntermUnary *node)
6072
{
6173
// Decide if the node represents a call to dFdx() or dFdy()
6274
if ((node->getOp() != EOpDFdx) && (node->getOp() != EOpDFdy))
@@ -140,6 +152,32 @@ bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
140152
return true;
141153
}
142154

155+
bool Traverser::visitUnaryWithoutRotation(Visit visit, TIntermUnary *node)
156+
{
157+
// Decide if the node represents a call to dFdy()
158+
if (node->getOp() != EOpDFdy)
159+
{
160+
return true;
161+
}
162+
163+
// Copy the dFdy node so we can replace it with the corrected value
164+
TIntermUnary *newDfdy = node->deepCopy()->getAsUnaryNode();
165+
166+
size_t objectSize = node->getType().getObjectSize();
167+
TOperator multiplyOp = (objectSize == 1) ? EOpMul : EOpVectorTimesScalar;
168+
169+
TIntermBinary *flipY =
170+
new TIntermBinary(EOpIndexDirect, mFlipXY->deepCopy(), CreateIndexNode(1));
171+
// Correct dFdy()'s value:
172+
// (dFdy() * mFlipXY.y)
173+
TIntermBinary *correctedDfdy = new TIntermBinary(multiplyOp, newDfdy, flipY);
174+
175+
// Replace the old dFdy node with the new node that contains the corrected value
176+
queueReplacement(correctedDfdy, OriginalNode::IS_DROPPED);
177+
178+
return true;
179+
}
180+
143181
} // anonymous namespace
144182

145183
bool RewriteDfdy(TCompiler *compiler,

src/compiler/translator/tree_ops/RewriteDfdy.h

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class TIntermBinary;
2424
class TIntermTyped;
2525
class TSymbolTable;
2626

27+
// If fragRotation = nullptr, no rotation will be applied.
2728
ANGLE_NO_DISCARD bool RewriteDfdy(TCompiler *compiler,
2829
TIntermNode *root,
2930
const TSymbolTable &symbolTable,

src/libANGLE/renderer/metal/ContextMtl.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,13 @@ class ContextMtl : public ContextImpl, public mtl::Context
442442

443443
// Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is
444444
// padded to the size of two vec4's).
445-
float preRotation[8];
445+
// Unused in Metal.
446+
float preRotation[8] = {};
446447

447448
// Used to pre-rotate gl_FragCoord for Vulkan swapchain images on Android (a mat2, which is
448449
// padded to the size of two vec4's).
449-
float fragRotation[8];
450+
// Unused in Metal.
451+
float fragRotation[8] = {};
450452

451453
uint32_t coverageMask;
452454

src/libANGLE/renderer/metal/ContextMtl.mm

+1-19
Original file line numberDiff line numberDiff line change
@@ -1702,25 +1702,7 @@ bool NeedToInvertDepthRange(float near, float far)
17021702
mDriverUniforms.depthRange[2] = depthRangeDiff;
17031703
mDriverUniforms.depthRange[3] = NeedToInvertDepthRange(depthRangeNear, depthRangeFar) ? -1 : 1;
17041704

1705-
// Fill in a mat2 identity matrix, plus padding
1706-
mDriverUniforms.preRotation[0] = 1.0f;
1707-
mDriverUniforms.preRotation[1] = 0.0f;
1708-
mDriverUniforms.preRotation[2] = 0.0f;
1709-
mDriverUniforms.preRotation[3] = 0.0f;
1710-
mDriverUniforms.preRotation[4] = 0.0f;
1711-
mDriverUniforms.preRotation[5] = 1.0f;
1712-
mDriverUniforms.preRotation[6] = 0.0f;
1713-
mDriverUniforms.preRotation[7] = 0.0f;
1714-
1715-
// Fill in a mat2 identity matrix, plus padding
1716-
mDriverUniforms.fragRotation[0] = 1.0f;
1717-
mDriverUniforms.fragRotation[1] = 0.0f;
1718-
mDriverUniforms.fragRotation[2] = 0.0f;
1719-
mDriverUniforms.fragRotation[3] = 0.0f;
1720-
mDriverUniforms.fragRotation[4] = 0.0f;
1721-
mDriverUniforms.fragRotation[5] = 1.0f;
1722-
mDriverUniforms.fragRotation[6] = 0.0f;
1723-
mDriverUniforms.fragRotation[7] = 0.0f;
1705+
// NOTE(hqle): preRotation & fragRotation are unused.
17241706

17251707
// Sample coverage mask
17261708
uint32_t sampleBitCount = mDrawFramebuffer->getSamples();

src/libANGLE/renderer/vulkan/ShaderVk.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte
6464
// context state does not allow it
6565
compileOptions |= SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION;
6666

67+
if (contextVk->getFeatures().enablePreRotateSurfaces.enabled)
68+
{
69+
// Let compiler inserts pre-rotation code.
70+
compileOptions |= SH_ADD_PRE_ROTATION;
71+
}
72+
6773
return compileImpl(context, compilerInstance, mData.getSource(), compileOptions | options);
6874
}
6975

src/tests/egl_tests/EGLPreRotationTest.cpp

+68-17
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@ using namespace angle;
2323
namespace
2424
{
2525

26+
using EGLPreRotationSurfaceTestParams = std::tuple<angle::PlatformParameters, bool>;
27+
28+
std::string PrintToStringParamName(
29+
const ::testing::TestParamInfo<EGLPreRotationSurfaceTestParams> &info)
30+
{
31+
std::stringstream ss;
32+
ss << std::get<0>(info.param);
33+
if (std::get<1>(info.param))
34+
{
35+
ss << "__PreRotationEnabled";
36+
}
37+
else
38+
{
39+
ss << "__PreRotationDisabled";
40+
}
41+
return ss.str();
42+
}
43+
2644
// A class to test various Android pre-rotation cases. In order to make it easier to debug test
2745
// failures, the initial window size is 256x256, and each pixel will have a unique and predictable
2846
// value. The red channel will increment with the x axis, and the green channel will increment
@@ -33,7 +51,7 @@ namespace
3351
// Lower-right, which is ( 1.0,-1.0) & (256, 0) in GLES will be red (0xFF, 0x00, 0x00, 0xFF)
3452
// Upper-left, which is (-1.0, 1.0) & ( 0, 256) in GLES will be green (0x00, 0xFF, 0x00, 0xFF)
3553
// Upper-right, which is ( 1.0, 1.0) & (256, 256) in GLES will be yellow (0xFF, 0xFF, 0x00, 0xFF)
36-
class EGLPreRotationSurfaceTest : public ANGLETest
54+
class EGLPreRotationSurfaceTest : public ANGLETestWithParam<EGLPreRotationSurfaceTestParams>
3755
{
3856
protected:
3957
EGLPreRotationSurfaceTest()
@@ -81,10 +99,24 @@ class EGLPreRotationSurfaceTest : public ANGLETest
8199

82100
void initializeDisplay()
83101
{
84-
GLenum platformType = GetParam().getRenderer();
85-
GLenum deviceType = GetParam().getDeviceType();
102+
const angle::PlatformParameters platform = ::testing::get<0>(GetParam());
103+
GLenum platformType = platform.getRenderer();
104+
GLenum deviceType = platform.getDeviceType();
105+
106+
std::vector<const char *> enabledFeatures;
107+
std::vector<const char *> disabledFeatures;
108+
if (::testing::get<1>(GetParam()))
109+
{
110+
enabledFeatures.push_back("enable_pre_rotation_surfaces");
111+
}
112+
else
113+
{
114+
disabledFeatures.push_back("enable_pre_rotation_surfaces");
115+
}
116+
enabledFeatures.push_back(nullptr);
117+
disabledFeatures.push_back(nullptr);
86118

87-
std::vector<EGLint> displayAttributes;
119+
std::vector<EGLAttrib> displayAttributes;
88120
displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
89121
displayAttributes.push_back(platformType);
90122
displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
@@ -93,11 +125,15 @@ class EGLPreRotationSurfaceTest : public ANGLETest
93125
displayAttributes.push_back(EGL_DONT_CARE);
94126
displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
95127
displayAttributes.push_back(deviceType);
128+
displayAttributes.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
129+
displayAttributes.push_back(reinterpret_cast<EGLAttrib>(enabledFeatures.data()));
130+
displayAttributes.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE);
131+
displayAttributes.push_back(reinterpret_cast<EGLAttrib>(disabledFeatures.data()));
96132
displayAttributes.push_back(EGL_NONE);
97133

98-
mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
99-
reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
100-
displayAttributes.data());
134+
mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
135+
reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
136+
displayAttributes.data());
101137
ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
102138

103139
EGLint majorVersion, minorVersion;
@@ -109,7 +145,8 @@ class EGLPreRotationSurfaceTest : public ANGLETest
109145

110146
void initializeContext()
111147
{
112-
EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion, EGL_NONE};
148+
EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION,
149+
::testing::get<0>(GetParam()).majorVersion, EGL_NONE};
113150

114151
mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
115152
ASSERT_EGL_SUCCESS();
@@ -1582,12 +1619,26 @@ TEST_P(EGLPreRotationBlitFramebufferTest, FboDestOutOfBoundsSourceAndDestBlitFra
15821619
}
15831620
} // anonymous namespace
15841621

1585-
ANGLE_INSTANTIATE_TEST(EGLPreRotationSurfaceTest,
1586-
WithNoFixture(ES2_VULKAN()),
1587-
WithNoFixture(ES3_VULKAN()));
1588-
ANGLE_INSTANTIATE_TEST(EGLPreRotationLargeSurfaceTest,
1589-
WithNoFixture(ES2_VULKAN()),
1590-
WithNoFixture(ES3_VULKAN()));
1591-
ANGLE_INSTANTIATE_TEST(EGLPreRotationBlitFramebufferTest,
1592-
WithNoFixture(ES2_VULKAN()),
1593-
WithNoFixture(ES3_VULKAN()));
1622+
#ifdef Bool
1623+
// X11 ridiculousness.
1624+
# undef Bool
1625+
#endif
1626+
1627+
ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationSurfaceTest,
1628+
PrintToStringParamName,
1629+
testing::Bool(),
1630+
WithNoFixture(ES2_VULKAN()),
1631+
WithNoFixture(ES3_VULKAN()),
1632+
WithNoFixture(ES3_VULKAN_SWIFTSHADER()));
1633+
ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationLargeSurfaceTest,
1634+
PrintToStringParamName,
1635+
testing::Bool(),
1636+
WithNoFixture(ES2_VULKAN()),
1637+
WithNoFixture(ES3_VULKAN()),
1638+
WithNoFixture(ES3_VULKAN_SWIFTSHADER()));
1639+
ANGLE_INSTANTIATE_TEST_COMBINE_1(EGLPreRotationBlitFramebufferTest,
1640+
PrintToStringParamName,
1641+
testing::Bool(),
1642+
WithNoFixture(ES2_VULKAN()),
1643+
WithNoFixture(ES3_VULKAN()),
1644+
WithNoFixture(ES3_VULKAN_SWIFTSHADER()));

0 commit comments

Comments
 (0)