Skip to content

Commit

Permalink
Dawn: Add DawnImageRepresentationFallback.
Browse files Browse the repository at this point in the history
To support sharing IOSurface backed SI with Dawn's Vulkan/SwiftShader
backend. Currently this DawnImageRepresentationFallback
is implemented by CPU readbacks/uploads.

In theory this class could be used by any backing not natively supported
by Vulkan/SwiftSahder in future. Such as D3DImageBacking. As long as
those backings implement UploadFromMemory & ReadbackToMemory methods.

Bug: dawn:1953
Change-Id: Ie87dddecac89103654015cb3063d2deac6de2299
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4759704
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1184331}
  • Loading branch information
kakashidinho authored and Chromium LUCI CQ committed Aug 16, 2023
1 parent ecc712f commit 5ff6532
Show file tree
Hide file tree
Showing 11 changed files with 705 additions and 117 deletions.
61 changes: 45 additions & 16 deletions components/viz/common/resources/shared_image_format.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,9 @@ bool SharedImageFormat::IsBitmapFormatSupported() const {
}

int SharedImageFormat::NumberOfPlanes() const {
if (is_single_plane())
if (is_single_plane()) {
return 1;
}
switch (plane_config()) {
case PlaneConfig::kY_U_V:
case PlaneConfig::kY_V_U:
Expand All @@ -201,16 +202,19 @@ bool SharedImageFormat::IsValidPlaneIndex(int plane_index) const {
return plane_index >= 0 && plane_index < NumberOfPlanes();
}

absl::optional<size_t> SharedImageFormat::MaybeEstimatedSizeInBytes(
absl::optional<size_t> SharedImageFormat::MaybeEstimatedPlaneSizeInBytes(
int plane_index,
const gfx::Size& size) const {
DCHECK(!size.IsEmpty());

if (is_single_plane()) {
if (IsLegacyMultiplanar()) {
return GetEquivalentMultiplanarFormat(*this).MaybeEstimatedSizeInBytes(
size);
return GetEquivalentMultiplanarFormat(*this)
.MaybeEstimatedPlaneSizeInBytes(plane_index, size);
}

DCHECK_EQ(plane_index, 0);

base::CheckedNumeric<size_t> bits_per_row =
BitsPerPixelForTrueSinglePlaneFormat(*this);
bits_per_row *= size.width();
Expand All @@ -229,20 +233,42 @@ absl::optional<size_t> SharedImageFormat::MaybeEstimatedSizeInBytes(
}

size_t bytes_per_element = StorageBytesPerElement(channel_format());

gfx::Size plane_size = GetPlaneSize(plane_index, size);

base::CheckedNumeric<size_t> plane_estimated_bytes =
bytes_per_element * NumChannelsInPlane(plane_index);
DCHECK(plane_estimated_bytes.IsValid());
plane_estimated_bytes *= plane_size.width();
plane_estimated_bytes *= plane_size.height();
if (!plane_estimated_bytes.IsValid()) {
return absl::nullopt;
}

return plane_estimated_bytes.ValueOrDie();
}

absl::optional<size_t> SharedImageFormat::MaybeEstimatedSizeInBytes(
const gfx::Size& size) const {
DCHECK(!size.IsEmpty());

if (is_single_plane()) {
if (IsLegacyMultiplanar()) {
return GetEquivalentMultiplanarFormat(*this).MaybeEstimatedSizeInBytes(
size);
}
return MaybeEstimatedPlaneSizeInBytes(0, size);
}

base::CheckedNumeric<size_t> total_estimated_bytes = 0;
for (int plane_index = 0; plane_index < NumberOfPlanes(); ++plane_index) {
gfx::Size plane_size = GetPlaneSize(plane_index, size);

base::CheckedNumeric<size_t> plane_estimated_bytes =
bytes_per_element * NumChannelsInPlane(plane_index);
DCHECK(plane_estimated_bytes.IsValid());
plane_estimated_bytes *= plane_size.width();
plane_estimated_bytes *= plane_size.height();
if (!plane_estimated_bytes.IsValid()) {
absl::optional<size_t> plane_estimated_bytes =
MaybeEstimatedPlaneSizeInBytes(plane_index, size);
if (!plane_estimated_bytes.has_value()) {
return absl::nullopt;
}

total_estimated_bytes += plane_estimated_bytes;
total_estimated_bytes += plane_estimated_bytes.value();
if (!total_estimated_bytes.IsValid()) {
return absl::nullopt;
}
Expand All @@ -262,8 +288,9 @@ bool SharedImageFormat::VerifySizeInBytes(const gfx::Size& size) const {
gfx::Size SharedImageFormat::GetPlaneSize(int plane_index,
const gfx::Size& size) const {
DCHECK(IsValidPlaneIndex(plane_index));
if (is_single_plane())
if (is_single_plane()) {
return size;
}

switch (plane_config()) {
case PlaneConfig::kY_U_V:
Expand Down Expand Up @@ -384,8 +411,9 @@ bool SharedImageFormat::IsCompressed() const {
}

bool SharedImageFormat::IsLegacyMultiplanar() const {
if (!is_single_plane())
if (!is_single_plane()) {
return false;
}

switch (singleplanar_format()) {
case mojom::SingleplanarFormat::YV12_LEGACY:
Expand Down Expand Up @@ -435,8 +463,9 @@ int SharedImageFormat::BitsPerPixel() const {
}

bool SharedImageFormat::operator==(const SharedImageFormat& o) const {
if (plane_type_ != o.plane_type())
if (plane_type_ != o.plane_type()) {
return false;
}

switch (plane_type_) {
case PlaneType::kUnknown:
Expand Down
6 changes: 6 additions & 0 deletions components/viz/common/resources/shared_image_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ class COMPONENT_EXPORT(VIZ_SHARED_IMAGE_FORMAT) SharedImageFormat {
// formats.
absl::optional<size_t> MaybeEstimatedSizeInBytes(const gfx::Size& size) const;

// Returns estimated size in bytes for a plane of an image in this format of
// `size` or nullopt if size in bytes overflows.
absl::optional<size_t> MaybeEstimatedPlaneSizeInBytes(
int plane_index,
const gfx::Size& size) const;

// Returns estimated size in bytes for an image in this format of `size` or 0
// if size in bytes overflows. Includes all planes for multiplanar formats.
size_t EstimatedSizeInBytes(const gfx::Size& size) const;
Expand Down
28 changes: 23 additions & 5 deletions gpu/command_buffer/service/dawn_context_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ void LogError(WGPUErrorType type, char const* message, void* userdata) {
void LogDeviceLost(WGPUDeviceLostReason reason,
char const* message,
void* userdata) {
if (reason == WGPUDeviceLostReason::WGPUDeviceLostReason_Destroyed)
if (reason == WGPUDeviceLostReason::WGPUDeviceLostReason_Destroyed) {
return;
}
LOG(FATAL) << message;
}

Expand Down Expand Up @@ -115,14 +116,26 @@ std::unique_ptr<DawnContextProvider> DawnContextProvider::Create(
const GpuPreferences& gpu_preferences,
webgpu::DawnCachingInterfaceFactory* caching_interface_factory,
CacheBlobCallback callback) {
return DawnContextProvider::CreateWithBackend(
GetDefaultBackendType(), /*force_fallback_adapter=*/false,
gpu_preferences, caching_interface_factory, std::move(callback));
}

std::unique_ptr<DawnContextProvider> DawnContextProvider::CreateWithBackend(
wgpu::BackendType backend_type,
bool force_fallback_adapter,
const GpuPreferences& gpu_preferences,
webgpu::DawnCachingInterfaceFactory* caching_interface_factory,
CacheBlobCallback callback) {
auto context_provider =
base::WrapUnique(new DawnContextProvider(caching_interface_factory));

// TODO(rivr): This may return a GPU that is not the active one. Currently
// the only known way to avoid this is platform-specific; e.g. on Mac, create
// a Dawn device, get the actual Metal device from it, and compare against
// MTLCreateSystemDefaultDevice().
if (!context_provider->Initialize(gpu_preferences, std::move(callback))) {
if (!context_provider->Initialize(backend_type, force_fallback_adapter,
gpu_preferences, std::move(callback))) {
context_provider.reset();
}
return context_provider;
Expand All @@ -133,7 +146,9 @@ DawnContextProvider::DawnContextProvider(
: caching_interface_factory_(caching_interface_factory) {}
DawnContextProvider::~DawnContextProvider() = default;

bool DawnContextProvider::Initialize(const GpuPreferences& gpu_preferences,
bool DawnContextProvider::Initialize(wgpu::BackendType backend_type,
bool force_fallback_adapter,
const GpuPreferences& gpu_preferences,
CacheBlobCallback callback) {
std::unique_ptr<webgpu::DawnCachingInterface> caching_interface;
if (caching_interface_factory_) {
Expand Down Expand Up @@ -188,7 +203,8 @@ bool DawnContextProvider::Initialize(const GpuPreferences& gpu_preferences,
};

wgpu::RequestAdapterOptions adapter_options;
adapter_options.backendType = GetDefaultBackendType();
adapter_options.backendType = backend_type;
adapter_options.forceFallbackAdapter = force_fallback_adapter;
adapter_options.powerPreference = wgpu::PowerPreference::LowPower;

#if BUILDFLAG(IS_WIN)
Expand Down Expand Up @@ -233,6 +249,8 @@ bool DawnContextProvider::Initialize(const GpuPreferences& gpu_preferences,
device.SetLoggingCallback(&LogInfo, nullptr);
device_ = std::move(device);

backend_type_ = backend_type;

#if BUILDFLAG(IS_WIN)
// DirectComposition is initialized in ui/gl/init/gl_initializer_win.cc while
// initializing GL. So we need to shutdown it and re-initialize it here with
Expand Down Expand Up @@ -269,7 +287,7 @@ wgpu::Instance DawnContextProvider::GetInstance() const {
#if BUILDFLAG(IS_WIN)
Microsoft::WRL::ComPtr<ID3D11Device> DawnContextProvider::GetD3D11Device()
const {
if (GetDefaultBackendType() == wgpu::BackendType::D3D11) {
if (backend_type() == wgpu::BackendType::D3D11) {
return dawn::native::d3d11::GetD3D11Device(device_.Get());
}
return nullptr;
Expand Down
12 changes: 11 additions & 1 deletion gpu/command_buffer/service/dawn_context_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,20 @@ class GPU_GLES2_EXPORT DawnContextProvider {
const GpuPreferences& gpu_preferences = GpuPreferences(),
webgpu::DawnCachingInterfaceFactory* caching_interface_factory = nullptr,
CacheBlobCallback callback = {});
static std::unique_ptr<DawnContextProvider> CreateWithBackend(
wgpu::BackendType backend_type,
bool force_fallback_adapter = false,
const GpuPreferences& gpu_preferences = GpuPreferences(),
webgpu::DawnCachingInterfaceFactory* caching_interface_factory = nullptr,
CacheBlobCallback callback = {});

DawnContextProvider(const DawnContextProvider&) = delete;
DawnContextProvider& operator=(const DawnContextProvider&) = delete;

~DawnContextProvider();

wgpu::Device GetDevice() const { return device_; }
wgpu::BackendType backend_type() const { return backend_type_; }
wgpu::Instance GetInstance() const;

bool InitializeGraphiteContext(
Expand All @@ -66,13 +73,16 @@ class GPU_GLES2_EXPORT DawnContextProvider {
private:
explicit DawnContextProvider(
webgpu::DawnCachingInterfaceFactory* caching_interface_factory);
bool Initialize(const GpuPreferences& gpu_preferences,
bool Initialize(wgpu::BackendType backend_type,
bool force_fallback_adapter,
const GpuPreferences& gpu_preferences,
CacheBlobCallback callback);

raw_ptr<webgpu::DawnCachingInterfaceFactory> caching_interface_factory_;
std::unique_ptr<dawn::platform::Platform> platform_;
std::unique_ptr<webgpu::DawnInstance> instance_;
wgpu::Device device_;
wgpu::BackendType backend_type_;
std::unique_ptr<skgpu::graphite::Context> graphite_context_;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ class GPU_GLES2_EXPORT IOSurfaceImageBacking
IOSurfaceImageBacking& operator=(const IOSurfaceImageBacking& other) = delete;
~IOSurfaceImageBacking() override;

bool UploadFromMemory(const std::vector<SkPixmap>& pixmaps) override;
bool ReadbackToMemory(const std::vector<SkPixmap>& pixmaps) override;

bool InitializePixels(base::span<const uint8_t> pixel_data);

std::unique_ptr<gfx::GpuFence> GetLastWriteGpuFence();
Expand Down

0 comments on commit 5ff6532

Please sign in to comment.