Bug 1957001 - Use FenceD3D11 for shnchronization in DXGIYCbCrTextureData r=media-playback-reviewers,gfx-reviewers,alwu,lsalzman
DXGIYCbCrTextureData uses keyed mutex for synchronization. But it is inefficient than FenceD3D11. And it caused the performance problem when DXGIYCbCrTextureData has multiple users like Bug 1956305
Differential Revision: https://phabricator.services.mozilla.com/D243622
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "Units.h"
|
||||
|
||||
@@ -202,13 +203,7 @@ class RenderCompositor {
|
||||
}
|
||||
virtual bool MaybeProcessScreenshotQueue() { return false; }
|
||||
|
||||
// Returns FileDescriptor of release fence.
|
||||
// Release fence is a fence that is used for waiting until usage/composite of
|
||||
// AHardwareBuffer is ended. The fence is delivered to client side via
|
||||
// ImageBridge. It is used only on android.
|
||||
virtual UniqueFileHandle GetAndResetReleaseFence() {
|
||||
return UniqueFileHandle();
|
||||
}
|
||||
virtual RefPtr<layers::Fence> GetAndResetReleaseFence() { return nullptr; }
|
||||
|
||||
virtual bool IsPaused() { return false; }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/StackArray.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
#include "mozilla/layers/HelpersD3D11.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
@@ -124,11 +125,14 @@ bool RenderCompositorANGLE::Initialize(nsACString& aError) {
|
||||
MOZ_ASSERT(mEGLConfig);
|
||||
|
||||
mDevice = GetDeviceOfEGLDisplay(aError);
|
||||
|
||||
if (!mDevice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layers::FenceD3D11::IsSupported(mDevice)) {
|
||||
mFence = layers::FenceD3D11::Create(mDevice);
|
||||
}
|
||||
|
||||
mDevice->GetImmediateContext(getter_AddRefs(mCtx));
|
||||
if (!mCtx) {
|
||||
aError.Assign("RcANGLE(get immediate context failed)"_ns);
|
||||
@@ -462,6 +466,10 @@ RenderedFrameId RenderCompositorANGLE::EndFrame(
|
||||
RenderedFrameId frameId = GetNextRenderFrameId();
|
||||
InsertGraphicsCommandsFinishedWaitQuery(frameId);
|
||||
|
||||
if (mFence) {
|
||||
mFence->IncrementAndSignal();
|
||||
}
|
||||
|
||||
if (!UseCompositor()) {
|
||||
auto start = TimeStamp::Now();
|
||||
if (auto* fxrHandler = mWidget->AsWindows()->GetFxrOutputHandler()) {
|
||||
@@ -564,6 +572,14 @@ RenderedFrameId RenderCompositorANGLE::EndFrame(
|
||||
return frameId;
|
||||
}
|
||||
|
||||
RefPtr<layers::Fence> RenderCompositorANGLE::GetAndResetReleaseFence() {
|
||||
RefPtr<layers::Fence> fence;
|
||||
if (mFence) {
|
||||
fence = mFence->CloneFromHandle();
|
||||
}
|
||||
return fence.forget();
|
||||
}
|
||||
|
||||
bool RenderCompositorANGLE::WaitForGPU() {
|
||||
// Note: this waits on the query we inserted in the previous frame,
|
||||
// not the one we just inserted now. Example:
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace gl {
|
||||
class GLLibraryEGL;
|
||||
} // namespace gl
|
||||
|
||||
namespace layers {
|
||||
class FenceD3D11;
|
||||
} // namespace layers
|
||||
|
||||
namespace wr {
|
||||
|
||||
class DCLayerTree;
|
||||
@@ -113,6 +117,8 @@ class RenderCompositorANGLE final : public RenderCompositor {
|
||||
bool RequestFullRender() override;
|
||||
uint32_t GetMaxPartialPresentRects() override;
|
||||
|
||||
RefPtr<layers::Fence> GetAndResetReleaseFence() override;
|
||||
|
||||
bool MaybeReadback(const gfx::IntSize& aReadbackSize,
|
||||
const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer,
|
||||
@@ -169,6 +175,7 @@ class RenderCompositorANGLE final : public RenderCompositor {
|
||||
bool mFirstPresent = true;
|
||||
// Wether we're currently using alpha.
|
||||
bool mSwapChainUsingAlpha = false;
|
||||
RefPtr<layers::FenceD3D11> mFence;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -123,7 +123,7 @@ RenderedFrameId RenderCompositorEGL::EndFrame(
|
||||
if (sync) {
|
||||
int fenceFd = egl->fDupNativeFenceFDANDROID(sync);
|
||||
if (fenceFd >= 0) {
|
||||
mReleaseFenceFd = UniqueFileHandle(fenceFd);
|
||||
mReleaseFence = new layers::FenceFileHandle(UniqueFileHandle(fenceFd));
|
||||
}
|
||||
egl->fDestroySync(sync);
|
||||
sync = nullptr;
|
||||
@@ -259,12 +259,12 @@ void RenderCompositorEGL::DestroyEGLSurface() {
|
||||
}
|
||||
}
|
||||
|
||||
UniqueFileHandle RenderCompositorEGL::GetAndResetReleaseFence() {
|
||||
RefPtr<layers::Fence> RenderCompositorEGL::GetAndResetReleaseFence() {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
MOZ_ASSERT(!layers::AndroidHardwareBufferApi::Get() || mReleaseFenceFd);
|
||||
return std::move(mReleaseFenceFd);
|
||||
MOZ_ASSERT(!layers::AndroidHardwareBufferApi::Get() || mReleaseFence);
|
||||
return mReleaseFence.forget();
|
||||
#else
|
||||
return UniqueFileHandle();
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class RenderCompositorEGL : public RenderCompositor {
|
||||
void SetBufferDamageRegion(const wr::DeviceIntRect* aRects,
|
||||
size_t aNumRects) override;
|
||||
|
||||
UniqueFileHandle GetAndResetReleaseFence() override;
|
||||
RefPtr<layers::Fence> GetAndResetReleaseFence() override;
|
||||
|
||||
protected:
|
||||
EGLSurface CreateEGLSurface();
|
||||
@@ -66,7 +66,7 @@ class RenderCompositorEGL : public RenderCompositor {
|
||||
// Release fence is a fence that is used for waiting until usage/composite of
|
||||
// AHardwareBuffer is ended. The fence is delivered to client side via
|
||||
// ImageBridge. It is used only on android.
|
||||
UniqueFileHandle mReleaseFenceFd;
|
||||
RefPtr<layers::Fence> mReleaseFence;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11TextureMap.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
|
||||
namespace mozilla {
|
||||
@@ -472,8 +473,10 @@ bool RenderDXGITextureHost::SyncObjectNeeded() {
|
||||
|
||||
RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
|
||||
RefPtr<gfx::FileHandleWrapper> (&aHandles)[3],
|
||||
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorDepth aColorDepth,
|
||||
gfx::ColorRange aColorRange, gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr)
|
||||
const gfx::YUVColorSpace aYUVColorSpace, const gfx::ColorDepth aColorDepth,
|
||||
const gfx::ColorRange aColorRange, const gfx::IntSize aSizeY,
|
||||
const gfx::IntSize aSizeCbCr,
|
||||
const layers::GpuProcessFencesHolderId aFencesHolderId)
|
||||
: mHandles{aHandles[0], aHandles[1], aHandles[2]},
|
||||
mSurfaces{0},
|
||||
mStreams{0},
|
||||
@@ -483,7 +486,7 @@ RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
|
||||
mColorRange(aColorRange),
|
||||
mSizeY(aSizeY),
|
||||
mSizeCbCr(aSizeCbCr),
|
||||
mLocked(false) {
|
||||
mFencesHolderId(aFencesHolderId) {
|
||||
MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
|
||||
// Assume the chroma planes are rounded up if the luma plane is odd sized.
|
||||
MOZ_ASSERT((mSizeCbCr.width == mSizeY.width ||
|
||||
@@ -631,25 +634,20 @@ bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
mTextures[i]->QueryInterface(
|
||||
(IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutexs[i]));
|
||||
}
|
||||
mDevice = aDevice;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderDXGIYCbCrTextureHost::LockInternal() {
|
||||
if (!mLocked) {
|
||||
if (mKeyedMutexs[0]) {
|
||||
for (const auto& mutex : mKeyedMutexs) {
|
||||
HRESULT hr = mutex->AcquireSync(0, 10000);
|
||||
if (hr != S_OK) {
|
||||
gfxCriticalError()
|
||||
<< "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr="
|
||||
<< gfx::hexa(hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto* fenceHolderMap = layers::GpuProcessD3D11FencesHolderMap::Get();
|
||||
if (!fenceHolderMap) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return false;
|
||||
}
|
||||
if (!fenceHolderMap->WaitWriteFence(mFencesHolderId, mDevice)) {
|
||||
return false;
|
||||
}
|
||||
mLocked = true;
|
||||
}
|
||||
@@ -688,11 +686,6 @@ wr::WrExternalImage RenderDXGIYCbCrTextureHost::Lock(uint8_t aChannelIndex,
|
||||
|
||||
void RenderDXGIYCbCrTextureHost::Unlock() {
|
||||
if (mLocked) {
|
||||
if (mKeyedMutexs[0]) {
|
||||
for (const auto& mutex : mKeyedMutexs) {
|
||||
mutex->ReleaseSync(0);
|
||||
}
|
||||
}
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
@@ -736,7 +729,6 @@ void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
mTextureHandles[i] = 0;
|
||||
mTextures[i] = nullptr;
|
||||
mKeyedMutexs[i] = nullptr;
|
||||
|
||||
if (mSurfaces[i]) {
|
||||
egl->fDestroySurface(mSurfaces[i]);
|
||||
@@ -748,6 +740,7 @@ void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
|
||||
}
|
||||
}
|
||||
}
|
||||
mDevice = nullptr;
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -139,8 +139,10 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
|
||||
public:
|
||||
explicit RenderDXGIYCbCrTextureHost(
|
||||
RefPtr<gfx::FileHandleWrapper> (&aHandles)[3],
|
||||
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorDepth aColorDepth,
|
||||
gfx::ColorRange aColorRange, gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr);
|
||||
const gfx::YUVColorSpace aYUVColorSpace,
|
||||
const gfx::ColorDepth aColorDepth, const gfx::ColorRange aColorRange,
|
||||
const gfx::IntSize aSizeY, const gfx::IntSize aSizeCbCr,
|
||||
const layers::GpuProcessFencesHolderId aFencesHolderId);
|
||||
|
||||
RenderDXGIYCbCrTextureHost* AsRenderDXGIYCbCrTextureHost() override {
|
||||
return this;
|
||||
@@ -200,7 +202,7 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
|
||||
|
||||
RefPtr<gfx::FileHandleWrapper> mHandles[3];
|
||||
RefPtr<ID3D11Texture2D> mTextures[3];
|
||||
RefPtr<IDXGIKeyedMutex> mKeyedMutexs[3];
|
||||
RefPtr<ID3D11Device> mDevice;
|
||||
|
||||
EGLSurface mSurfaces[3];
|
||||
EGLStreamKHR mStreams[3];
|
||||
@@ -212,13 +214,14 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
|
||||
RefPtr<ID3D11DeviceContext> mDeviceContext;
|
||||
RefPtr<ID3D11Texture2D> mCpuTexture[3];
|
||||
|
||||
gfx::YUVColorSpace mYUVColorSpace;
|
||||
gfx::ColorDepth mColorDepth;
|
||||
gfx::ColorRange mColorRange;
|
||||
gfx::IntSize mSizeY;
|
||||
gfx::IntSize mSizeCbCr;
|
||||
const gfx::YUVColorSpace mYUVColorSpace;
|
||||
const gfx::ColorDepth mColorDepth;
|
||||
const gfx::ColorRange mColorRange;
|
||||
const gfx::IntSize mSizeY;
|
||||
const gfx::IntSize mSizeCbCr;
|
||||
const layers::GpuProcessFencesHolderId mFencesHolderId;
|
||||
|
||||
bool mLocked;
|
||||
bool mLocked = false;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorManagerParent.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/layers/WebRenderBridgeParent.h"
|
||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||
#include "mozilla/layers/SurfacePool.h"
|
||||
@@ -866,10 +867,10 @@ void RenderThread::UpdateAndRender(
|
||||
renderer->GetCompositorBridge(), info, aStartId,
|
||||
aStartTime, start, end, aRender, *aStats));
|
||||
|
||||
UniqueFileHandle fenceFd;
|
||||
RefPtr<layers::Fence> fence;
|
||||
|
||||
if (latestFrameId.IsValid()) {
|
||||
fenceFd = renderer->GetAndResetReleaseFence();
|
||||
fence = renderer->GetAndResetReleaseFence();
|
||||
|
||||
// Wait for GPU after posting NotifyDidRender, since the wait is not
|
||||
// necessary for the NotifyDidRender.
|
||||
@@ -898,7 +899,7 @@ void RenderThread::UpdateAndRender(
|
||||
// this code at all; it would bail out at the mRenderers.find check above.
|
||||
MOZ_ASSERT(pipelineMgr);
|
||||
pipelineMgr->NotifyPipelinesUpdated(info, latestFrameId, lastCompletedFrameId,
|
||||
std::move(fenceFd));
|
||||
std::move(fence));
|
||||
}
|
||||
|
||||
void RenderThread::Pause(wr::WindowId aWindowId) {
|
||||
|
||||
@@ -36,6 +36,7 @@ class GLContext;
|
||||
} // namespace gl
|
||||
namespace layers {
|
||||
class CompositorBridgeParent;
|
||||
class Fence;
|
||||
class ShaderProgramOGLsHolder;
|
||||
class SurfacePool;
|
||||
} // namespace layers
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/ProfilerScreenshots.h"
|
||||
#include "mozilla/webrender/RenderCompositor.h"
|
||||
@@ -280,7 +281,7 @@ void RendererOGL::WaitForGPU() {
|
||||
}
|
||||
}
|
||||
|
||||
UniqueFileHandle RendererOGL::GetAndResetReleaseFence() {
|
||||
RefPtr<layers::Fence> RendererOGL::GetAndResetReleaseFence() {
|
||||
return mCompositor->GetAndResetReleaseFence();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ class GLContext;
|
||||
|
||||
namespace layers {
|
||||
class CompositorBridgeParent;
|
||||
class Fence;
|
||||
class SyncObjectHost;
|
||||
} // namespace layers
|
||||
|
||||
@@ -70,7 +71,7 @@ class RendererOGL {
|
||||
void WaitForGPU();
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
UniqueFileHandle GetAndResetReleaseFence();
|
||||
RefPtr<layers::Fence> GetAndResetReleaseFence();
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
RenderedFrameId GetLastCompletedFrameId();
|
||||
|
||||
Reference in New Issue
Block a user