Vulkan: Support fetching from default FBO

If GL_EXT_shader_framebuffer_fetch is enabled, specify framebuffer
attachments as having VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT.

Add new test FramebufferFetchES31.DefaultFramebufferTest which
exercises the behavior.

Also limit exposure of either framebuffer fetch extension to be
Android only due to swapchain images requiring INPUT_ATTACHMENT.

Test: FramebufferFetchES31.DefaultFramebufferTest
Bug: angleproject:6893
Change-Id: I227e36a9844e2301f0fe0602f4e4d905874b32e3
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3389791
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Ian Elliott <ianelliott@google.com>
Commit-Queue: Cody Northrop <cnorthrop@google.com>
This commit is contained in:
Cody Northrop 2022-01-14 12:45:14 -07:00 коммит произвёл Angle LUCI CQ
Родитель ff5368cd21
Коммит b536079817
3 изменённых файлов: 73 добавлений и 6 удалений

Просмотреть файл

@ -3020,14 +3020,14 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
// http://anglebug.com/6872
// On ARM hardware, framebuffer-fetch-like behavior on Vulkan is already coherent, so we can
// expose the coherent version of the GL extension despite unofficial Vulkan support.
ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetch, isARM);
ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetch, IsAndroid() && isARM);
// Important games are not checking supported extensions properly, and are confusing the
// GL_EXT_shader_framebuffer_fetch_non_coherent as the GL_EXT_shader_framebuffer_fetch
// extension. Therefore, don't enable the extension on Arm and Qualcomm by default.
// https://issuetracker.google.com/issues/186643966
ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetchNonCoherent,
!(isARM || isQualcomm));
IsAndroid() && !(isARM || isQualcomm));
angle::PlatformMethods *platform = ANGLEPlatformCurrent();
platform->overrideFeaturesVk(platform, &mFeatures);

Просмотреть файл

@ -125,15 +125,22 @@ angle::Result InitImageHelper(DisplayVk *displayVk,
vk::ImageHelper *imageHelper)
{
const angle::Format &textureFormat = vkFormat.getActualRenderableImageFormat();
bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
const VkImageUsageFlags usage = isDepthOrStencilFormat ? kSurfaceVkDepthStencilImageUsageFlags
: kSurfaceVkColorImageUsageFlags;
bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
VkImageUsageFlags usage = isDepthOrStencilFormat ? kSurfaceVkDepthStencilImageUsageFlags
: kSurfaceVkColorImageUsageFlags;
RendererVk *rendererVk = displayVk->getRenderer();
// If shaders may be fetching from this, we need this image to be an input
if (rendererVk->getFeatures().supportsShaderFramebufferFetch.enabled ||
rendererVk->getFeatures().supportsShaderFramebufferFetchNonCoherent.enabled)
{
usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u),
std::max(static_cast<uint32_t>(height), 1u), 1u};
angle::FormatID renderableFormatId = vkFormat.getActualRenderableImageFormatID();
RendererVk *rendererVk = displayVk->getRenderer();
// For devices that don't support creating swapchain images with RGB8, emulate with RGBA8.
if (rendererVk->getFeatures().overrideSurfaceFormatRGB8toRGBA8.enabled &&
renderableFormatId == angle::FormatID::R8G8B8_UNORM)
@ -1105,6 +1112,13 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
// We need transfer src for reading back from the backbuffer.
VkImageUsageFlags imageUsageFlags = kSurfaceVkColorImageUsageFlags;
// If shaders may be fetching from this, we need this image to be an input
if (renderer->getFeatures().supportsShaderFramebufferFetch.enabled ||
renderer->getFeatures().supportsShaderFramebufferFetchNonCoherent.enabled)
{
imageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
// We need storage image for compute writes (debug overlay output).
if (kEnableOverlay)
{

Просмотреть файл

@ -1612,6 +1612,59 @@ void main (void)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Verify we can use inout with the default framebuffer
// http://anglebug.com/6893
TEST_P(FramebufferFetchES31, DefaultFramebufferTest)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
constexpr char kVS[] = R"(#version 300 es
in highp vec4 a_position;
void main (void)
{
gl_Position = a_position;
})";
constexpr char kFS[] = R"(#version 300 es
#extension GL_EXT_shader_framebuffer_fetch : require
layout(location = 0) inout highp vec4 o_color;
uniform highp vec4 u_color;
void main (void)
{
o_color += u_color;
})";
GLProgram program;
program.makeRaster(kVS, kFS);
glUseProgram(program);
ASSERT_GL_NO_ERROR();
// Ensure that we're rendering to the default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Start with a clear buffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLint positionLocation = glGetAttribLocation(program, "a_position");
GLint colorLocation = glGetUniformLocation(program, "u_color");
// Draw once with red
glUniform4fv(colorLocation, 1, GLColor::red.toNormalizedVector().data());
render(positionLocation, GL_FALSE);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
ASSERT_GL_NO_ERROR();
// Draw again with blue, adding it to the existing red, ending up with magenta
glUniform4fv(colorLocation, 1, GLColor::blue.toNormalizedVector().data());
render(positionLocation, GL_FALSE);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::magenta);
ASSERT_GL_NO_ERROR();
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferFetchES31);
ANGLE_INSTANTIATE_TEST_ES31(FramebufferFetchES31);
} // namespace angle