Commit f28d63e9 by Mohan Maiya Committed by Commit Bot

Vulkan: Enable glBlitFramebuffer for EXT_sRGB_write_control

Implements support for the glBlitFramebuffer edge case in the EXT_sRGB_write_control spec, and fully exposes this extension. Bug: angleproject:5075 Test: SRGBFramebufferTest*.*Vulkan* Change-Id: I05f044abbc5cb272825d1fc4b9028217f18e63c2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2785641Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
parent 5dad9d8a
...@@ -1125,6 +1125,9 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1125,6 +1125,9 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
(noFlip || !disableFlippingBlitWithCommand) && (noFlip || !disableFlippingBlitWithCommand) &&
HasSrcBlitFeature(renderer, readRenderTarget) && HasSrcBlitFeature(renderer, readRenderTarget) &&
(rotation == SurfaceRotation::Identity); (rotation == SurfaceRotation::Identity);
// If we need to reinterpret the colorspace then the blit must be done through a shader
bool reinterpretsColorspace =
mCurrentFramebufferDesc.getWriteControlMode() != gl::SrgbWriteControlMode::Default;
bool areChannelsBlitCompatible = true; bool areChannelsBlitCompatible = true;
bool areFormatsIdentical = true; bool areFormatsIdentical = true;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
...@@ -1145,7 +1148,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1145,7 +1148,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
} }
AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params); AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);
if (canBlitWithCommand && areChannelsBlitCompatible) if (canBlitWithCommand && areChannelsBlitCompatible && !reinterpretsColorspace)
{ {
for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{ {
...@@ -1157,7 +1160,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1157,7 +1160,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
} }
// If we're not flipping or rotating, use Vulkan's builtin resolve. // If we're not flipping or rotating, use Vulkan's builtin resolve.
else if (isColorResolve && !flipX && !flipY && areChannelsBlitCompatible && else if (isColorResolve && !flipX && !flipY && areChannelsBlitCompatible &&
areFormatsIdentical && rotation == SurfaceRotation::Identity) areFormatsIdentical && rotation == SurfaceRotation::Identity &&
!reinterpretsColorspace)
{ {
// Resolving with a subpass resolve attachment has a few restrictions: // Resolving with a subpass resolve attachment has a few restrictions:
// 1.) glBlitFramebuffer() needs to copy the read color attachment to all enabled // 1.) glBlitFramebuffer() needs to copy the read color attachment to all enabled
......
...@@ -453,11 +453,8 @@ void RendererVk::ensureCapsInitialized() const ...@@ -453,11 +453,8 @@ void RendererVk::ensureCapsInitialized() const
vk::GetTextureSRGBOverrideSupport(this, mNativeExtensions); vk::GetTextureSRGBOverrideSupport(this, mNativeExtensions);
mNativeExtensions.textureSRGBDecode = vk::GetTextureSRGBDecodeSupport(this); mNativeExtensions.textureSRGBDecode = vk::GetTextureSRGBDecodeSupport(this);
// Doesn't yet support glBlitFramebuffer // EXT_srgb_write_control requires image_format_list
// http://anglebug.com/5075 mNativeExtensions.sRGBWriteControl = getFeatures().supportsImageFormatList.enabled;
// Will be fully enabled in a follow up change when issues with glBlitFramebuffer have been
// resolved
mNativeExtensions.sRGBWriteControl = false;
// Vulkan natively supports io interface block. // Vulkan natively supports io interface block.
mNativeExtensions.shaderIoBlocksOES = true; mNativeExtensions.shaderIoBlocksOES = true;
......
...@@ -46,6 +46,9 @@ class SRGBFramebufferTest : public ANGLETest ...@@ -46,6 +46,9 @@ class SRGBFramebufferTest : public ANGLETest
GLint mColorLocation = -1; GLint mColorLocation = -1;
}; };
class SRGBFramebufferTestES3 : public SRGBFramebufferTest
{};
// Test basic validation of GL_EXT_sRGB_write_control // Test basic validation of GL_EXT_sRGB_write_control
TEST_P(SRGBFramebufferTest, Validation) TEST_P(SRGBFramebufferTest, Validation)
{ {
...@@ -237,8 +240,70 @@ TEST_P(SRGBFramebufferTest, NegativeLifetimeTracking) ...@@ -237,8 +240,70 @@ TEST_P(SRGBFramebufferTest, NegativeLifetimeTracking)
EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
} }
// Test that glBlitFramebuffer correctly converts colorspaces
TEST_P(SRGBFramebufferTestES3, BlitFramebuffer)
{
// http://anglebug.com/5790
ANGLE_SKIP_TEST_IF(!IsVulkan());
if (!IsGLExtensionEnabled("GL_EXT_sRGB_write_control") ||
(!IsGLExtensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3))
{
std::cout
<< "Test skipped because GL_EXT_sRGB_write_control and GL_EXT_sRGB are not available."
<< std::endl;
return;
}
GLTexture dstTexture;
glBindTexture(GL_TEXTURE_2D, dstTexture.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
nullptr);
GLFramebuffer dstFramebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer.get());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTexture.get(),
0);
GLTexture srcTexture;
glBindTexture(GL_TEXTURE_2D, srcTexture.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
nullptr);
GLFramebuffer srcFramebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, srcFramebuffer.get());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexture.get(),
0);
glUseProgram(mProgram);
glUniform4fv(mColorLocation, 1, srgbColor.toNormalizedVector().data());
// Draw onto the framebuffer normally
glEnable(GL_FRAMEBUFFER_SRGB_EXT);
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
// Blit the framebuffer normally
glEnable(GL_FRAMEBUFFER_SRGB_EXT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer);
glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
// Blit the framebuffer with forced linear colorspace
glDisable(GL_FRAMEBUFFER_SRGB_EXT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer);
glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer);
EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SRGBFramebufferTest); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SRGBFramebufferTest);
ANGLE_INSTANTIATE_TEST_ES3(SRGBFramebufferTestES3);
} // namespace angle } // namespace angle
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