Vulkan: Move framebuffer dirty bits handling after texture

When texture changes, it notify the observer. Framebuffer object is one
of the observer and is able to respond to the changes in texture object.
In this specific case, when texture called TextureVk::releaseImage and
requires framebuffer object to syncState and call
TextureVk::initRenderTargets. The problem right now is that framebuffer
object's dirty bits are processed before texture, which means if the
texture is being used by currently bound framebuffer object, it will not
trigger the FBO's dirty bit handling. This CL moves container object
dirty bit (DIRTY_OBJECT_DRAW_FRAMEBUFFER and
DIRTY_OBJECT_READ_FRAMEBUFFER)  after texture/image object's dirty bits.

Bug: chromium:1212206
Bug: chromium:1197431
Change-Id: I95723da1ce5b8936d66692242f2e25e7a73bafe6
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2915764
Commit-Queue: Charlie Lao <cclao@google.com>
Reviewed-by: Ian Elliott <ianelliott@google.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Charlie Lao 2021-05-24 19:05:44 -07:00 коммит произвёл Angle LUCI CQ
Родитель ecf2956d93
Коммит a280c671f1
3 изменённых файлов: 19 добавлений и 15 удалений

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

@ -704,12 +704,12 @@ class State : angle::NonCopyable
DIRTY_OBJECT_IMAGES_INIT,
DIRTY_OBJECT_READ_ATTACHMENTS,
DIRTY_OBJECT_DRAW_ATTACHMENTS,
DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY,
DIRTY_OBJECT_TEXTURES, // Top-level dirty bit. Also see mDirtyTextures.
DIRTY_OBJECT_IMAGES, // Top-level dirty bit. Also see mDirtyImages.
DIRTY_OBJECT_SAMPLERS, // Top-level dirty bit. Also see mDirtySamplers.
DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_PROGRAM,
DIRTY_OBJECT_UNKNOWN,
DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
@ -943,9 +943,9 @@ class State : angle::NonCopyable
using DirtyObjectHandler = angle::Result (State::*)(const Context *context, Command command);
static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
&State::syncActiveTextures, &State::syncTexturesInit, &State::syncImagesInit,
&State::syncReadAttachments, &State::syncDrawAttachments, &State::syncReadFramebuffer,
&State::syncDrawFramebuffer, &State::syncVertexArray, &State::syncTextures,
&State::syncImages, &State::syncSamplers, &State::syncProgram};
&State::syncReadAttachments, &State::syncDrawAttachments, &State::syncVertexArray,
&State::syncTextures, &State::syncImages, &State::syncSamplers,
&State::syncReadFramebuffer, &State::syncDrawFramebuffer, &State::syncProgram};
// Robust init must happen before Framebuffer init for the Vulkan back-end.
static_assert(DIRTY_OBJECT_ACTIVE_TEXTURES < DIRTY_OBJECT_TEXTURES_INIT, "init order");
@ -959,14 +959,21 @@ class State : angle::NonCopyable
static_assert(DIRTY_OBJECT_IMAGES_INIT == 2, "check DIRTY_OBJECT_IMAGES_INIT index");
static_assert(DIRTY_OBJECT_READ_ATTACHMENTS == 3, "check DIRTY_OBJECT_READ_ATTACHMENTS index");
static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS == 4, "check DIRTY_OBJECT_DRAW_ATTACHMENTS index");
static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 5, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 6, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 7, "check DIRTY_OBJECT_VERTEX_ARRAY index");
static_assert(DIRTY_OBJECT_TEXTURES == 8, "check DIRTY_OBJECT_TEXTURES index");
static_assert(DIRTY_OBJECT_IMAGES == 9, "check DIRTY_OBJECT_IMAGES index");
static_assert(DIRTY_OBJECT_SAMPLERS == 10, "check DIRTY_OBJECT_SAMPLERS index");
static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 5, "check DIRTY_OBJECT_VERTEX_ARRAY index");
static_assert(DIRTY_OBJECT_TEXTURES == 6, "check DIRTY_OBJECT_TEXTURES index");
static_assert(DIRTY_OBJECT_IMAGES == 7, "check DIRTY_OBJECT_IMAGES index");
static_assert(DIRTY_OBJECT_SAMPLERS == 8, "check DIRTY_OBJECT_SAMPLERS index");
static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 9, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 10, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_PROGRAM == 11, "check DIRTY_OBJECT_PROGRAM index");
// Container (FBO) object must handled after the texture so that if texture code adds dirty bit
// to container object, they will be picked up in the same draw call.
static_assert(DIRTY_OBJECT_TEXTURES < DIRTY_OBJECT_READ_FRAMEBUFFER,
"State::syncDirtyObjects order");
static_assert(DIRTY_OBJECT_TEXTURES < DIRTY_OBJECT_DRAW_FRAMEBUFFER,
"State::syncDirtyObjects order");
// Dispatch table for buffer update functions.
static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;

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

@ -3335,9 +3335,6 @@ TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
// LINEAR_MIPMAP_LINEAR did not make any changes.
TEST_P(FramebufferTest_ES3, FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)
{
// http://crbug.com/1197431
ANGLE_SKIP_TEST_IF(IsVulkan());
constexpr char kFS[] = R"(precision mediump float;
uniform sampler2D u_tex0;
void main() {

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

@ -4247,7 +4247,7 @@ TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel)
TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback)
{
// http://crbug.com/1212206
ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
ANGLE_SKIP_TEST_IF(IsMetal());
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());