Commit 4ce13b5e authored by Rafael Cintron's avatar Rafael Cintron Committed by Commit Bot

Implement CreateSharedImage from GpuMemoryBufferHandle

To reduce the number of texture copies in camera and XR scenarios,
we need to be able to share textures between processes using Windows
handle objects.

To facilitate this, we implement the overload of
SharedImageBackingFactoryD3D::CreateSharedImage which accepts a
gfx::GpuMemoryBufferHandle.

Bug: 1131616
Change-Id: I9561229b7631d0a89a7ced4ee6fc0de43c029d45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2438649
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812835}
parent ae4204a6
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
#include "gpu/command_buffer/service/shared_image_backing_factory_d3d.h" #include "gpu/command_buffer/service/shared_image_backing_factory_d3d.h"
#include <d3d11_1.h>
#include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/shared_image_backing_d3d.h" #include "gpu/command_buffer/service/shared_image_backing_d3d.h"
#include "ui/gfx/buffer_format_util.h" #include "ui/gfx/buffer_format_util.h"
#include "ui/gl/direct_composition_surface_win.h" #include "ui/gl/direct_composition_surface_win.h"
...@@ -141,13 +144,9 @@ std::unique_ptr<SharedImageBacking> SharedImageBackingFactoryD3D::MakeBacking( ...@@ -141,13 +144,9 @@ std::unique_ptr<SharedImageBacking> SharedImageBackingFactoryD3D::MakeBacking(
return nullptr; return nullptr;
} }
} else if (shared_handle.IsValid()) { } else if (shared_handle.IsValid()) {
const HRESULT hr = d3d11_texture.As(&dxgi_keyed_mutex); // Keyed mutexes are required for Dawn interop but are not used
if (FAILED(hr)) { // for XR composition where fences are used instead.
DLOG(ERROR) << "Unable to QueryInterface for IDXGIKeyedMutex on texture " d3d11_texture.As(&dxgi_keyed_mutex);
"with shared handle "
<< std::hex;
return nullptr;
}
} }
DCHECK(d3d11_texture); DCHECK(d3d11_texture);
...@@ -380,15 +379,58 @@ SharedImageBackingFactoryD3D::CreateSharedImage( ...@@ -380,15 +379,58 @@ SharedImageBackingFactoryD3D::CreateSharedImage(
GrSurfaceOrigin surface_origin, GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type, SkAlphaType alpha_type,
uint32_t usage) { uint32_t usage) {
NOTIMPLEMENTED(); // TODO: Add support for shared memory GMBs.
return nullptr; DCHECK_EQ(handle.type, gfx::DXGI_SHARED_HANDLE);
if (!handle.dxgi_handle.IsValid()) {
DLOG(ERROR) << "Invalid handle type passed to CreateSharedImage";
return nullptr;
}
if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, format)) {
DLOG(ERROR) << "Invalid image size " << size.ToString() << " for "
<< gfx::BufferFormatToString(format);
return nullptr;
}
Microsoft::WRL::ComPtr<ID3D11Device1> d3d11_device1;
HRESULT hr = d3d11_device_.As(&d3d11_device1);
if (FAILED(hr)) {
DLOG(ERROR) << "Failed to query for ID3D11Device1. Error: "
<< logging::SystemErrorCodeToString(hr);
return nullptr;
}
Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
hr = d3d11_device1->OpenSharedResource1(handle.dxgi_handle.Get(),
IID_PPV_ARGS(&d3d11_texture));
if (FAILED(hr)) {
DLOG(ERROR) << "Unable to open shared resource from DXGI handle. Error: "
<< logging::SystemErrorCodeToString(hr);
return nullptr;
}
D3D11_TEXTURE2D_DESC desc;
d3d11_texture->GetDesc(&desc);
// TODO: Add checks for device specific limits.
if (desc.Width != static_cast<UINT>(size.width()) ||
desc.Height != static_cast<UINT>(size.height())) {
DLOG(ERROR)
<< "Size passed to CreateSharedImage must match texture being opened";
return nullptr;
}
return MakeBacking(mailbox, viz::GetResourceFormat(format), size, color_space,
surface_origin, alpha_type, usage, /*swap_chain=*/nullptr,
/*buffer_index=*/0, std::move(d3d11_texture),
std::move(handle.dxgi_handle));
} }
// Returns true if the specified GpuMemoryBufferType can be imported using // Returns true if the specified GpuMemoryBufferType can be imported using
// this factory. // this factory.
bool SharedImageBackingFactoryD3D::CanImportGpuMemoryBuffer( bool SharedImageBackingFactoryD3D::CanImportGpuMemoryBuffer(
gfx::GpuMemoryBufferType memory_buffer_type) { gfx::GpuMemoryBufferType memory_buffer_type) {
return false; return (memory_buffer_type == gfx::DXGI_SHARED_HANDLE);
} }
} // namespace gpu } // namespace gpu
...@@ -96,6 +96,10 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryD3D ...@@ -96,6 +96,10 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryD3D
bool CanImportGpuMemoryBuffer( bool CanImportGpuMemoryBuffer(
gfx::GpuMemoryBufferType memory_buffer_type) override; gfx::GpuMemoryBufferType memory_buffer_type) override;
Microsoft::WRL::ComPtr<ID3D11Device> GetDeviceForTesting() const {
return d3d11_device_;
}
private: private:
// Wraps the optional swap chain buffer (front buffer/back buffer) and texture // Wraps the optional swap chain buffer (front buffer/back buffer) and texture
// into GLimage and creates a GL texture and stores it as gles2::Texture or as // into GLimage and creates a GL texture and stores it as gles2::Texture or as
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/service_utils.h" #include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/shared_context_state.h" #include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image_backing_d3d.h"
#include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/command_buffer/service/shared_image_manager.h" #include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/command_buffer/service/shared_image_representation.h" #include "gpu/command_buffer/service/shared_image_representation.h"
...@@ -846,5 +847,72 @@ TEST_F(SharedImageBackingFactoryD3DTest, SkiaAccessFirstFails) { ...@@ -846,5 +847,72 @@ TEST_F(SharedImageBackingFactoryD3DTest, SkiaAccessFirstFails) {
skia_representation->BeginScopedReadAccess(nullptr, nullptr); skia_representation->BeginScopedReadAccess(nullptr, nullptr);
EXPECT_EQ(scoped_read_access, nullptr); EXPECT_EQ(scoped_read_access, nullptr);
} }
TEST_F(SharedImageBackingFactoryD3DTest, CreateSharedImageFromHandle) {
if (!IsD3DSharedImageSupported())
return;
EXPECT_TRUE(
shared_image_factory_->CanImportGpuMemoryBuffer(gfx::DXGI_SHARED_HANDLE));
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
shared_image_factory_->GetDeviceForTesting();
const gfx::Size size(1, 1);
D3D11_TEXTURE2D_DESC desc;
desc.Width = size.width();
desc.Height = size.height();
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.MiscFlags =
D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED;
Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
HRESULT hr = d3d11_device->CreateTexture2D(&desc, nullptr, &d3d11_texture);
ASSERT_EQ(hr, S_OK);
Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
hr = d3d11_texture.As(&dxgi_resource);
ASSERT_EQ(hr, S_OK);
HANDLE shared_handle;
hr = dxgi_resource->CreateSharedHandle(
nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
&shared_handle);
ASSERT_EQ(hr, S_OK);
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle;
gpu_memory_buffer_handle.dxgi_handle.Set(shared_handle);
gpu_memory_buffer_handle.type = gfx::DXGI_SHARED_HANDLE;
auto mailbox = Mailbox::GenerateForSharedImage();
const auto format = gfx::BufferFormat::RGBA_8888;
const auto color_space = gfx::ColorSpace::CreateSRGB();
const uint32_t usage = SHARED_IMAGE_USAGE_GLES2 | SHARED_IMAGE_USAGE_DISPLAY;
const gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
const GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
const SkAlphaType alpha_type = kPremul_SkAlphaType;
auto backing = shared_image_factory_->CreateSharedImage(
mailbox, 0, std::move(gpu_memory_buffer_handle), format, surface_handle,
size, color_space, surface_origin, alpha_type, usage);
ASSERT_NE(backing, nullptr);
EXPECT_EQ(backing->format(), viz::RGBA_8888);
EXPECT_EQ(backing->size(), size);
EXPECT_EQ(backing->color_space(), color_space);
EXPECT_EQ(backing->surface_origin(), surface_origin);
EXPECT_EQ(backing->alpha_type(), alpha_type);
EXPECT_EQ(backing->mailbox(), mailbox);
SharedImageBackingD3D* backing_d3d =
static_cast<SharedImageBackingD3D*>(backing.get());
EXPECT_EQ(backing_d3d->GetSharedHandle(), shared_handle);
}
} // anonymous namespace } // anonymous namespace
} // namespace gpu } // namespace gpu
...@@ -162,6 +162,7 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage( ...@@ -162,6 +162,7 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
uint32_t usage) { uint32_t usage) {
DCHECK(gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP || DCHECK(gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP ||
gpu_memory_buffer->GetType() == gfx::ANDROID_HARDWARE_BUFFER || gpu_memory_buffer->GetType() == gfx::ANDROID_HARDWARE_BUFFER ||
gpu_memory_buffer->GetType() == gfx::DXGI_SHARED_HANDLE ||
gpu_memory_buffer_manager); gpu_memory_buffer_manager);
auto mailbox = Mailbox::GenerateForSharedImage(); auto mailbox = Mailbox::GenerateForSharedImage();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment