Bug 1910520 - Add Metal SharedEvent handling around WebRender for compositing IOSurface of WebGPU r=gfx-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D228946
This commit is contained in:
sotaro
2024-12-11 02:00:23 +00:00
parent 34c8691dbb
commit 95ea53535b
26 changed files with 370 additions and 41 deletions

View File

@@ -5,6 +5,8 @@
#include "ExternalTexture.h"
#include "mozilla/webgpu/WebGPUParent.h"
#ifdef XP_WIN
# include "mozilla/webgpu/ExternalTextureD3D11.h"
#endif
@@ -21,19 +23,22 @@ namespace mozilla::webgpu {
// static
UniquePtr<ExternalTexture> ExternalTexture::Create(
const ffi::WGPUGlobal* aContext, const ffi::WGPUDeviceId aDeviceId,
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
const uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage) {
MOZ_ASSERT(aParent);
UniquePtr<ExternalTexture> texture;
#ifdef XP_WIN
texture = ExternalTextureD3D11::Create(aWidth, aHeight, aFormat, aUsage);
#elif defined(MOZ_WIDGET_GTK)
texture = ExternalTextureDMABuf::Create(aContext, aDeviceId, aWidth, aHeight,
auto* context = aParent->GetContext();
texture = ExternalTextureDMABuf::Create(context, aDeviceId, aWidth, aHeight,
aFormat, aUsage);
#elif defined(XP_MACOSX)
texture =
ExternalTextureMacIOSurface::Create(aWidth, aHeight, aFormat, aUsage);
texture = ExternalTextureMacIOSurface::Create(aParent, aDeviceId, aWidth,
aHeight, aFormat, aUsage);
#endif
return texture;
}

View File

@@ -9,6 +9,7 @@
#include "mozilla/gfx/Point.h"
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/webgpu/ffi/wgpu.h"
#include "mozilla/webgpu/WebGPUTypes.h"
namespace mozilla {
@@ -20,13 +21,14 @@ namespace webgpu {
class ExternalTextureDMABuf;
class ExternalTextureMacIOSurface;
class WebGPUParent;
// A texture that can be used by the WebGPU implementation but is created and
// owned by Gecko
class ExternalTexture {
public:
static UniquePtr<ExternalTexture> Create(
const ffi::WGPUGlobal* aContext, const ffi::WGPUDeviceId aDeviceId,
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
const uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage);

View File

@@ -7,12 +7,15 @@
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "mozilla/layers/GpuFenceMTLSharedEvent.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/webgpu/WebGPUParent.h"
namespace mozilla::webgpu {
// static
UniquePtr<ExternalTextureMacIOSurface> ExternalTextureMacIOSurface::Create(
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
const uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage) {
@@ -24,18 +27,23 @@ UniquePtr<ExternalTextureMacIOSurface> ExternalTextureMacIOSurface::Create(
RefPtr<MacIOSurface> surface =
MacIOSurface::CreateIOSurface(aWidth, aHeight, true);
if (!surface) {
gfxCriticalNoteOnce << "Failed to create MacIOSurface: (" << aWidth << ", "
<< aHeight << ")";
return nullptr;
}
return MakeUnique<ExternalTextureMacIOSurface>(aWidth, aHeight, aFormat,
aUsage, std::move(surface));
return MakeUnique<ExternalTextureMacIOSurface>(
aParent, aDeviceId, aWidth, aHeight, aFormat, aUsage, std::move(surface));
}
ExternalTextureMacIOSurface::ExternalTextureMacIOSurface(
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
const uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage, RefPtr<MacIOSurface>&& aSurface)
: ExternalTexture(aWidth, aHeight, aFormat, aUsage),
mParent(aParent),
mDeviceId(aDeviceId),
mSurface(std::move(aSurface)) {}
ExternalTextureMacIOSurface::~ExternalTextureMacIOSurface() {}
@@ -51,9 +59,22 @@ uint32_t ExternalTextureMacIOSurface::GetIOSurfaceId() {
Maybe<layers::SurfaceDescriptor>
ExternalTextureMacIOSurface::ToSurfaceDescriptor(
Maybe<gfx::FenceInfo>& aFenceInfo) {
MOZ_ASSERT(mSubmissionIndex > 0);
RefPtr<layers::GpuFence> gpuFence;
UniquePtr<ffi::WGPUMetalSharedEventHandle> eventHandle(
wgpu_server_get_device_fence_metal_shared_event(mParent->GetContext(),
mDeviceId));
if (eventHandle) {
gpuFence = layers::GpuFenceMTLSharedEvent::Create(std::move(eventHandle),
mSubmissionIndex);
} else {
gfxCriticalNoteOnce << "Failed to get MetalSharedEventHandle";
}
return Some(layers::SurfaceDescriptorMacIOSurface(
mSurface->GetIOSurfaceID(), !mSurface->HasAlpha(),
mSurface->GetYUVColorSpace()));
mSurface->GetYUVColorSpace(), std::move(gpuFence)));
}
void ExternalTextureMacIOSurface::GetSnapshot(const ipc::Shmem& aDestShmem,

View File

@@ -7,6 +7,7 @@
#define GPU_ExternalTextureMacIOSurface_H_
#include "mozilla/gfx/FileHandleWrapper.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/webgpu/ExternalTexture.h"
class MacIOSurface;
@@ -18,11 +19,14 @@ namespace webgpu {
class ExternalTextureMacIOSurface final : public ExternalTexture {
public:
static UniquePtr<ExternalTextureMacIOSurface> Create(
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
const uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage);
ExternalTextureMacIOSurface(const uint32_t aWidth, const uint32_t aHeight,
ExternalTextureMacIOSurface(WebGPUParent* aParent,
const ffi::WGPUDeviceId aDeviceId,
const uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage,
RefPtr<MacIOSurface>&& aSurface);
@@ -43,6 +47,8 @@ class ExternalTextureMacIOSurface final : public ExternalTexture {
uint32_t GetIOSurfaceId();
protected:
const WeakPtr<WebGPUParent> mParent;
const RawId mDeviceId;
const RefPtr<MacIOSurface> mSurface;
};

View File

@@ -1635,7 +1635,7 @@ std::shared_ptr<ExternalTexture> WebGPUParent::CreateExternalTexture(
mExternalTextures.end());
UniquePtr<ExternalTexture> texture = ExternalTexture::Create(
mContext.get(), aDeviceId, aWidth, aHeight, aFormat, aUsage);
this, aDeviceId, aWidth, aHeight, aFormat, aUsage);
if (!texture) {
return nullptr;
}

View File

@@ -178,6 +178,8 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
return ForwardError(Some(aDeviceId), aError);
}
ffi::WGPUGlobal* GetContext() const { return mContext.get(); }
private:
static void MapCallback(uint8_t* aUserData,
ffi::WGPUBufferMapAsyncStatus aStatus);

View File

@@ -95,7 +95,8 @@ Maybe<layers::SurfaceDescriptor>
SharedSurface_IOSurface::ToSurfaceDescriptor() {
const bool isOpaque = false; // RGBA
return Some(layers::SurfaceDescriptorMacIOSurface(
mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace()));
mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace(),
(layers::GpuFence*)nullptr));
}
} // namespace gl

29
gfx/layers/GpuFence.h Normal file
View File

@@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_GpuFence_H
#define MOZILLA_GFX_GpuFence_H
#include "nsISupportsImpl.h"
namespace mozilla {
namespace layers {
class GpuFence {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GpuFence);
virtual bool HasCompleted() = 0;
protected:
GpuFence() = default;
virtual ~GpuFence() = default;
};
} // namespace layers
} // namespace mozilla
#endif /* MOZILLA_GFX_GpuFence_H */

View File

@@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GpuFenceMTLSharedEvent.h"
#include "mozilla/gfx/Logging.h"
namespace mozilla {
namespace layers {
/* static */
RefPtr<GpuFenceMTLSharedEvent> GpuFenceMTLSharedEvent::Create(
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
const uint64_t aFenceValue) {
if (!aSharedEventHandle) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
return new GpuFenceMTLSharedEvent(std::move(aSharedEventHandle), aFenceValue);
}
GpuFenceMTLSharedEvent::GpuFenceMTLSharedEvent(
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
const uint64_t aFenceValue)
: mSharedEventHandle(std::move(aSharedEventHandle)),
mFenceValue(aFenceValue) {}
bool GpuFenceMTLSharedEvent::HasCompleted() {
auto value =
wgpu_server_metal_shared_event_signaled_value(mSharedEventHandle.get());
return value >= mFenceValue;
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_GpuFenceMTLSharedEvent_H
#define MOZILLA_GFX_GpuFenceMTLSharedEvent_H
#include "mozilla/layers/GpuFence.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/webgpu/ffi/wgpu.h"
#include "mozilla/webgpu/WebGPUTypes.h"
namespace mozilla {
namespace webgpu {
namespace ffi {
struct WGPUMetalSharedEventHandle;
}
} // namespace webgpu
namespace layers {
class GpuFenceMTLSharedEvent : public GpuFence {
public:
static RefPtr<GpuFenceMTLSharedEvent> Create(
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
const uint64_t aFenceValue);
bool HasCompleted() override;
protected:
GpuFenceMTLSharedEvent(
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
const uint64_t aFenceValue);
virtual ~GpuFenceMTLSharedEvent() = default;
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle> mSharedEventHandle;
const uint64_t mFenceValue;
};
} // namespace layers
} // namespace mozilla
#endif /* MOZILLA_GFX_GpuFenceMTLSharedEvent_H */

View File

@@ -28,6 +28,7 @@ class RenderTextureHost;
namespace layers {
class GpuFence;
class NativeLayer;
class NativeLayerCA;
class NativeLayerWayland;
@@ -235,6 +236,8 @@ class NativeLayer {
virtual void AttachExternalImage(wr::RenderTextureHost* aExternalImage) = 0;
virtual GpuFence* GetGpuFence() = 0;
protected:
virtual ~NativeLayer() = default;
};

View File

@@ -268,6 +268,7 @@ class NativeLayerCA : public NativeLayer {
void DumpLayer(std::ostream& aOutputStream);
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
GpuFence* GetGpuFence() override;
void SetRootWindowIsFullscreen(bool aFullscreen);

View File

@@ -937,6 +937,22 @@ void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
});
}
GpuFence* NativeLayerCA::GetGpuFence() {
if (!mTextureHost) {
return nullptr;
}
wr::RenderMacIOSurfaceTextureHost* texture =
mTextureHost->AsRenderMacIOSurfaceTextureHost();
if (!texture) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
gfxCriticalNoteOnce << "ExternalImage is not RenderMacIOSurfaceTextureHost";
return nullptr;
}
return texture->GetGpuFence();
}
bool NativeLayerCA::IsVideo(const MutexAutoLock& aProofOfLock) {
// If we have a texture host, we've checked to see if it's providing video.
// And if we don't have a texture host, it isn't video, so we just check

View File

@@ -125,6 +125,7 @@ class NativeLayerWayland final : public NativeLayer {
bool SurfaceIsFlipped() override;
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
GpuFence* GetGpuFence() override { return nullptr; }
void Commit();
void Unmap();

View File

@@ -29,6 +29,7 @@
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/FocusTarget.h"
#include "mozilla/layers/GeckoContentControllerTypes.h"
#include "mozilla/layers/GpuFence.h"
#include "mozilla/layers/KeyboardMap.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/MatrixMessage.h"
@@ -1172,6 +1173,39 @@ struct ParamTraits<mozilla::layers::DoubleTapToZoomMetrics> {
} /* namespace IPC */
namespace mozilla {
namespace ipc {
template <>
struct IPDLParamTraits<layers::GpuFence*> {
static void Write(IPC::MessageWriter* aWriter, IProtocol* aActor,
layers::GpuFence* aParam) {
if (aParam) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
WriteIPDLParam(aWriter, aActor, false);
}
static bool Read(IPC::MessageReader* aReader, IProtocol* aActor,
RefPtr<layers::GpuFence>* aResult) {
*aResult = nullptr;
bool notnull = false;
if (!ReadIPDLParam(aReader, aActor, &notnull)) {
return false;
}
if (!notnull) {
return true;
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return true;
}
};
} // namespace ipc
} // namespace mozilla
#define DEFINE_SERVO_PARAMTRAITS(ty_) \
MOZ_DEFINE_RUST_PARAMTRAITS(mozilla::ty_, Servo_##ty_##_Serialize, \
Servo_##ty_##_Deserialize)

View File

@@ -29,6 +29,7 @@ using gfxImageFormat from "gfxTypes.h";
using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
[RefCounted] using mozilla::layers::GpuFence from "mozilla/layers/GpuFence.h";
using mozilla::layers::GpuProcessTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::GpuProcessQueryId from "mozilla/layers/LayersTypes.h";
using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
@@ -67,6 +68,7 @@ namespace layers {
uint32_t surfaceId;
bool isOpaque;
YUVColorSpace yUVColorSpace;
nullable GpuFence gpuFence;
};
[Comparable] struct SurfaceDescriptorDMABuf {

View File

@@ -145,6 +145,7 @@ EXPORTS.mozilla.layers += [
"D3D11ZeroCopyTextureImage.h",
"DirectionUtils.h",
"Effects.h",
"GpuFence.h",
"ImageDataSerializer.h",
"ipc/ActiveResource.h",
"ipc/APZChild.h",
@@ -263,6 +264,7 @@ if CONFIG["MOZ_WAYLAND"]:
if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
EXPORTS.mozilla.layers += [
"GpuFenceMTLSharedEvent.h",
"NativeLayerCA.h",
"SurfacePoolCA.h",
]
@@ -275,6 +277,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
"SurfacePoolCA.mm",
]
SOURCES += [
"GpuFenceMTLSharedEvent.cpp",
"MacIOSurfaceHelpers.cpp",
"MacIOSurfaceImage.cpp",
]

View File

@@ -50,17 +50,19 @@ MacIOSurfaceTextureData* MacIOSurfaceTextureData::Create(const IntSize& aSize,
}
bool MacIOSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
aOutDescriptor = SurfaceDescriptorMacIOSurface(mSurface->GetIOSurfaceID(),
!mSurface->HasAlpha(),
mSurface->GetYUVColorSpace());
RefPtr<layers::GpuFence> gpuFence;
aOutDescriptor = SurfaceDescriptorMacIOSurface(
mSurface->GetIOSurfaceID(), !mSurface->HasAlpha(),
mSurface->GetYUVColorSpace(), std::move(gpuFence));
return true;
}
void MacIOSurfaceTextureData::GetSubDescriptor(
RemoteDecoderVideoSubDescriptor* const aOutDesc) {
*aOutDesc = SurfaceDescriptorMacIOSurface(mSurface->GetIOSurfaceID(),
!mSurface->HasAlpha(),
mSurface->GetYUVColorSpace());
RefPtr<layers::GpuFence> gpuFence;
*aOutDesc = SurfaceDescriptorMacIOSurface(
mSurface->GetIOSurfaceID(), !mSurface->HasAlpha(),
mSurface->GetYUVColorSpace(), std::move(gpuFence));
}
void MacIOSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const {

View File

@@ -7,6 +7,7 @@
#include "MacIOSurfaceTextureHostOGL.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "mozilla/layers/GpuFence.h"
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/webrender/WebRenderAPI.h"
@@ -24,6 +25,7 @@ MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(
if (!mSurface) {
gfxCriticalNote << "Failed to look up MacIOSurface";
}
mGpuFence = aDescriptor.gpuFence();
}
MacIOSurfaceTextureHostOGL::~MacIOSurfaceTextureHostOGL() {
@@ -74,7 +76,7 @@ void MacIOSurfaceTextureHostOGL::CreateRenderTexture(
MOZ_ASSERT(mExternalImageId.isSome());
RefPtr<wr::RenderTextureHost> texture =
new wr::RenderMacIOSurfaceTextureHost(GetMacIOSurface());
new wr::RenderMacIOSurfaceTextureHost(GetMacIOSurface(), mGpuFence);
bool isDRM = (bool)(mFlags & TextureFlags::DRM_SOURCE);
texture->SetIsFromDRMSource(isDRM);

View File

@@ -17,6 +17,8 @@ class MacIOSurface;
namespace mozilla {
namespace layers {
class GpuFence;
/**
* A TextureHost for shared MacIOSurface
*
@@ -77,6 +79,7 @@ class MacIOSurfaceTextureHostOGL : public TextureHost {
protected:
RefPtr<GLTextureSource> mTextureSource;
RefPtr<MacIOSurface> mSurface;
RefPtr<GpuFence> mGpuFence;
};
} // namespace layers

View File

@@ -13,6 +13,7 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/CompositionRecorder.h"
#include "mozilla/layers/GpuFence.h"
#include "mozilla/layers/NativeLayer.h"
#include "mozilla/layers/SurfacePool.h"
#include "mozilla/StaticPrefs_gfx.h"
@@ -88,6 +89,8 @@ RenderedFrameId RenderCompositorNative::EndFrame(
DoSwap();
MOZ_ASSERT(mPendingGpuFeces.empty());
if (mNativeLayerForEntireWindow) {
mNativeLayerForEntireWindow->NotifySurfaceReady();
mNativeLayerRoot->CommitToScreen();
@@ -431,6 +434,13 @@ void RenderCompositorNative::AddSurface(
layer->SetSamplingFilter(ToSamplingFilter(aImageRendering));
mAddedLayers.AppendElement(layer);
if (surface.mIsExternal) {
RefPtr<layers::GpuFence> fence = layer->GetGpuFence();
if (fence && BackendType() == layers::WebRenderBackend::HARDWARE) {
mPendingGpuFeces.emplace_back(fence);
}
}
if (!surface.mIsExternal) {
mAddedTilePixelCount += layerSize.width * layerSize.height;
}
@@ -471,16 +481,16 @@ RenderCompositorNativeOGL::~RenderCompositorNativeOGL() {
gfxCriticalNote
<< "Failed to make render context current during destroying.";
// Leak resources!
mPreviousFrameDoneSync = nullptr;
mThisFrameDoneSync = nullptr;
mPreviousFrameDoneFences = nullptr;
mThisFrameDoneFences = nullptr;
return;
}
if (mPreviousFrameDoneSync) {
mGL->fDeleteSync(mPreviousFrameDoneSync);
if (mPreviousFrameDoneFences && mPreviousFrameDoneFences->mSync) {
mGL->fDeleteSync(mPreviousFrameDoneFences->mSync);
}
if (mThisFrameDoneSync) {
mGL->fDeleteSync(mThisFrameDoneSync);
if (mThisFrameDoneFences && mThisFrameDoneFences->mSync) {
mGL->fDeleteSync(mThisFrameDoneFences->mSync);
}
}
@@ -512,23 +522,43 @@ void RenderCompositorNativeOGL::InsertFrameDoneSync() {
#ifdef XP_DARWIN
// Only do this on macOS.
// On other platforms, SwapBuffers automatically applies back-pressure.
if (mThisFrameDoneSync) {
mGL->fDeleteSync(mThisFrameDoneSync);
if (mThisFrameDoneFences && mThisFrameDoneFences->mSync) {
mGL->fDeleteSync(mThisFrameDoneFences->mSync);
}
mThisFrameDoneSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
mThisFrameDoneFences =
MakeUnique<BackPressureFences>(std::move(mPendingGpuFeces));
mThisFrameDoneFences->mSync =
mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
#endif
}
bool RenderCompositorNativeOGL::WaitForGPU() {
if (mPreviousFrameDoneSync) {
if (mPreviousFrameDoneFences) {
bool complete = false;
while (!complete) {
complete = true;
for (const auto& fence : mPreviousFrameDoneFences->mGpuFeces) {
if (!fence->HasCompleted()) {
complete = false;
break;
}
}
if (!complete) {
PR_Sleep(PR_MillisecondsToInterval(1));
}
}
if (mPreviousFrameDoneFences->mSync) {
AUTO_PROFILER_LABEL("Waiting for GPU to finish previous frame", GRAPHICS);
mGL->fClientWaitSync(mPreviousFrameDoneSync,
mGL->fClientWaitSync(mPreviousFrameDoneFences->mSync,
LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT,
LOCAL_GL_TIMEOUT_IGNORED);
mGL->fDeleteSync(mPreviousFrameDoneSync);
mGL->fDeleteSync(mPreviousFrameDoneFences->mSync);
}
mPreviousFrameDoneSync = mThisFrameDoneSync;
mThisFrameDoneSync = nullptr;
}
mPreviousFrameDoneFences = std::move(mThisFrameDoneFences);
MOZ_ASSERT(!mThisFrameDoneFences);
return true;
}

View File

@@ -7,6 +7,7 @@
#ifndef MOZILLA_GFX_RENDERCOMPOSITOR_NATIVE_H
#define MOZILLA_GFX_RENDERCOMPOSITOR_NATIVE_H
#include <deque>
#include <unordered_map>
#include "GLTypes.h"
@@ -18,6 +19,7 @@
namespace mozilla {
namespace layers {
class GpuFence;
class NativeLayerRootSnapshotter;
class NativeLayerRoot;
class NativeLayer;
@@ -140,6 +142,7 @@ class RenderCompositorNative : public RenderCompositor {
gfx::IntRect mVisibleBounds;
std::unordered_map<wr::NativeSurfaceId, Surface, SurfaceIdHashFn> mSurfaces;
TimeStamp mBeginFrameTimeStamp;
std::deque<RefPtr<layers::GpuFence>> mPendingGpuFeces;
};
static inline bool operator==(const RenderCompositorNative::TileKey& a0,
@@ -176,9 +179,18 @@ class RenderCompositorNativeOGL : public RenderCompositorNative {
RefPtr<gl::GLContext> mGL;
struct BackPressureFences {
explicit BackPressureFences(
std::deque<RefPtr<layers::GpuFence>>&& aGpuFeces)
: mGpuFeces(std::move(aGpuFeces)) {}
GLsync mSync = nullptr;
std::deque<RefPtr<layers::GpuFence>> mGpuFeces;
};
// Used to apply back-pressure in WaitForGPU().
GLsync mPreviousFrameDoneSync = nullptr;
GLsync mThisFrameDoneSync = nullptr;
UniquePtr<BackPressureFences> mPreviousFrameDoneFences;
UniquePtr<BackPressureFences> mThisFrameDoneFences;
};
// RenderCompositorNativeSWGL is a NativeLayer compositor that only

View File

@@ -13,6 +13,7 @@
#endif
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/GpuFence.h"
#include "ScopedGLHelpers.h"
namespace mozilla {
@@ -41,8 +42,8 @@ static bool CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL,
}
RenderMacIOSurfaceTextureHost::RenderMacIOSurfaceTextureHost(
MacIOSurface* aSurface)
: mSurface(aSurface), mTextureHandles{0, 0, 0} {
MacIOSurface* aSurface, layers::GpuFence* aGpuFence)
: mSurface(aSurface), mGpuFence(aGpuFence), mTextureHandles{0, 0, 0} {
MOZ_COUNT_CTOR_INHERITED(RenderMacIOSurfaceTextureHost, RenderTextureHost);
}

View File

@@ -14,14 +14,16 @@
namespace mozilla {
namespace layers {
class GpuFence;
class SurfaceDescriptorMacIOSurface;
}
} // namespace layers
namespace wr {
class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL {
public:
explicit RenderMacIOSurfaceTextureHost(MacIOSurface* aSurface);
explicit RenderMacIOSurfaceTextureHost(MacIOSurface* aSurface,
layers::GpuFence* aGpuFence);
wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL) override;
void Unlock() override;
@@ -46,11 +48,14 @@ class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL {
PlaneInfo& aPlaneInfo) override;
void UnmapPlanes() override;
layers::GpuFence* GetGpuFence() { return mGpuFence; }
private:
virtual ~RenderMacIOSurfaceTextureHost();
void DeleteTextureHandle();
RefPtr<MacIOSurface> mSurface;
RefPtr<layers::GpuFence> mGpuFence;
RefPtr<gl::GLContext> mGL;
GLuint mTextureHandles[3];
};

View File

@@ -1270,6 +1270,62 @@ pub extern "C" fn wgpu_vkimage_get_dma_buf_info(handle: &VkImageHandle) -> DMABu
}
}
#[cfg(target_os = "macos")]
pub struct MetalSharedEventHandle(metal::SharedEvent);
#[cfg(not(target_os = "macos"))]
pub struct MetalSharedEventHandle;
#[no_mangle]
#[allow(unreachable_code)]
#[allow(unused_variables)]
pub extern "C" fn wgpu_server_get_device_fence_metal_shared_event(
global: &Global,
device_id: id::DeviceId,
) -> *mut MetalSharedEventHandle {
#[cfg(target_os = "macos")]
{
let shared_event = unsafe {
global.device_fence_as_hal::<wgc::api::Metal, _, Option<metal::SharedEvent>>(
device_id,
|hal_fence| hal_fence.map(|fence| fence.raw_shared_event().unwrap().clone()),
)
};
let shared_event = match shared_event {
Some(shared_event) => shared_event,
None => {
return ptr::null_mut();
}
};
return Box::into_raw(Box::new(MetalSharedEventHandle(shared_event)));
}
ptr::null_mut()
}
#[no_mangle]
#[allow(unreachable_code)]
#[allow(unused_variables)]
pub extern "C" fn wgpu_server_metal_shared_event_signaled_value(
shared_event: &mut MetalSharedEventHandle,
) -> u64 {
#[cfg(target_os = "macos")]
{
return shared_event.0.signaled_value();
}
u64::MAX
}
#[no_mangle]
#[allow(unreachable_code)]
#[allow(unused_variables)]
pub extern "C" fn wgpu_server_delete_metal_shared_event(shared_event: *mut MetalSharedEventHandle) {
#[cfg(target_os = "macos")]
{
let _ = unsafe { Box::from_raw(shared_event) };
}
}
extern "C" {
#[allow(dead_code)]
fn gfx_critical_note(msg: *const c_char);

View File

@@ -68,6 +68,14 @@ class DefaultDelete<webgpu::ffi::WGPUVkImageHandle> {
};
#endif
template <>
class DefaultDelete<webgpu::ffi::WGPUMetalSharedEventHandle> {
public:
void operator()(webgpu::ffi::WGPUMetalSharedEventHandle* aPtr) const {
webgpu::ffi::wgpu_server_delete_metal_shared_event(aPtr);
}
};
} // namespace mozilla
#endif // WGPU_h