зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1646073 - Enable WebGL SwapChain pooling on Android. Use a separate SwapChain for WebVR. r=jgilbert
- Enable WebGL SwapChain pooling on Android. Creating and releasing Android Surfaces every frame causes a big performance hit due to AndroidSurface slow destructors bug. - Add a separate SwapChain for WebVR. We are already using separate SwapChains for WebXR (WebGLFramebuffer::mOpaqueSwapChain) but not for WebVR (it uses the canvas backbuffer). Differential Revision: https://phabricator.services.mozilla.com/D79840
This commit is contained in:
Родитель
10ad51e7e6
Коммит
cc77358c6f
|
@ -413,19 +413,24 @@ void ClientWebGLContext::EndComposition() {
|
|||
|
||||
// -
|
||||
|
||||
void ClientWebGLContext::Present(WebGLFramebufferJS* const fb,
|
||||
const layers::TextureType type) {
|
||||
if (!mIsCanvasDirty && !fb) return;
|
||||
void ClientWebGLContext::Present(WebGLFramebufferJS* const xrFb,
|
||||
const layers::TextureType type,
|
||||
const bool webvr) {
|
||||
if (!mIsCanvasDirty && !xrFb) return;
|
||||
if (!xrFb) {
|
||||
mIsCanvasDirty = false;
|
||||
}
|
||||
|
||||
Run<RPROC(Present)>(fb ? fb->mId : 0, type);
|
||||
Run<RPROC(Present)>(xrFb ? xrFb->mId : 0, type, webvr);
|
||||
}
|
||||
|
||||
Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
|
||||
WebGLFramebufferJS* const fb) {
|
||||
return Run<RPROC(GetFrontBuffer)>(fb ? fb->mId : 0);
|
||||
WebGLFramebufferJS* const fb, bool vr) {
|
||||
return Run<RPROC(GetFrontBuffer)>(fb ? fb->mId : 0, vr);
|
||||
}
|
||||
|
||||
void ClientWebGLContext::ClearVRSwapChain() { Run<RPROC(ClearVRSwapChain)>(); }
|
||||
|
||||
// -
|
||||
|
||||
already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
|
||||
|
|
|
@ -992,11 +992,15 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
|||
}
|
||||
void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
|
||||
|
||||
void Present(WebGLFramebufferJS*, layers::TextureType);
|
||||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebufferJS*);
|
||||
void Present(WebGLFramebufferJS*, layers::TextureType,
|
||||
const bool webvr = false);
|
||||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebufferJS*,
|
||||
const bool webvr = false);
|
||||
RefPtr<gfx::SourceSurface> GetFrontBufferSnapshot(
|
||||
bool requireAlphaPremult = true) override;
|
||||
|
||||
void ClearVRSwapChain();
|
||||
|
||||
private:
|
||||
RefPtr<gfx::DataSourceSurface> BackBufferSnapshot();
|
||||
void DoReadPixels(const webgl::ReadPixelsDesc&, Range<uint8_t>) const;
|
||||
|
|
|
@ -107,8 +107,8 @@ void HostWebGLContext::JsWarning(const std::string& text) const {
|
|||
}
|
||||
|
||||
Maybe<layers::SurfaceDescriptor> HostWebGLContext::GetFrontBuffer(
|
||||
const ObjectId fb) const {
|
||||
return mContext->GetFrontBuffer(AutoResolve(fb));
|
||||
const ObjectId xrFb, const bool webvr) const {
|
||||
return mContext->GetFrontBuffer(AutoResolve(xrFb), webvr);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
|
|
@ -184,15 +184,19 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
|
|||
mContext->SetCompositableHost(compositableHost);
|
||||
}
|
||||
|
||||
void Present(const ObjectId fb, const layers::TextureType t) const {
|
||||
return (void)mContext->Present(AutoResolve(fb), t);
|
||||
void Present(const ObjectId xrFb, const layers::TextureType t,
|
||||
const bool webvr) const {
|
||||
return (void)mContext->Present(AutoResolve(xrFb), t, webvr);
|
||||
}
|
||||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId fb) const;
|
||||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb,
|
||||
const bool webvr) const;
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot() const {
|
||||
return mContext->GetFrontBufferSnapshot();
|
||||
}
|
||||
|
||||
void ClearVRSwapChain() { mContext->ClearVRSwapChain(); }
|
||||
|
||||
void Resize(const uvec2& size) { return mContext->Resize(size); }
|
||||
|
||||
uvec2 DrawingBufferSize() { return mContext->DrawingBufferSize(); }
|
||||
|
|
|
@ -972,16 +972,20 @@ bool WebGLContext::PresentIntoXR(gl::SwapChain& swapChain,
|
|||
return true;
|
||||
}
|
||||
|
||||
void WebGLContext::Present(WebGLFramebuffer* const fb,
|
||||
const layers::TextureType consumerType) {
|
||||
void WebGLContext::Present(WebGLFramebuffer* const xrFb,
|
||||
const layers::TextureType consumerType,
|
||||
const bool webvr) {
|
||||
const FuncScope funcScope(*this, "<Present>");
|
||||
if (IsContextLost()) return;
|
||||
|
||||
auto swapChain = &mSwapChain;
|
||||
auto swapChain = webvr ? &mWebVRSwapChain : &mSwapChain;
|
||||
if (xrFb) {
|
||||
swapChain = &xrFb->mOpaqueSwapChain;
|
||||
}
|
||||
const gl::MozFramebuffer* maybeFB = nullptr;
|
||||
if (fb) {
|
||||
swapChain = &fb->mOpaqueSwapChain;
|
||||
maybeFB = fb->mOpaque.get();
|
||||
if (xrFb) {
|
||||
swapChain = &xrFb->mOpaqueSwapChain;
|
||||
maybeFB = xrFb->mOpaque.get();
|
||||
} else {
|
||||
mResolvedDefaultFB = nullptr;
|
||||
}
|
||||
|
@ -1006,10 +1010,10 @@ void WebGLContext::Present(WebGLFramebuffer* const fb,
|
|||
}
|
||||
|
||||
Maybe<layers::SurfaceDescriptor> WebGLContext::GetFrontBuffer(
|
||||
WebGLFramebuffer* const fb) {
|
||||
auto swapChain = &mSwapChain;
|
||||
if (fb) {
|
||||
swapChain = &fb->mOpaqueSwapChain;
|
||||
WebGLFramebuffer* const xrFb, const bool webvr) {
|
||||
auto swapChain = webvr ? &mWebVRSwapChain : &mSwapChain;
|
||||
if (xrFb) {
|
||||
swapChain = &xrFb->mOpaqueSwapChain;
|
||||
}
|
||||
const auto& front = swapChain->FrontBuffer();
|
||||
if (!front) return {};
|
||||
|
@ -1090,6 +1094,8 @@ RefPtr<gfx::DataSourceSurface> WebGLContext::GetFrontBufferSnapshot() {
|
|||
return surf;
|
||||
}
|
||||
|
||||
void WebGLContext::ClearVRSwapChain() { mWebVRSwapChain.ClearPool(); }
|
||||
|
||||
// ------------------------
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> GetTempSurface(const gfx::IntSize& aSize,
|
||||
|
|
|
@ -483,13 +483,15 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
// Present to compositor
|
||||
private:
|
||||
bool PresentInto(gl::SwapChain& swapChain);
|
||||
bool PresentIntoXR(gl::SwapChain& swapChain, const gl::MozFramebuffer& fb);
|
||||
bool PresentIntoXR(gl::SwapChain& swapChain, const gl::MozFramebuffer& xrFb);
|
||||
|
||||
public:
|
||||
void Present(WebGLFramebuffer*, layers::TextureType);
|
||||
void Present(WebGLFramebuffer*, layers::TextureType, const bool webvr);
|
||||
RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot();
|
||||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*);
|
||||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*,
|
||||
const bool webvr);
|
||||
|
||||
void ClearVRSwapChain();
|
||||
void RunContextLossTimer();
|
||||
void CheckForContextLoss();
|
||||
|
||||
|
@ -1214,6 +1216,7 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB;
|
||||
|
||||
gl::SwapChain mSwapChain;
|
||||
gl::SwapChain mWebVRSwapChain;
|
||||
|
||||
// --
|
||||
|
||||
|
|
|
@ -172,6 +172,7 @@ DEFINE_ASYNC(HostWebGLContext::EndQuery)
|
|||
DEFINE_ASYNC(HostWebGLContext::QueryCounter)
|
||||
DEFINE_SYNC(HostWebGLContext::GetQueryParameter)
|
||||
DEFINE_ASYNC(HostWebGLContext::SetFramebufferIsInOpaqueRAF)
|
||||
DEFINE_ASYNC(HostWebGLContext::ClearVRSwapChain)
|
||||
|
||||
#undef DEFINE_METHOD_HELPER
|
||||
#undef DEFINE_ASYNC
|
||||
|
|
|
@ -16,16 +16,44 @@ namespace mozilla::gl {
|
|||
// -
|
||||
// SwapChainPresenter
|
||||
|
||||
// We need to apply pooling on Android because of the AndroidSurface slow
|
||||
// destructor bugs. They cause a noticeable performance hit. See bug
|
||||
// #1646073.
|
||||
static constexpr size_t kPoolSize =
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
4;
|
||||
#else
|
||||
0;
|
||||
#endif
|
||||
|
||||
UniquePtr<SwapChainPresenter> SwapChain::Acquire(const gfx::IntSize& size) {
|
||||
MOZ_ASSERT(mFactory);
|
||||
auto back = mFactory->CreateShared(size);
|
||||
if (!back) return nullptr;
|
||||
|
||||
std::shared_ptr<SharedSurface> surf;
|
||||
if (!mPool.empty() && mPool.front()->mDesc.size != size) {
|
||||
mPool = {};
|
||||
}
|
||||
if (kPoolSize && mPool.size() == kPoolSize) {
|
||||
surf = mPool.front();
|
||||
mPool.pop();
|
||||
}
|
||||
if (!surf) {
|
||||
auto uniquePtrSurf = mFactory->CreateShared(size);
|
||||
if (!uniquePtrSurf) return nullptr;
|
||||
surf.reset(uniquePtrSurf.release());
|
||||
}
|
||||
mPool.push(surf);
|
||||
while (mPool.size() > kPoolSize) {
|
||||
mPool.pop();
|
||||
}
|
||||
|
||||
auto ret = MakeUnique<SwapChainPresenter>(*this);
|
||||
ret->SwapBackBuffer(std::move(back));
|
||||
ret->SwapBackBuffer(std::move(surf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SwapChain::ClearPool() { mPool = {}; }
|
||||
|
||||
// -
|
||||
|
||||
SwapChainPresenter::SwapChainPresenter(SwapChain& swapChain)
|
||||
|
@ -45,8 +73,8 @@ SwapChainPresenter::~SwapChainPresenter() {
|
|||
}
|
||||
}
|
||||
|
||||
UniquePtr<SharedSurface> SwapChainPresenter::SwapBackBuffer(
|
||||
UniquePtr<SharedSurface> back) {
|
||||
std::shared_ptr<SharedSurface> SwapChainPresenter::SwapBackBuffer(
|
||||
std::shared_ptr<SharedSurface> back) {
|
||||
if (mBackBuffer) {
|
||||
mBackBuffer->UnlockProd();
|
||||
mBackBuffer->ProducerRelease();
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "SurfaceTypes.h"
|
||||
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
|
@ -33,7 +36,7 @@ class SwapChainPresenter final {
|
|||
friend class SwapChain;
|
||||
|
||||
SwapChain* mSwapChain;
|
||||
UniquePtr<SharedSurface> mBackBuffer;
|
||||
std::shared_ptr<SharedSurface> mBackBuffer;
|
||||
|
||||
public:
|
||||
explicit SwapChainPresenter(SwapChain& swapChain);
|
||||
|
@ -41,7 +44,7 @@ class SwapChainPresenter final {
|
|||
|
||||
const auto& BackBuffer() const { return mBackBuffer; }
|
||||
|
||||
UniquePtr<SharedSurface> SwapBackBuffer(UniquePtr<SharedSurface>);
|
||||
std::shared_ptr<SharedSurface> SwapBackBuffer(std::shared_ptr<SharedSurface>);
|
||||
GLuint Fb() const;
|
||||
};
|
||||
|
||||
|
@ -54,13 +57,17 @@ class SwapChain final {
|
|||
UniquePtr<SurfaceFactory> mFactory;
|
||||
|
||||
private:
|
||||
UniquePtr<SharedSurface> mFrontBuffer;
|
||||
std::shared_ptr<SharedSurface> mFrontBuffer;
|
||||
SwapChainPresenter* mPresenter = nullptr;
|
||||
|
||||
private:
|
||||
std::queue<std::shared_ptr<SharedSurface>> mPool;
|
||||
|
||||
public:
|
||||
SwapChain();
|
||||
virtual ~SwapChain();
|
||||
|
||||
void ClearPool();
|
||||
const auto& FrontBuffer() const { return mFrontBuffer; }
|
||||
UniquePtr<SwapChainPresenter> Acquire(const gfx::IntSize&);
|
||||
};
|
||||
|
|
|
@ -92,8 +92,8 @@ void VRLayerChild::SubmitFrame(const VRDisplayInfo& aDisplayInfo) {
|
|||
texType = layers::TextureType::AndroidNativeWindow;
|
||||
}
|
||||
|
||||
webgl->Present(mFramebuffer, texType);
|
||||
mThisFrameTextureDesc = webgl->GetFrontBuffer(mFramebuffer);
|
||||
webgl->Present(mFramebuffer, texType, true);
|
||||
mThisFrameTextureDesc = webgl->GetFrontBuffer(mFramebuffer, true);
|
||||
}
|
||||
|
||||
mLastSubmittedFrameId = frameId;
|
||||
|
@ -112,6 +112,10 @@ bool VRLayerChild::IsIPCOpen() { return mIPCOpen; }
|
|||
void VRLayerChild::ClearSurfaces() {
|
||||
mThisFrameTextureDesc = Nothing();
|
||||
mLastFrameTextureDesc = Nothing();
|
||||
const auto& webgl = mCanvasElement->GetWebGLContext();
|
||||
if (!mFramebuffer && webgl) {
|
||||
webgl->ClearVRSwapChain();
|
||||
}
|
||||
}
|
||||
|
||||
void VRLayerChild::ActorDestroy(ActorDestroyReason aWhy) { mIPCOpen = false; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче