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 "ExternalTexture.h"
#include "mozilla/webgpu/WebGPUParent.h"
#ifdef XP_WIN #ifdef XP_WIN
# include "mozilla/webgpu/ExternalTextureD3D11.h" # include "mozilla/webgpu/ExternalTextureD3D11.h"
#endif #endif
@@ -21,19 +23,22 @@ namespace mozilla::webgpu {
// static // static
UniquePtr<ExternalTexture> ExternalTexture::Create( 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 uint32_t aWidth, const uint32_t aHeight,
const struct ffi::WGPUTextureFormat aFormat, const struct ffi::WGPUTextureFormat aFormat,
const ffi::WGPUTextureUsages aUsage) { const ffi::WGPUTextureUsages aUsage) {
MOZ_ASSERT(aParent);
UniquePtr<ExternalTexture> texture; UniquePtr<ExternalTexture> texture;
#ifdef XP_WIN #ifdef XP_WIN
texture = ExternalTextureD3D11::Create(aWidth, aHeight, aFormat, aUsage); texture = ExternalTextureD3D11::Create(aWidth, aHeight, aFormat, aUsage);
#elif defined(MOZ_WIDGET_GTK) #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); aFormat, aUsage);
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
texture = texture = ExternalTextureMacIOSurface::Create(aParent, aDeviceId, aWidth,
ExternalTextureMacIOSurface::Create(aWidth, aHeight, aFormat, aUsage); aHeight, aFormat, aUsage);
#endif #endif
return texture; return texture;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -95,7 +95,8 @@ Maybe<layers::SurfaceDescriptor>
SharedSurface_IOSurface::ToSurfaceDescriptor() { SharedSurface_IOSurface::ToSurfaceDescriptor() {
const bool isOpaque = false; // RGBA const bool isOpaque = false; // RGBA
return Some(layers::SurfaceDescriptorMacIOSurface( return Some(layers::SurfaceDescriptorMacIOSurface(
mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace())); mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace(),
(layers::GpuFence*)nullptr));
} }
} // namespace gl } // 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 { namespace layers {
class GpuFence;
class NativeLayer; class NativeLayer;
class NativeLayerCA; class NativeLayerCA;
class NativeLayerWayland; class NativeLayerWayland;
@@ -235,6 +236,8 @@ class NativeLayer {
virtual void AttachExternalImage(wr::RenderTextureHost* aExternalImage) = 0; virtual void AttachExternalImage(wr::RenderTextureHost* aExternalImage) = 0;
virtual GpuFence* GetGpuFence() = 0;
protected: protected:
virtual ~NativeLayer() = default; virtual ~NativeLayer() = default;
}; };

View File

@@ -268,6 +268,7 @@ class NativeLayerCA : public NativeLayer {
void DumpLayer(std::ostream& aOutputStream); void DumpLayer(std::ostream& aOutputStream);
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override; void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
GpuFence* GetGpuFence() override;
void SetRootWindowIsFullscreen(bool aFullscreen); 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) { bool NativeLayerCA::IsVideo(const MutexAutoLock& aProofOfLock) {
// If we have a texture host, we've checked to see if it's providing video. // 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 // 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; bool SurfaceIsFlipped() override;
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override; void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
GpuFence* GetGpuFence() override { return nullptr; }
void Commit(); void Commit();
void Unmap(); void Unmap();

View File

@@ -29,6 +29,7 @@
#include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/FocusTarget.h" #include "mozilla/layers/FocusTarget.h"
#include "mozilla/layers/GeckoContentControllerTypes.h" #include "mozilla/layers/GeckoContentControllerTypes.h"
#include "mozilla/layers/GpuFence.h"
#include "mozilla/layers/KeyboardMap.h" #include "mozilla/layers/KeyboardMap.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/MatrixMessage.h" #include "mozilla/layers/MatrixMessage.h"
@@ -1172,6 +1173,39 @@ struct ParamTraits<mozilla::layers::DoubleTapToZoomMetrics> {
} /* namespace IPC */ } /* 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_) \ #define DEFINE_SERVO_PARAMTRAITS(ty_) \
MOZ_DEFINE_RUST_PARAMTRAITS(mozilla::ty_, Servo_##ty_##_Serialize, \ MOZ_DEFINE_RUST_PARAMTRAITS(mozilla::ty_, Servo_##ty_##_Serialize, \
Servo_##ty_##_Deserialize) 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::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureOwnerId 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::GpuProcessTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::GpuProcessQueryId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::GpuProcessQueryId from "mozilla/layers/LayersTypes.h";
using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
@@ -67,6 +68,7 @@ namespace layers {
uint32_t surfaceId; uint32_t surfaceId;
bool isOpaque; bool isOpaque;
YUVColorSpace yUVColorSpace; YUVColorSpace yUVColorSpace;
nullable GpuFence gpuFence;
}; };
[Comparable] struct SurfaceDescriptorDMABuf { [Comparable] struct SurfaceDescriptorDMABuf {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,14 +14,16 @@
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
class GpuFence;
class SurfaceDescriptorMacIOSurface; class SurfaceDescriptorMacIOSurface;
} } // namespace layers
namespace wr { namespace wr {
class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL { class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL {
public: public:
explicit RenderMacIOSurfaceTextureHost(MacIOSurface* aSurface); explicit RenderMacIOSurfaceTextureHost(MacIOSurface* aSurface,
layers::GpuFence* aGpuFence);
wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL) override; wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL) override;
void Unlock() override; void Unlock() override;
@@ -46,11 +48,14 @@ class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL {
PlaneInfo& aPlaneInfo) override; PlaneInfo& aPlaneInfo) override;
void UnmapPlanes() override; void UnmapPlanes() override;
layers::GpuFence* GetGpuFence() { return mGpuFence; }
private: private:
virtual ~RenderMacIOSurfaceTextureHost(); virtual ~RenderMacIOSurfaceTextureHost();
void DeleteTextureHandle(); void DeleteTextureHandle();
RefPtr<MacIOSurface> mSurface; RefPtr<MacIOSurface> mSurface;
RefPtr<layers::GpuFence> mGpuFence;
RefPtr<gl::GLContext> mGL; RefPtr<gl::GLContext> mGL;
GLuint mTextureHandles[3]; 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" { extern "C" {
#[allow(dead_code)] #[allow(dead_code)]
fn gfx_critical_note(msg: *const c_char); fn gfx_critical_note(msg: *const c_char);

View File

@@ -68,6 +68,14 @@ class DefaultDelete<webgpu::ffi::WGPUVkImageHandle> {
}; };
#endif #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 } // namespace mozilla
#endif // WGPU_h #endif // WGPU_h