Commit 39b5e771 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix vector size issue with clearWithCommand

gl::DrawBuffersVector was used to hold the clear values, but that didn't have enough space for depth/stencil clear values if MAX draw buffers where used and cleared. The added test in this change exposes the vkCmdClearAttachment Qualcomm bug (previously presumed to affect color clears only) with depth/stencil buffers, so the workaround is expanded to avoid vkCmdClearAttachment entirely. Bug: b/159808300 Change-Id: I27c58d9b534bce0bdd27cc53fc64e139f1363c1a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2455166 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com>
parent bd0d3f9c
...@@ -762,6 +762,9 @@ using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumC ...@@ -762,6 +762,9 @@ using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumC
template <typename T> template <typename T>
using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>; using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
template <typename T>
using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>; using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
template <typename T> template <typename T>
......
...@@ -504,13 +504,13 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context, ...@@ -504,13 +504,13 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
bool clearAnyWithCommand = clearAnyWithRenderPassLoadOp; bool clearAnyWithCommand = clearAnyWithRenderPassLoadOp;
// On buggy hardware, prefer to clear color with a draw call instead of // On buggy hardware, prefer to clear with a draw call instead of vkCmdClearAttachments.
// vkCmdClearAttachments.
if (renderer->getFeatures().preferDrawClearOverVkCmdClearAttachments.enabled) if (renderer->getFeatures().preferDrawClearOverVkCmdClearAttachments.enabled)
{ {
clearColorDrawBuffersMask.reset(); clearColorWithRenderPassLoadOp = false;
clearAnyWithCommand = clearDepthWithRenderPassLoadOp = false;
clearDepthWithRenderPassLoadOp || clearStencilWithRenderPassLoadOp; clearStencilWithRenderPassLoadOp = false;
clearAnyWithCommand = false;
} }
if (clearAnyWithCommand) if (clearAnyWithCommand)
...@@ -529,7 +529,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context, ...@@ -529,7 +529,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
} }
// Fallback to other methods for whatever isn't cleared here. // Fallback to other methods for whatever isn't cleared here.
if (clearColorDrawBuffersMask.any()) if (clearColorWithRenderPassLoadOp)
{ {
clearColorBuffers.reset(); clearColorBuffers.reset();
clearColor = false; clearColor = false;
...@@ -544,7 +544,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context, ...@@ -544,7 +544,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
} }
// If nothing left to clear, early out. // If nothing left to clear, early out.
if (!clearColor && !clearStencil) if (!clearColor && !clearDepth && !clearStencil)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2138,7 +2138,8 @@ angle::Result FramebufferVk::clearWithCommand( ...@@ -2138,7 +2138,8 @@ angle::Result FramebufferVk::clearWithCommand(
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue) const VkClearDepthStencilValue &clearDepthStencilValue)
{ {
gl::DrawBuffersVector<VkClearAttachment> attachments; gl::AttachmentVector<VkClearAttachment> attachments;
// Go through clearColorBuffers and add them to the list of attachments to clear. // Go through clearColorBuffers and add them to the list of attachments to clear.
for (size_t colorIndexGL : clearColorBuffers) for (size_t colorIndexGL : clearColorBuffers)
{ {
......
...@@ -1697,6 +1697,206 @@ TEST_P(ClearTestES3, ClearDisabledNonZeroAttachmentNoAssert) ...@@ -1697,6 +1697,206 @@ TEST_P(ClearTestES3, ClearDisabledNonZeroAttachmentNoAssert)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that having a framebuffer with maximum number of attachments and clearing color, depth and
// stencil works.
TEST_P(ClearTestES3, ClearMaxAttachments)
{
// http://anglebug.com/4612
ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
constexpr GLsizei kSize = 16;
GLint maxDrawBuffers = 0;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
ASSERT_GE(maxDrawBuffers, 4);
// Setup framebuffer.
GLFramebuffer fb;
glBindFramebuffer(GL_FRAMEBUFFER, fb);
std::vector<GLRenderbuffer> color(maxDrawBuffers);
std::vector<GLenum> drawBuffers(maxDrawBuffers);
for (GLint colorIndex = 0; colorIndex < maxDrawBuffers; ++colorIndex)
{
glBindRenderbuffer(GL_RENDERBUFFER, color[colorIndex]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorIndex,
GL_RENDERBUFFER, color[colorIndex]);
drawBuffers[colorIndex] = GL_COLOR_ATTACHMENT0 + colorIndex;
}
GLRenderbuffer depthStencil;
glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
EXPECT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
glDrawBuffers(maxDrawBuffers, drawBuffers.data());
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClearDepthf(1.0f);
glClearStencil(0x55);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
EXPECT_GL_NO_ERROR();
// Verify that every color attachment is cleared correctly.
for (GLint colorIndex = 0; colorIndex < maxDrawBuffers; ++colorIndex)
{
glReadBuffer(GL_COLOR_ATTACHMENT0 + colorIndex);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
}
// Verify that depth and stencil attachments are cleared correctly.
GLFramebuffer fbVerify;
glBindFramebuffer(GL_FRAMEBUFFER, fbVerify);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color[0]);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
// If depth is not cleared to 1, rendering would fail.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// If stencil is not cleared to 0x55, rendering would fail.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF);
// Draw green.
ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.95f);
// Verify that green was drawn.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
}
// Test that having a framebuffer with maximum number of attachments and clearing color, depth and
// stencil after a draw call works.
TEST_P(ClearTestES3, ClearMaxAttachmentsAfterDraw)
{
// http://anglebug.com/4612
ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
constexpr GLsizei kSize = 16;
GLint maxDrawBuffers = 0;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
ASSERT_GE(maxDrawBuffers, 4);
// Setup framebuffer.
GLFramebuffer fb;
glBindFramebuffer(GL_FRAMEBUFFER, fb);
std::vector<GLRenderbuffer> color(maxDrawBuffers);
std::vector<GLenum> drawBuffers(maxDrawBuffers);
for (GLint colorIndex = 0; colorIndex < maxDrawBuffers; ++colorIndex)
{
glBindRenderbuffer(GL_RENDERBUFFER, color[colorIndex]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorIndex,
GL_RENDERBUFFER, color[colorIndex]);
drawBuffers[colorIndex] = GL_COLOR_ATTACHMENT0 + colorIndex;
}
GLRenderbuffer depthStencil;
glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
EXPECT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
glDrawBuffers(maxDrawBuffers, drawBuffers.data());
// Issue a draw call to render blue, depth=0 and stencil 0x3C to the attachments.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x3C, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glStencilMask(0xFF);
// Generate shader for this framebuffer.
std::stringstream strstr;
strstr << "#version 300 es\n"
"precision highp float;\n";
for (GLint colorIndex = 0; colorIndex < maxDrawBuffers; ++colorIndex)
{
strstr << "layout(location = " << colorIndex << ") out vec4 value" << colorIndex << ";\n";
}
strstr << "void main()\n"
"{\n";
for (GLint colorIndex = 0; colorIndex < maxDrawBuffers; ++colorIndex)
{
strstr << "value" << colorIndex << " = vec4(0.0f, 0.0f, 1.0f, 1.0f);\n";
}
strstr << "}\n";
ANGLE_GL_PROGRAM(drawMRT, essl3_shaders::vs::Simple(), strstr.str().c_str());
drawQuad(drawMRT, essl3_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClearDepthf(1.0f);
glClearStencil(0x55);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
EXPECT_GL_NO_ERROR();
// Verify that every color attachment is cleared correctly.
for (GLint colorIndex = 0; colorIndex < maxDrawBuffers; ++colorIndex)
{
glReadBuffer(GL_COLOR_ATTACHMENT0 + colorIndex);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
}
// Verify that depth and stencil attachments are cleared correctly.
GLFramebuffer fbVerify;
glBindFramebuffer(GL_FRAMEBUFFER, fbVerify);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color[0]);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
// If depth is not cleared to 1, rendering would fail.
glDepthFunc(GL_LESS);
// If stencil is not cleared to 0x55, rendering would fail.
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw green.
ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.95f);
// Verify that green was drawn.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
}
#ifdef Bool #ifdef Bool
// X11 craziness. // X11 craziness.
# undef Bool # undef Bool
......
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