Bug 1865984 - Add FenceD3D11 handling to WebGL on Windows r=gfx-reviewers,lsalzman,aosmond

ID3D11Fence could get better performance than keyed mutex. And ID3D11Fence  handling is necessary to support overlay.

Differential Revision: https://phabricator.services.mozilla.com/D194325
This commit is contained in:
sotaro
2025-04-10 20:47:40 +00:00
parent 0644250f84
commit 176876046f
2 changed files with 82 additions and 21 deletions

View File

@@ -10,6 +10,8 @@
#include "GLLibraryEGL.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/gfx/FileHandleWrapper.h"
#include "mozilla/layers/CompositeProcessD3D11FencesHolderMap.h"
#include "mozilla/layers/FenceD3D11.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
namespace mozilla {
@@ -71,12 +73,19 @@ SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc& desc) {
}
// Create a texture in case we need to readback.
auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
const bool useFence =
fencesHolderMap && layers::FenceD3D11::IsSupported(device);
const DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM;
CD3D11_TEXTURE2D_DESC texDesc(
format, desc.size.width, desc.size.height, 1, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
if (useFence) {
texDesc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
} else {
texDesc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
}
RefPtr<ID3D11Texture2D> texture2D;
auto hr =
@@ -100,10 +109,20 @@ SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc& desc) {
RefPtr<gfx::FileHandleWrapper> handle =
new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle));
Maybe<layers::CompositeProcessFencesHolderId> fencesHolderId;
RefPtr<layers::FenceD3D11> fence;
RefPtr<IDXGIKeyedMutex> keyedMutex;
texture2D->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(keyedMutex));
if (!keyedMutex) {
return nullptr;
if (useFence) {
fence = layers::FenceD3D11::Create(device);
if (!fence) {
return nullptr;
}
fencesHolderId = Some(layers::CompositeProcessFencesHolderId::GetNext());
} else {
texture2D->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(keyedMutex));
if (!keyedMutex) {
return nullptr;
}
}
const auto& config = gle->mSurfaceConfig;
@@ -113,19 +132,35 @@ SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc& desc) {
CreatePBufferSurface(egl.get(), config, desc.size, texture2D);
if (!pbuffer) return nullptr;
if (useFence) {
auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
fencesHolderMap->Register(fencesHolderId.ref());
}
return AsUnique(new SharedSurface_ANGLEShareHandle(
desc, egl, pbuffer, std::move(handle), keyedMutex));
desc, device, egl, pbuffer, std::move(handle), fencesHolderId, fence,
keyedMutex));
}
SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(
const SharedSurfaceDesc& desc, const std::weak_ptr<EglDisplay>& egl,
EGLSurface pbuffer, RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
const SharedSurfaceDesc& desc, const RefPtr<ID3D11Device> aDevice,
const std::weak_ptr<EglDisplay>& egl, EGLSurface pbuffer,
RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
const Maybe<layers::CompositeProcessFencesHolderId> aFencesHolderId,
const RefPtr<layers::FenceD3D11>& aWriteFence,
const RefPtr<IDXGIKeyedMutex>& keyedMutex)
: SharedSurface(desc, nullptr),
mDevice(aDevice),
mEGL(egl),
mPBuffer(pbuffer),
mSharedHandle(std::move(aSharedHandle)),
mKeyedMutex(keyedMutex) {}
mFencesHolderId(aFencesHolderId),
mWriteFence(std::move(aWriteFence)),
mKeyedMutex(keyedMutex) {
MOZ_ASSERT((mKeyedMutex && mFencesHolderId.isNothing()) ||
(!mKeyedMutex && mFencesHolderId.isSome()));
MOZ_ASSERT_IF(mFencesHolderId.isSome(), mWriteFence);
}
SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() {
const auto& gl = mDesc.gl;
@@ -147,9 +182,15 @@ void SharedSurface_ANGLEShareHandle::LockProdImpl() {
void SharedSurface_ANGLEShareHandle::UnlockProdImpl() {}
void SharedSurface_ANGLEShareHandle::ProducerAcquireImpl() {
HRESULT hr = mKeyedMutex->AcquireSync(0, 10000);
if (hr == WAIT_TIMEOUT) {
MOZ_CRASH("GFX: ANGLE share handle timeout");
if (mFencesHolderId.isSome()) {
auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
fencesHolderMap->WaitAllFencesAndForget(mFencesHolderId.ref(), mDevice);
}
if (mKeyedMutex) {
HRESULT hr = mKeyedMutex->AcquireSync(0, 10000);
if (hr == WAIT_TIMEOUT) {
MOZ_CRASH("GFX: ANGLE share handle timeout");
}
}
}
@@ -159,7 +200,14 @@ void SharedSurface_ANGLEShareHandle::ProducerReleaseImpl() {
// whether we need Flush() or not depends on the ANGLE semantics.
// For now, we'll just do it
gl->fFlush();
mKeyedMutex->ReleaseSync(0);
if (mFencesHolderId.isSome()) {
mWriteFence->IncrementAndSignal();
auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
fencesHolderMap->SetWriteFence(mFencesHolderId.ref(), mWriteFence);
}
if (mKeyedMutex) {
mKeyedMutex->ReleaseSync(0);
}
}
void SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl() {
@@ -167,7 +215,9 @@ void SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl() {
}
void SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl() {
mKeyedMutex->ReleaseSync(0);
if (mKeyedMutex) {
mKeyedMutex->ReleaseSync(0);
}
}
Maybe<layers::SurfaceDescriptor>
@@ -176,8 +226,7 @@ SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor() {
return Some(layers::SurfaceDescriptorD3D10(
mSharedHandle, /* gpuProcessTextureId */ Nothing(),
/* arrayIndex */ 0, format, mDesc.size, mDesc.colorSpace,
gfx::ColorRange::FULL, /* hasKeyedMutex */ true,
/* fencesHolderId */ Nothing()));
gfx::ColorRange::FULL, !!mKeyedMutex, mFencesHolderId));
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -8,9 +8,12 @@
#include <windows.h>
#include <memory>
#include "mozilla/layers/LayersTypes.h"
#include "SharedSurface.h"
struct IDXGIKeyedMutex;
struct ID3D11Device;
struct ID3D11Texture2D;
namespace mozilla {
@@ -19,6 +22,10 @@ namespace gfx {
class FileHandleWrapper;
} // namespace gfx
namespace layers {
class FenceD3D11;
} // namespace layers
namespace gl {
class GLContext;
@@ -26,20 +33,25 @@ class EglDisplay;
class SharedSurface_ANGLEShareHandle final : public SharedSurface {
public:
const RefPtr<ID3D11Device> mDevice;
const std::weak_ptr<EglDisplay> mEGL;
const EGLSurface mPBuffer;
const RefPtr<gfx::FileHandleWrapper> mSharedHandle;
const Maybe<layers::CompositeProcessFencesHolderId> mFencesHolderId;
const RefPtr<layers::FenceD3D11> mWriteFence;
const RefPtr<IDXGIKeyedMutex> mKeyedMutex;
static UniquePtr<SharedSurface_ANGLEShareHandle> Create(
const SharedSurfaceDesc&);
private:
SharedSurface_ANGLEShareHandle(const SharedSurfaceDesc&,
const std::weak_ptr<EglDisplay>& egl,
EGLSurface pbuffer,
RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex);
SharedSurface_ANGLEShareHandle(
const SharedSurfaceDesc&, const RefPtr<ID3D11Device> aDevice,
const std::weak_ptr<EglDisplay>& egl, EGLSurface pbuffer,
RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
const Maybe<layers::CompositeProcessFencesHolderId> aFencesHolderId,
const RefPtr<layers::FenceD3D11>& aWriteFence,
const RefPtr<IDXGIKeyedMutex>& keyedMutex);
public:
virtual ~SharedSurface_ANGLEShareHandle();