Clear glColorMask at the start of a RenderPass for LoadOp::Clear attachments
Bug: dawn:133
Change-Id: Id8c6180f7a9ef2f7901aca6690d611fad4f13beb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/6560
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp
index 5b7e968..b2fecc4 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -657,6 +657,7 @@
// Load op - color
if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
+ glColorMaski(i, true, true, true, true);
glClearBufferfv(GL_COLOR, i, &attachmentInfo.clearColor.r);
}
}
diff --git a/src/tests/end2end/ColorStateTests.cpp b/src/tests/end2end/ColorStateTests.cpp
index e83a57a..f71a5de 100644
--- a/src/tests/end2end/ColorStateTests.cpp
+++ b/src/tests/end2end/ColorStateTests.cpp
@@ -1001,4 +1001,64 @@
}
}
+// This tests a problem in the OpenGL backend where a previous color write mask
+// persisted and prevented a render pass loadOp from fully clearing the output
+// attachment.
+TEST_P(ColorStateTest, ColorWriteMaskDoesNotAffectRenderPassLoadOpClear) {
+ dawn::ShaderModule fsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"(
+ #version 450
+ layout(set = 0, binding = 0) uniform myBlock {
+ vec4 color;
+ } myUbo;
+
+ layout(location = 0) out vec4 fragColor;
+
+ void main() {
+ fragColor = myUbo.color;
+ }
+ )");
+
+ utils::ComboRenderPipelineDescriptor baseDescriptor(device);
+ baseDescriptor.layout = pipelineLayout;
+ baseDescriptor.cVertexStage.module = vsModule;
+ baseDescriptor.cFragmentStage.module = fsModule;
+ baseDescriptor.cColorStates[0]->format = renderPass.colorFormat;
+
+ basePipeline = device.CreateRenderPipeline(&baseDescriptor);
+
+ utils::ComboRenderPipelineDescriptor testDescriptor(device);
+ testDescriptor.layout = pipelineLayout;
+ testDescriptor.cVertexStage.module = vsModule;
+ testDescriptor.cFragmentStage.module = fsModule;
+ testDescriptor.cColorStates[0]->format = renderPass.colorFormat;
+ testDescriptor.cColorStates[0]->colorWriteMask = dawn::ColorWriteMask::Red;
+
+ testPipeline = device.CreateRenderPipeline(&testDescriptor);
+
+ RGBA8 base(32, 64, 128, 192);
+ RGBA8 expected(0, 0, 0, 0);
+
+ dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+ {
+ // Clear the output attachment to |base|
+ dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
+ pass.SetPipeline(basePipeline);
+ pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({{base}})), 0, nullptr);
+ pass.Draw(3, 1, 0, 0);
+
+ // Set a pipeline that will dirty the color write mask
+ pass.SetPipeline(testPipeline);
+ pass.EndPass();
+ }
+ {
+ // This renderpass' loadOp should clear all channels of the output attachment
+ dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
+ pass.EndPass();
+ }
+ dawn::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+
+ EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
+}
+
DAWN_INSTANTIATE_TEST(ColorStateTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);