зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1859969 - Implement WebGPUParent::GetFrontBufferSnapshot() during presenting WebGPU without readback on Window r=gfx-reviewers,lsalzman
RemoteTextureMap::GetLatestBufferSnapshot() is changed to get snapshot from wegpu::ExternalTexture if it exists. Actual snapshot from wegpu::ExternalTexture is implemented in ExternalTextureD3D11::GetSnapshot(). Differential Revision: https://phabricator.services.mozilla.com/D191937
This commit is contained in:
Родитель
4242919cdf
Коммит
7ab49b2dc9
|
@ -12,6 +12,10 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class Shmem;
|
||||
}
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
// A texture that can be used by the WebGPU implementation but is created and
|
||||
|
@ -30,6 +34,9 @@ class ExternalTexture {
|
|||
|
||||
virtual Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() = 0;
|
||||
|
||||
virtual void GetSnapshot(const ipc::Shmem& aDestShmem,
|
||||
const gfx::IntSize& aSize) {}
|
||||
|
||||
gfx::IntSize GetSize() { return gfx::IntSize(mWidth, mHeight); }
|
||||
|
||||
void SetTextureRaw(ffi::WGPUTextureRaw* aTextureRaw);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
|
||||
namespace mozilla::webgpu {
|
||||
|
||||
|
@ -32,7 +33,7 @@ UniquePtr<ExternalTextureD3D11> ExternalTextureD3D11::Create(
|
|||
DXGI_FORMAT_B8G8R8A8_UNORM, aWidth, aHeight, 1, 1,
|
||||
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
HRESULT hr =
|
||||
|
@ -77,7 +78,68 @@ Maybe<layers::SurfaceDescriptor> ExternalTextureD3D11::ToSurfaceDescriptor() {
|
|||
(WindowsHandle)GetExternalTextureHandle(),
|
||||
/* gpuProcessTextureId */ Nothing(),
|
||||
/* arrayIndex */ 0, format, gfx::IntSize(mWidth, mHeight),
|
||||
gfx::ColorSpace2::SRGB, gfx::ColorRange::FULL, /* hasKeyedMutex */ true));
|
||||
gfx::ColorSpace2::SRGB, gfx::ColorRange::FULL,
|
||||
/* hasKeyedMutex */ false));
|
||||
}
|
||||
|
||||
void ExternalTextureD3D11::GetSnapshot(const ipc::Shmem& aDestShmem,
|
||||
const gfx::IntSize& aSize) {
|
||||
RefPtr<ID3D11Device> device;
|
||||
mTexture->GetDevice(getter_AddRefs(device));
|
||||
if (!device) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
gfxCriticalNoteOnce << "Failed to get ID3D11Device";
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> deviceContext;
|
||||
device->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||
if (!deviceContext) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
gfxCriticalNoteOnce << "Failed to get ID3D11DeviceContext";
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC textureDesc = {0};
|
||||
mTexture->GetDesc(&textureDesc);
|
||||
|
||||
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
textureDesc.Usage = D3D11_USAGE_STAGING;
|
||||
textureDesc.BindFlags = 0;
|
||||
textureDesc.MiscFlags = 0;
|
||||
textureDesc.MipLevels = 1;
|
||||
|
||||
RefPtr<ID3D11Texture2D> cpuTexture;
|
||||
HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr,
|
||||
getter_AddRefs(cpuTexture));
|
||||
if (FAILED(hr)) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
gfxCriticalNote << "Failed to create ID3D11Texture2D: " << gfx::hexa(hr);
|
||||
return;
|
||||
}
|
||||
|
||||
deviceContext->CopyResource(cpuTexture, mTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
hr = deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &map);
|
||||
if (FAILED(hr)) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
gfxCriticalNote << "Failed to map ID3D11Texture2D: " << gfx::hexa(hr);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t stride = layers::ImageDataSerializer::ComputeRGBStride(
|
||||
gfx::SurfaceFormat::B8G8R8A8, aSize.width);
|
||||
uint8_t* src = static_cast<uint8_t*>(map.pData);
|
||||
uint8_t* dst = aDestShmem.get<uint8_t>();
|
||||
|
||||
MOZ_ASSERT(stride * aSize.height <= aDestShmem.Size<uint8_t>());
|
||||
|
||||
for (int y = 0; y < aSize.height; y++) {
|
||||
memcpy(dst, src, stride);
|
||||
src += map.RowPitch;
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::webgpu
|
||||
|
|
|
@ -29,6 +29,9 @@ class ExternalTextureD3D11 final : public ExternalTexture {
|
|||
|
||||
Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
|
||||
|
||||
void GetSnapshot(const ipc::Shmem& aDestShmem,
|
||||
const gfx::IntSize& aSize) override;
|
||||
|
||||
protected:
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
};
|
||||
|
|
|
@ -1023,7 +1023,8 @@ ipc::IPCResult WebGPUParent::GetFrontBufferSnapshot(
|
|||
IProtocol* aProtocol, const layers::RemoteTextureOwnerId& aOwnerId,
|
||||
Maybe<Shmem>& aShmem, gfx::IntSize& aSize) {
|
||||
const auto& lookup = mPresentationDataMap.find(aOwnerId);
|
||||
if (lookup == mPresentationDataMap.end() || !mRemoteTextureOwner) {
|
||||
if (lookup == mPresentationDataMap.end() || !mRemoteTextureOwner ||
|
||||
!mRemoteTextureOwner->IsRegistered(aOwnerId)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -349,6 +349,7 @@ void RemoteTextureMap::GetLatestBufferSnapshot(
|
|||
// The compositable ref of remote texture should be updated in mMonitor lock.
|
||||
CompositableTextureHostRef textureHostRef;
|
||||
RefPtr<TextureHost> releasingTexture; // Release outside the monitor
|
||||
std::shared_ptr<webgpu::ExternalTexture> externalTexture;
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
|
@ -360,18 +361,14 @@ void RemoteTextureMap::GetLatestBufferSnapshot(
|
|||
|
||||
// Get latest TextureHost of remote Texture.
|
||||
if (owner->mWaitingTextureDataHolders.empty() &&
|
||||
!owner->mLatestTextureHost) {
|
||||
return;
|
||||
}
|
||||
TextureHost* textureHost =
|
||||
!owner->mWaitingTextureDataHolders.empty()
|
||||
? owner->mWaitingTextureDataHolders.back()->mTextureHost
|
||||
: owner->mLatestTextureHost;
|
||||
if (!textureHost->AsBufferTextureHost()) {
|
||||
// Only BufferTextureHost is supported for now.
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
owner->mUsingTextureDataHolders.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto* holder = !owner->mWaitingTextureDataHolders.empty()
|
||||
? owner->mWaitingTextureDataHolders.back().get()
|
||||
: owner->mUsingTextureDataHolders.back().get();
|
||||
TextureHost* textureHost = holder->mTextureHost;
|
||||
|
||||
if (textureHost->GetSize() != aSize) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return;
|
||||
|
@ -381,17 +378,29 @@ void RemoteTextureMap::GetLatestBufferSnapshot(
|
|||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return;
|
||||
}
|
||||
// Increment compositable ref to prevent that TextureHost is removed during
|
||||
// memcpy.
|
||||
textureHostRef = textureHost;
|
||||
if (holder->mResourceWrapper &&
|
||||
holder->mResourceWrapper->mExternalTexture) {
|
||||
// Increment compositable ref to prevent that TextureDataHolder is removed
|
||||
// during memcpy.
|
||||
textureHostRef = textureHost;
|
||||
externalTexture = holder->mResourceWrapper->mExternalTexture;
|
||||
} else if (textureHost->AsBufferTextureHost()) {
|
||||
// Increment compositable ref to prevent that TextureDataHolder is removed
|
||||
// during memcpy.
|
||||
textureHostRef = textureHost;
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!textureHostRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* bufferTextureHost = textureHostRef->AsBufferTextureHost();
|
||||
if (bufferTextureHost) {
|
||||
if (externalTexture) {
|
||||
externalTexture->GetSnapshot(aDestShmem, aSize);
|
||||
} else if (auto* bufferTextureHost = textureHostRef->AsBufferTextureHost()) {
|
||||
uint32_t stride = ImageDataSerializer::ComputeRGBStride(
|
||||
bufferTextureHost->GetFormat(), aSize.width);
|
||||
uint32_t bufferSize = stride * aSize.height;
|
||||
|
|
Загрузка…
Ссылка в новой задаче