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:
Imanol Fernandez 2020-06-17 18:56:16 +00:00
Родитель 10ad51e7e6
Коммит cc77358c6f
10 изменённых файлов: 99 добавлений и 37 удалений

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

@ -413,19 +413,24 @@ void ClientWebGLContext::EndComposition() {
// -
void ClientWebGLContext::Present(WebGLFramebufferJS* const fb,
const layers::TextureType type) {
if (!mIsCanvasDirty && !fb) return;
mIsCanvasDirty = false;
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; }