Metal: Fix dropped out arguments from functions with many args.

RewriteOutArgs has an early-exit if it spots a potentially aliased
arg. It's also responsible for marking out args as references,
which caused an issue in Google Earth.
Removing the early-exit fixes both issues.

Bug: chromium:1474736
Change-Id: Ib68dd3f3e2e0a1e773e4e09edcdfa3a4bdfc1ef2
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4823006
Commit-Queue: Jonah Ryan-Davis <jonahr@google.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Jonah Ryan-Davis
2023-08-29 13:31:07 -04:00
committed by Angle LUCI CQ
parent 0d67d1bb23
commit 1ab5d01d9b
3 changed files with 98 additions and 14 deletions

View File

@@ -125,23 +125,11 @@ class Rewriter : public TIntermRebuild
const TVariable &param = *func->getParam(i);
const TType &paramType = param.getType();
const TQualifier paramQual = paramType.getQualifier();
switch (paramQual)
{
case TQualifier::EvqParamOut:
case TQualifier::EvqParamInOut:
if (!mSymbolEnv.isReference(param))
{
mSymbolEnv.markAsReference(param, AddressSpace::Thread);
}
break;
default:
break;
}
return paramQual;
};
// Check which params might be aliased, and mark all out params as references.
bool mightAlias = false;
for (size_t i = 0; i < argCount; ++i)
{
const TQualifier paramQual = getParamQualifier(i);
@@ -151,11 +139,17 @@ class Rewriter : public TIntermRebuild
case TQualifier::EvqParamOut:
case TQualifier::EvqParamInOut:
{
const TVariable &param = *func->getParam(i);
if (!mSymbolEnv.isReference(param))
{
mSymbolEnv.markAsReference(param, AddressSpace::Thread);
}
// Note: not the same as param above, this refers to the variable in the
// argument list in the callsite.
const TVariable *var = GetVariable(*args[i]);
if (mVarBuffer.insert(var).count > 1)
{
mightAlias = true;
i = argCount;
}
}
break;

View File

@@ -814,3 +814,37 @@ TEST_F(MSLOutputTest, GlobalRescopingDeclarationAfterFunction)
)";
compile(shaderString);
}
TEST_F(MSLOutputTest, ReusedOutVarName)
{
const std::string &shaderString =
R"(#version 300 es
precision mediump float;
out vec4 my_FragColor;
void funcWith1Out(
out float outC) {
outC = 1.0;
}
void funcWith4Outs(
out float outA,
out float outB,
out float outC,
out float outD) {
outA = 1.0;
outB = 1.0;
outD = 1.0;
}
void main()
{
funcWith1Out(my_FragColor.g);
funcWith4Outs(my_FragColor.r, my_FragColor.g, my_FragColor.b, my_FragColor.a);
}
)";
compile(shaderString);
}

View File

@@ -16200,6 +16200,34 @@ void main() {
ASSERT_GL_NO_ERROR();
}
// Test that aliasing function out parameters work even when multiple params are aliased.
TEST_P(GLSLTest, AliasingFunctionOutParamsMultiple)
{
constexpr char kFS[] = R"(precision highp float;
const vec4 colorGreen = vec4(0.,1.,0.,1.);
const vec4 colorRed = vec4(1.,0.,0.,1.);
bool outParametersAreDistinct(out float x, out float y, out float z, out float a) {
x = 1.0;
y = 2.0;
z = 3.0;
a = 4.0;
return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
}
void main() {
float x = 0.0;
float y = 0.0;
gl_FragColor = outParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
}
)";
ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
}
// Test that aliasing function inout parameters work.
TEST_P(GLSLTest, AliasingFunctionInOutParams)
{
@@ -16225,6 +16253,34 @@ void main() {
ASSERT_GL_NO_ERROR();
}
// Test that aliasing function inout parameters work when more than one param is aliased.
TEST_P(GLSLTest, AliasingFunctionInOutParamsMultiple)
{
constexpr char kFS[] = R"(precision highp float;
const vec4 colorGreen = vec4(0.,1.,0.,1.);
const vec4 colorRed = vec4(1.,0.,0.,1.);
bool inoutParametersAreDistinct(inout float x, inout float y, inout float z, inout float a) {
x = 1.0;
y = 2.0;
z = 3.0;
a = 4.0;
return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
}
void main() {
float x = 0.0;
float y = 0.0;
gl_FragColor = inoutParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
}
)";
ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
}
// Test that aliasing function out parameter with a global works.
TEST_P(GLSLTest, AliasingFunctionOutParamAndGlobal)
{