Skip to content

Commit

Permalink
[MappableSI] Implement ScopedMapping.
Browse files Browse the repository at this point in the history
1. Add a new interface MapSharedImage() to SharedImageInterface
which will map the shared image mailbox to CPU visible memory so
that clients can read/write to that memory.
This call issues a blocking/sync call to service side on the
client's thread until the GpuMemoryBufferHandle and other
metadata arrives back from the service side. This info is
then cached in SharedImageInterface so avoid blocking in future.

2. Add a new class ScopedMapping which will be used to manage
map/unmap and other access to underlying native buffer or shared
memory. Implement client and service side changes for it.

Bug: 1433317,1433318
Change-Id: I7f775ecef15eda497c13de1ce86fa51bf42fc3d1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4775830
Commit-Queue: vikas soni <vikassoni@chromium.org>
Commit-Queue: Alex Gough <ajgo@chromium.org>
Reviewed-by: Alex Gough <ajgo@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Auto-Submit: vikas soni <vikassoni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1187567}
  • Loading branch information
vikaschromie authored and Chromium LUCI CQ committed Aug 23, 2023
1 parent d1eca94 commit fa676e5
Show file tree
Hide file tree
Showing 19 changed files with 382 additions and 16 deletions.
5 changes: 4 additions & 1 deletion gpu/command_buffer/client/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ source_set("client_sources") {
"//skia",
]

deps += [ "//skia:buildflags" ]
deps += [
"//gpu/ipc/common:ipc_common_sources",
"//skia:buildflags",
]
}
}

Expand Down
1 change: 1 addition & 0 deletions gpu/command_buffer/client/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ include_rules = [
"+components/nacl/common/buildflags.h",
"+third_party/skia",
"+components/viz/common/resources/shared_image_format.h",
"+components/viz/common/resources/shared_image_format_utils.h",
]
71 changes: 71 additions & 0 deletions gpu/command_buffer/client/shared_image_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

#include "gpu/command_buffer/client/shared_image_interface.h"

#include "base/functional/callback_helpers.h"
#include "base/notreached.h"
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"

namespace gpu {

Expand All @@ -22,6 +25,68 @@ Mailbox SharedImageInterface::CreateSharedImage(
return Mailbox();
}

SharedImageInterface::ScopedMapping::ScopedMapping() = default;
SharedImageInterface::ScopedMapping::~ScopedMapping() {
if (buffer_) {
buffer_->Unmap();
}
}

// static
std::unique_ptr<SharedImageInterface::ScopedMapping>
SharedImageInterface::ScopedMapping::Create(gfx::GpuMemoryBufferHandle handle,
viz::SharedImageFormat format,
gfx::Size size,
gfx::BufferUsage buffer_usage) {
auto scoped_mapping = base::WrapUnique(new ScopedMapping());
if (!scoped_mapping->Init(std::move(handle), format, size, buffer_usage)) {
LOG(ERROR) << "ScopedMapping init failed.";
return nullptr;
}
return scoped_mapping;
}

bool SharedImageInterface::ScopedMapping::Init(
gfx::GpuMemoryBufferHandle handle,
viz::SharedImageFormat format,
gfx::Size size,
gfx::BufferUsage buffer_usage) {
GpuMemoryBufferSupport support;

// Only single planar buffer formats are supported currently. Multiplanar will
// be supported when Multiplanar SharedImages are fully implemented.
CHECK(format.is_single_plane());
buffer_ = support.CreateGpuMemoryBufferImplFromHandle(
std::move(handle), size,
viz::SinglePlaneSharedImageFormatToBufferFormat(format), buffer_usage,
base::DoNothing());
if (!buffer_) {
LOG(ERROR) << "Unable to create GpuMemoruBuffer.";
return false;
}
if (!buffer_->Map()) {
LOG(ERROR) << "Failed to map the buffer.";
buffer_.reset();
return false;
}
return true;
}

void* SharedImageInterface::ScopedMapping::Memory(const uint32_t plane_index) {
CHECK(buffer_);
return buffer_->memory(plane_index);
}

size_t SharedImageInterface::ScopedMapping::Stride(const uint32_t plane_index) {
CHECK(buffer_);
return buffer_->stride(plane_index);
}

gfx::BufferFormat SharedImageInterface::ScopedMapping::Format() {
CHECK(buffer_);
return buffer_->GetFormat();
}

uint32_t SharedImageInterface::UsageForMailbox(const Mailbox& mailbox) {
return 0u;
}
Expand All @@ -47,4 +112,10 @@ void SharedImageInterface::CopyToGpuMemoryBuffer(const SyncToken& sync_token,
NOTREACHED();
}

std::unique_ptr<SharedImageInterface::ScopedMapping>
SharedImageInterface::MapSharedImage(const Mailbox& mailbox) {
NOTIMPLEMENTED();
return nullptr;
}

} // namespace gpu
50 changes: 50 additions & 0 deletions gpu/command_buffer/client/shared_image_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@

#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "components/viz/common/resources/shared_image_format.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/gpu_export.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
#include "gpu/ipc/common/surface_handle.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/gpu/GrTypes.h"
Expand Down Expand Up @@ -45,6 +47,46 @@ class GpuMemoryBufferManager;
// synchronized using SyncTokens. See //docs/design/gpu_synchronization.md.
class GPU_EXPORT SharedImageInterface {
public:
// Provides access to the CPU visible memory for the mailbox if it is being
// used for CPU READ/WRITE and underlying resource(native buffers/shared
// memory) is CPU mappable. Memory and strides can be requested for each
// plane.
class ScopedMapping {
public:
~ScopedMapping();

// Returns a pointer to the beginning of the plane.
void* Memory(const uint32_t plane_index);

// Returns plane stride.
size_t Stride(const uint32_t plane_index);

// Returns BufferFormat.
gfx::BufferFormat Format();

private:
friend class ClientSharedImageInterface;

ScopedMapping();
static std::unique_ptr<ScopedMapping> Create(
gfx::GpuMemoryBufferHandle handle,
viz::SharedImageFormat format,
gfx::Size size,
gfx::BufferUsage buffer_usage);
bool Init(gfx::GpuMemoryBufferHandle handle,
viz::SharedImageFormat format,
gfx::Size size,
gfx::BufferUsage buffer_usage);

// ScopedMapping is essentially a wrapper around GpuMemoryBuffer for now for
// simplicity and will be removed later.
// TODO(crbug.com/1474697): Refactor/Rename GpuMemoryBuffer and its
// implementations as the end goal after all clients using GMB are
// converted to use the ScopedMapping and notion of GpuMemoryBuffer is being
// removed.
std::unique_ptr<gpu::GpuMemoryBufferImpl> buffer_;
};

virtual ~SharedImageInterface() = default;

// Creates a shared image of requested |format|, |size| and |color_space|.
Expand Down Expand Up @@ -283,6 +325,14 @@ class GPU_EXPORT SharedImageInterface {
// Informs that existing |mailbox| with |usage| can be passed to
// DestroySharedImage().
virtual void NotifyMailboxAdded(const Mailbox& mailbox, uint32_t usage);

// Maps |mailbox| into CPU visible memory(if SharedImageUsage/BufferUsage are
// set to do CPU READ/WRITE) and returns a ScopedMapping object which can be
// used to read/write to the CPU mapped memory. Mailbox must have been created
// with CPU_READ/CPU_WRITE usage. Note that this call can be blocking
// and blocks on the clients thread only the first time for a given |mailbox|.
virtual std::unique_ptr<SharedImageInterface::ScopedMapping> MapSharedImage(
const Mailbox& mailbox);
};

} // namespace gpu
Expand Down
16 changes: 16 additions & 0 deletions gpu/command_buffer/service/shared_image/shared_image_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,22 @@ bool SharedImageFactory::CopyToGpuMemoryBuffer(const Mailbox& mailbox) {
}
#endif

bool SharedImageFactory::GetGpuMemoryBufferHandleInfo(
const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle& handle,
viz::SharedImageFormat& format,
gfx::Size& size,
gfx::BufferUsage& buffer_usage) {
auto it = shared_images_.find(mailbox);
if (it == shared_images_.end()) {
LOG(ERROR)
<< "GetGpuMemoryBufferHandleInfo: Could not find shared image mailbox";
return false;
}
(*it)->GetGpuMemoryBufferHandleInfo(handle, format, size, buffer_usage);
return true;
}

void SharedImageFactory::RegisterSharedImageBackingFactoryForTesting(
SharedImageBackingFactory* factory) {
backing_factory_for_testing_ = factory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ class GPU_GLES2_EXPORT SharedImageFactory {
#endif

void SetGpuExtraInfo(const gfx::GpuExtraInfo& gpu_info);
bool GetGpuMemoryBufferHandleInfo(const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle& handle,
viz::SharedImageFormat& format,
gfx::Size& size,
gfx::BufferUsage& buffer_usage);

void RegisterSharedImageBackingFactoryForTesting(
SharedImageBackingFactory* factory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ class SharedImageRepresentationFactoryRef : public SharedImageRepresentation {
backing()->OnWriteSucceeded();
}
bool CopyToGpuMemoryBuffer() { return backing()->CopyToGpuMemoryBuffer(); }
void GetGpuMemoryBufferHandleInfo(gfx::GpuMemoryBufferHandle& handle,
viz::SharedImageFormat& format,
gfx::Size& size,
gfx::BufferUsage& buffer_usage) {
handle = backing()->GetGpuMemoryBufferHandle();
format = backing()->format();
size = backing()->size();
buffer_usage = backing()->buffer_usage();
}
bool PresentSwapChain() { return backing()->PresentSwapChain(); }
void RegisterImageFactory(SharedImageFactory* factory) {
DCHECK(is_primary_);
Expand Down
17 changes: 17 additions & 0 deletions gpu/ipc/client/client_shared_image_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,23 @@ void ClientSharedImageInterface::AddReferenceToSharedImage(
proxy_->AddReferenceToSharedImage(sync_token, mailbox, usage);
}

std::unique_ptr<SharedImageInterface::ScopedMapping>
ClientSharedImageInterface::MapSharedImage(const Mailbox& mailbox) {
auto handle_info = proxy_->GetGpuMemoryBufferHandleInfo(mailbox);
if (handle_info.handle.is_null()) {
LOG(ERROR) << "Buffer is null.";
return nullptr;
}
auto scoped_mapping = SharedImageInterface::ScopedMapping::Create(
std::move(handle_info.handle), handle_info.format, handle_info.size,
handle_info.buffer_usage);
if (!scoped_mapping) {
LOG(ERROR) << "Unable to create ScopedMapping.";
return nullptr;
}
return scoped_mapping;
}

uint32_t ClientSharedImageInterface::UsageForMailbox(const Mailbox& mailbox) {
return proxy_->UsageForMailbox(mailbox);
}
Expand Down
3 changes: 3 additions & 0 deletions gpu/ipc/client/client_shared_image_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class GPU_EXPORT ClientSharedImageInterface : public SharedImageInterface {
const Mailbox& mailbox,
uint32_t usage) override;

std::unique_ptr<SharedImageInterface::ScopedMapping> MapSharedImage(
const Mailbox& mailbox) override;

private:
Mailbox AddMailbox(const Mailbox& mailbox);

Expand Down
10 changes: 10 additions & 0 deletions gpu/ipc/client/gpu_channel_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@ int32_t GpuChannelHost::GenerateRouteID() {
return next_route_id_.GetNext();
}

void GpuChannelHost::GetGpuMemoryBufferHandleInfo(
const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle* handle,
viz::SharedImageFormat* format,
gfx::Size* size,
gfx::BufferUsage* buffer_usage) {
GetGpuChannel().GetGpuMemoryBufferHandleInfo(mailbox, handle, format, size,
buffer_usage);
}

void GpuChannelHost::CrashGpuProcessForTesting() {
GetGpuChannel().CrashForTesting();
}
Expand Down
6 changes: 6 additions & 0 deletions gpu/ipc/client/gpu_channel_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ class GPU_EXPORT GpuChannelHost
// Generate a route ID guaranteed to be unique for this channel.
int32_t GenerateRouteID();

void GetGpuMemoryBufferHandleInfo(const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle* handle,
viz::SharedImageFormat* format,
gfx::Size* size,
gfx::BufferUsage* buffer_usage);

// Crashes the GPU process. This functionality is added here because
// of instability when creating a new tab just to navigate to
// chrome://gpucrash . This only works when running tests and is
Expand Down
38 changes: 38 additions & 0 deletions gpu/ipc/client/shared_image_interface_proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,44 @@ void SharedImageInterfaceProxy::NotifyMailboxAdded(const Mailbox& mailbox,
AddMailbox(mailbox, usage);
}

SharedImageInterfaceProxy::GpuMemoryBufferHandleInfo
SharedImageInterfaceProxy::GetGpuMemoryBufferHandleInfo(
const Mailbox& mailbox) {
// Check if the handle info is already present in the map.
{
base::AutoLock lock(lock_);
auto it = mailbox_infos_.find(mailbox);

// Mailbox for which query is made must be present.
CHECK(it != mailbox_infos_.end());
if (it->second.handle_info) {
return it->second.handle_info.value();
}
}

// If not present, then get it from service side via blocking call.
// Flush all the pending deferred messages first to send them to service side.
Flush();

// Get the handle info from service side. This call will be blocked on current
// thread which is client's calling thread.
gfx::GpuMemoryBufferHandle handle;
viz::SharedImageFormat format;
gfx::Size size;
gfx::BufferUsage buffer_usage;
host_->GetGpuMemoryBufferHandleInfo(mailbox, &handle, &format, &size,
&buffer_usage);
GpuMemoryBufferHandleInfo handle_info(std::move(handle), format, size,
buffer_usage);

// Cache the handle info in the map.
{
base::AutoLock lock(lock_);
mailbox_infos_[mailbox].handle_info = handle_info;
}
return handle_info;
}

SharedImageInterfaceProxy::SharedImageInfo::SharedImageInfo() = default;
SharedImageInterfaceProxy::SharedImageInfo::~SharedImageInfo() = default;

Expand Down

0 comments on commit fa676e5

Please sign in to comment.