Commit 8cb95960 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix FS array output location assignment

Test: angle_end2end_test --gtest_filter=GLSLTest_ES3.FragmentShaderOutputArray/ES3_Vulkan Bug: angleproject:3707 Change-Id: I6519a76aa58ad80ada0e2ad90a2a70d93f831ce5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1704779 Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent ec30d78d
......@@ -508,6 +508,13 @@ void AssignAttributeLocations(const gl::ProgramState &programState,
}
}
std::string RemoveArrayZeroSubscript(const std::string &expression)
{
ASSERT(expression.size() > 3);
ASSERT(expression.substr(expression.size() - 3) == "[0]");
return expression.substr(0, expression.size() - 3);
}
void AssignOutputLocations(const gl::ProgramState &programState,
IntermediateShaderSource *fragmentSource)
{
......@@ -526,12 +533,27 @@ void AssignOutputLocations(const gl::ProgramState &programState,
{
const sh::OutputVariable &outputVar = outputVariables[outputLocation.index];
// In the following:
//
// out vec4 fragOutput[N];
//
// The varying name is |fragOutput[0]|. We need to remove the extra |[0]|.
std::string name = outputVar.name;
if (outputVar.isArray())
{
name = RemoveArrayZeroSubscript(name);
if (outputVar.isArrayOfArrays())
{
name = RemoveArrayZeroSubscript(name);
}
}
std::string locationString;
if (outputVar.location != -1)
{
locationString = "location = " + Str(outputVar.location);
}
else if (std::find(implicitOutputs.begin(), implicitOutputs.end(), outputVar.name) ==
else if (std::find(implicitOutputs.begin(), implicitOutputs.end(), name) ==
implicitOutputs.end())
{
// If there is only one output, it is allowed not to have a location qualifier, in
......@@ -541,7 +563,7 @@ void AssignOutputLocations(const gl::ProgramState &programState,
locationString = "location = 0";
}
fragmentSource->insertLayoutSpecifier(outputVar.name, locationString);
fragmentSource->insertLayoutSpecifier(name, locationString);
}
}
}
......
......@@ -488,6 +488,19 @@ class GLSLTest : public ANGLETest
glDeleteProgram(program);
ASSERT_GL_NO_ERROR();
}
void verifyAttachment2DColor(unsigned int index,
GLuint textureName,
GLenum target,
GLint level,
GLColor color)
{
glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
<< "index " << index;
}
};
class GLSLTestNoValidation : public GLSLTest
......@@ -535,6 +548,74 @@ void main()
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
}
// Test that array of fragment shader outputs is processed properly and draws
// E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
{
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
GLuint textures[4];
glGenTextures(4, textures);
for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
{
glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
}
GLint maxDrawBuffers;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
ASSERT_GE(maxDrawBuffers, 4);
GLuint readFramebuffer;
glGenFramebuffers(1, &readFramebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
constexpr char kFS[] = R"(#version 300 es
precision highp float;
out vec4 frag_color[4];
void main()
{
frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
}
)";
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
constexpr GLuint kMaxBuffers = 4;
// Enable all draw buffers.
for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
{
glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
textures[texIndex], 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
textures[texIndex], 0);
}
glDrawBuffers(kMaxBuffers, allBufs);
// Draw with simple program.
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
ASSERT_GL_NO_ERROR();
verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
}
TEST_P(GLSLTest, ScopedStructsOrderBug)
{
// TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
......
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