Hash :
3cfc0ce2
Author :
Date :
2025-03-24T07:41:33
Revert "Vulkan:Dont use Subject/Observer for SwapchainImageChanged" This reverts commit 48103cb2f2b292cb50cc5a29546b358b2e47fd29. Reason for revert: assert fails https://ci.chromium.org/ui/p/angle/builders/ci/android-arm64-exp-test/7085/overview I 22:27:33.697 77.533s _RunTestsOnDevice(17221FDF6000A4) [ RUN ] EGLAndroidAutoRefreshTest.SwapCPUThrottling/ES3_Vulkan_NoFixture INFO:root:ERR: SurfaceVk.cpp:3165 (getCurrentFramebuffer): ! Assert failed in getCurrentFramebuffer (../../src/libANGLE/renderer/vulkan/SurfaceVk.cpp:3165): mAcquireOperation.state == ImageAcquireState::Ready Original change's description: > Vulkan:Dont use Subject/Observer for SwapchainImageChanged > > Because we do deferred ANI (VkAcquireNextImage) call until image is > needed, we need a way to force Context to go through > FramebufferVk::syncState call (FramebufferVk::syncState calls > WindowSurfaceVk::getAttachmentRenderTarget, which end up calling ANI. > Right now we uses subject/observer mechanism, by sending > angle::SubjectMessage::SwapchainImageChanged to all observers of > WindowSurfaceVk. In this case it is egl::Surface. Then eglSurface > redirects this message to its observers, which are all gl::Framebuffer's > attachments: color, depth, stencil. Even though only color attachment > needs to be notified, but because we don't have a separate list of > observers, depth/stencil attachment also receive the notification and > they early out. Then gl::Framebuffer sets > DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 dirty bit and send the > angle::SubjectMessage::DirtyBitsFlagged to Context, which dirty DrawFBO > and ReadFBO and dirty cached state. Note that this is specific for swap > image changed case, there is no surface property change (surface > property change will still trigger the subject/observer message with > SubjectMessage::SubjectChanged message, but this occurs rarely). This > gets worse for apps that uses multiple contexts, for the example > pokemon_masters_ex has three contexts, each context has its own default > frame buffer that attach to the same surface, and we never remove > non-current context from the observer list. This end up with > egl::Surface has 12 observers and for every frame, it loop over the list > of 12 observers and send message (virtual function call) to each of > them. Color attachment also ends up sending two messages to Context, one > for Read FBO and another for Draw FBO. There are total 21 virtual > function calls. Even for single context usage, you have 6 virtual > function calls, for every frame. > > EGL spec says "an EGLSurface must be current on only one thread at a > time", any other context must call EGLMakeCurrent in order to use this > surface, which will add all necessary dirty bits at that time. So we > really only need to notify current context. In this CL, > SwapchainImageChanged no longer uses subject/observer mechanism, so this > message is removed. > > This CL still uses subject/observer mechanism to send DirtyBitsFlagged > from Framebuffer back to context. We could call setDrawFramebufferDirty > and setReadFramebufferDirty directly, but that will require to remove > the "const" decoration out of gl::Context which generates too much code > diff, so onStateChange(angle::SubjectMessage::DirtyBitsFlagged) is still > used. > > Bug: angleproject:400711938 > Change-Id: I61354516fd0aa307714b7abd30c6b6e45ff7b496 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6319893 > Commit-Queue: Charlie Lao <cclao@google.com> > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > Reviewed-by: Yuxin Hu <yuxinhu@google.com> Bug: angleproject:400711938 Change-Id: Ib7899d1ac63a1f86af0953a1d25922578c470fc9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6387755 Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SurfaceNULL.cpp:
// Implements the class methods for SurfaceNULL.
//
#include "libANGLE/renderer/null/SurfaceNULL.h"
#include "common/debug.h"
#include "libANGLE/renderer/null/FramebufferNULL.h"
namespace rx
{
SurfaceNULL::SurfaceNULL(const egl::SurfaceState &surfaceState) : SurfaceImpl(surfaceState) {}
SurfaceNULL::~SurfaceNULL() {}
egl::Error SurfaceNULL::initialize(const egl::Display *display)
{
return egl::NoError();
}
egl::Error SurfaceNULL::swap(const gl::Context *context)
{
return egl::NoError();
}
egl::Error SurfaceNULL::postSubBuffer(const gl::Context *context,
EGLint x,
EGLint y,
EGLint width,
EGLint height)
{
return egl::NoError();
}
egl::Error SurfaceNULL::querySurfacePointerANGLE(EGLint attribute, void **value)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error SurfaceNULL::bindTexImage(const gl::Context *context,
gl::Texture *texture,
EGLint buffer)
{
return egl::NoError();
}
egl::Error SurfaceNULL::releaseTexImage(const gl::Context *context, EGLint buffer)
{
return egl::NoError();
}
egl::Error SurfaceNULL::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
{
UNIMPLEMENTED();
return egl::Error(EGL_BAD_ACCESS);
}
egl::Error SurfaceNULL::getMscRate(EGLint *numerator, EGLint *denominator)
{
UNIMPLEMENTED();
return egl::Error(EGL_BAD_ACCESS);
}
void SurfaceNULL::setSwapInterval(const egl::Display *display, EGLint interval) {}
EGLint SurfaceNULL::getWidth() const
{
// TODO(geofflang): Read from an actual window?
return 100;
}
EGLint SurfaceNULL::getHeight() const
{
// TODO(geofflang): Read from an actual window?
return 100;
}
EGLint SurfaceNULL::isPostSubBufferSupported() const
{
return EGL_TRUE;
}
EGLint SurfaceNULL::getSwapBehavior() const
{
return EGL_BUFFER_PRESERVED;
}
angle::Result SurfaceNULL::initializeContents(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex)
{
return angle::Result::Continue;
}
egl::Error SurfaceNULL::attachToFramebuffer(const gl::Context *context,
gl::Framebuffer *framebuffer)
{
return egl::NoError();
}
egl::Error SurfaceNULL::detachFromFramebuffer(const gl::Context *context,
gl::Framebuffer *framebuffer)
{
return egl::NoError();
}
} // namespace rx