graphite: support deferring submits after D3D backing is destroyed.
Modify the way SkiaGraphiteImageRepresentation creates graphite's BackendTexture holders: - The default implementation creates non-owning holders that are not safe to be used outside the access' scope. - If the backing is D3DImageBacking, the created holders will contain a ref to the shared texture memory cache and the persistent graphite access. This is to keep the cached texture and its persistent access alive even if the backing is destroyed. Bug: 354940781 Bug: 354942507 Change-Id: I4c73c1baba5fb49337b5e8485e113fefab3c61a7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6290631 Reviewed-by: Saifuddin Hitawala <hitawala@chromium.org> Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org> Commit-Queue: Quyen Le <lehoangquyen@chromium.org> Cr-Commit-Position: refs/heads/main@{#1426565}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
6a06a50438
commit
a4db36cb22
gpu/command_buffer/service
BUILD.gn
shared_image
ahardwarebuffer_image_backing_factory.ccd3d_image_backing.ccd3d_image_backing.hd3d_image_representation.ccd3d_image_representation.hdawn_shared_texture_cache.ccdawn_shared_texture_cache.hdcomp_surface_image_backing.ccdxgi_swap_chain_image_backing.cciosurface_image_backing.hiosurface_image_backing.mmozone_image_backing.ccshared_image_representation.ccshared_image_representation.hskia_graphite_dawn_image_representation.ccskia_graphite_dawn_image_representation.h
@ -525,8 +525,8 @@ target(link_target_type, "gles2_sources") {
|
||||
sources += [
|
||||
"dawn_context_provider.cc",
|
||||
"dawn_context_provider.h",
|
||||
"shared_image/dawn_shared_texture_holder.cc",
|
||||
"shared_image/dawn_shared_texture_holder.h",
|
||||
"shared_image/dawn_shared_texture_cache.cc",
|
||||
"shared_image/dawn_shared_texture_cache.h",
|
||||
"shared_image/skia_graphite_dawn_image_representation.cc",
|
||||
"shared_image/skia_graphite_dawn_image_representation.h",
|
||||
]
|
||||
|
@ -535,7 +535,7 @@ AHardwareBufferImageBacking::ProduceSkiaGraphite(
|
||||
// NOTE: AHardwareBufferImageBacking doesn't support multiplanar formats,
|
||||
// so there is no need to specify the `is_yuv_plane` or
|
||||
// `legacy_plane_index` optional parameters.
|
||||
return SkiaGraphiteDawnImageRepresentation::Create(
|
||||
return std::make_unique<SkiaGraphiteDawnImageRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker);
|
||||
#else
|
||||
|
@ -134,14 +134,15 @@ void D3DImageBacking::GLTextureHolder::MarkContextLost() {
|
||||
|
||||
D3DImageBacking::GLTextureHolder::~GLTextureHolder() = default;
|
||||
|
||||
// PersistentGraphiteDawnAccess
|
||||
class D3DImageBacking::PersistentGraphiteDawnAccess {
|
||||
// PersistentGraphiteDawnAccess. This is ref counted because it would out-live
|
||||
// the parent backing when its ref is kept inside a GraphiteTextureHolder.
|
||||
class D3DImageBacking::PersistentGraphiteDawnAccess
|
||||
: public base::RefCountedThreadSafe<PersistentGraphiteDawnAccess> {
|
||||
public:
|
||||
PersistentGraphiteDawnAccess(scoped_refptr<SharedContextState> context_state,
|
||||
wgpu::Device device,
|
||||
wgpu::Texture texture,
|
||||
wgpu::SharedTextureMemory texture_memory);
|
||||
~PersistentGraphiteDawnAccess();
|
||||
|
||||
// Must be called once after construction. Since constructor cannot return
|
||||
// error, this provides a way to initialize the access and return a result.
|
||||
@ -168,6 +169,10 @@ class D3DImageBacking::PersistentGraphiteDawnAccess {
|
||||
bool IsGraphiteDevice(const wgpu::Device& device) const;
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<PersistentGraphiteDawnAccess>;
|
||||
|
||||
~PersistentGraphiteDawnAccess();
|
||||
|
||||
scoped_refptr<SharedContextState> context_state_;
|
||||
wgpu::Device device_;
|
||||
wgpu::Texture texture_;
|
||||
@ -282,6 +287,31 @@ bool D3DImageBacking::PersistentGraphiteDawnAccess::IsGraphiteDevice(
|
||||
return device_.Get() == device.Get();
|
||||
}
|
||||
|
||||
// GraphiteTextureHolder keeps a ref to DawnSharedTextureCache and
|
||||
// PersistentGraphiteDawnAccess to keep wgpu::Texture & and its access valid
|
||||
// until this holder is destroyed.
|
||||
class D3DImageBacking::GraphiteTextureHolder
|
||||
: public SkiaImageRepresentation::GraphiteTextureHolder {
|
||||
public:
|
||||
using Base = SkiaImageRepresentation::GraphiteTextureHolder;
|
||||
|
||||
GraphiteTextureHolder(
|
||||
scoped_refptr<DawnSharedTextureCache> shared_texture_cache,
|
||||
scoped_refptr<PersistentGraphiteDawnAccess>
|
||||
persistent_graphite_dawn_access,
|
||||
skgpu::graphite::BackendTexture backend_texture)
|
||||
: Base(std::move(backend_texture)),
|
||||
shared_texture_cache_(std::move(shared_texture_cache)),
|
||||
persistent_graphite_dawn_access_(
|
||||
std::move(persistent_graphite_dawn_access)) {}
|
||||
|
||||
private:
|
||||
~GraphiteTextureHolder() override = default;
|
||||
|
||||
scoped_refptr<DawnSharedTextureCache> shared_texture_cache_;
|
||||
scoped_refptr<PersistentGraphiteDawnAccess> persistent_graphite_dawn_access_;
|
||||
};
|
||||
|
||||
// static
|
||||
scoped_refptr<D3DImageBacking::GLTextureHolder>
|
||||
D3DImageBacking::CreateGLTexture(
|
||||
@ -443,7 +473,9 @@ D3DImageBacking::D3DImageBacking(
|
||||
swap_chain_(std::move(swap_chain)),
|
||||
is_back_buffer_(is_back_buffer),
|
||||
use_update_subresource1_(use_update_subresource1),
|
||||
angle_d3d11_device_(gl::QueryD3D11DeviceObjectFromANGLE()) {
|
||||
angle_d3d11_device_(gl::QueryD3D11DeviceObjectFromANGLE()),
|
||||
dawn_shared_texture_cache_(
|
||||
base::MakeRefCounted<DawnSharedTextureCache>()) {
|
||||
if (d3d11_texture_) {
|
||||
d3d11_texture_->GetDevice(&texture_d3d11_device_);
|
||||
d3d11_texture_->GetDesc(&d3d11_texture_desc_);
|
||||
@ -470,15 +502,11 @@ D3DImageBacking::D3DImageBacking(
|
||||
texture_target_(0),
|
||||
array_slice_(0),
|
||||
is_back_buffer_(false),
|
||||
use_update_subresource1_(false) {}
|
||||
use_update_subresource1_(false),
|
||||
dawn_shared_texture_cache_(
|
||||
base::MakeRefCounted<DawnSharedTextureCache>()) {}
|
||||
|
||||
D3DImageBacking::~D3DImageBacking() {
|
||||
{
|
||||
AutoLock auto_lock(this);
|
||||
FlushGraphiteCommandsIfNeeded();
|
||||
persistent_graphite_dawn_access_.reset();
|
||||
}
|
||||
|
||||
if (!have_context()) {
|
||||
for (auto& texture_holder : gl_texture_holders_) {
|
||||
if (texture_holder) {
|
||||
@ -773,17 +801,17 @@ std::unique_ptr<DawnImageRepresentation> D3DImageBacking::ProduceDawn(
|
||||
// TODO(crbug.com/345674550): Cache the textures for WebGPU device.
|
||||
DCHECK(shared_texture_memory);
|
||||
auto cached_shared_texture_memory =
|
||||
dawn_shared_texture_holder_.GetSharedTextureMemory(device);
|
||||
dawn_shared_texture_cache_->GetSharedTextureMemory(device);
|
||||
if (!cached_shared_texture_memory) {
|
||||
// GetSharedTextureMemory() might return non-null while nothing is
|
||||
// cached inside dawn_shared_texture_holder_. This can happen if a 2nd
|
||||
// cached inside dawn_shared_texture_cache_. This can happen if a 2nd
|
||||
// backing is created from an existing DXGISharedHandleState. The STM is
|
||||
// stored inside DXGISharedHandleState but not in the 2nd backing's
|
||||
// dawn_shared_texture_holder_ yet. In this case, we also need to cache
|
||||
// the STM in dawn_shared_texture_holder_ to allow wgpu::Texture to be
|
||||
// dawn_shared_texture_cache_ yet. In this case, we also need to cache
|
||||
// the STM in dawn_shared_texture_cache_ to allow wgpu::Texture to be
|
||||
// cached. Otherwise the wgpu::Texture would have been destroyed in
|
||||
// EndAccessDawn.
|
||||
dawn_shared_texture_holder_.MaybeCacheSharedTextureMemory(
|
||||
dawn_shared_texture_cache_->MaybeCacheSharedTextureMemory(
|
||||
device, shared_texture_memory);
|
||||
} else {
|
||||
CHECK_EQ(cached_shared_texture_memory.Get(),
|
||||
@ -811,7 +839,7 @@ void D3DImageBacking::InitPersistentGraphiteDawnAccess(
|
||||
|
||||
// Make sure we cache the shared texture memory so that the texture will be
|
||||
// properly cleaned up when the cache is destroyed.
|
||||
dawn_shared_texture_holder_.MaybeCacheSharedTextureMemory(
|
||||
dawn_shared_texture_cache_->MaybeCacheSharedTextureMemory(
|
||||
device, shared_texture_memory);
|
||||
|
||||
// Create a single texture that has all supported usages.
|
||||
@ -823,9 +851,9 @@ void D3DImageBacking::InitPersistentGraphiteDawnAccess(
|
||||
}
|
||||
|
||||
persistent_graphite_dawn_access_ =
|
||||
base::WrapUnique(new PersistentGraphiteDawnAccess(
|
||||
base::MakeRefCounted<PersistentGraphiteDawnAccess>(
|
||||
std::move(context_state), std::move(device), std::move(texture),
|
||||
std::move(shared_texture_memory)));
|
||||
std::move(shared_texture_memory));
|
||||
|
||||
if (!persistent_graphite_dawn_access_->BeginAccess(
|
||||
/*is_cleared=*/ClearedRectInternal() == gfx::Rect(size()))) {
|
||||
@ -840,7 +868,7 @@ wgpu::Texture D3DImageBacking::GetOrCreateDawnTexture(
|
||||
wgpu::TextureUsage wgpu_internal_usage,
|
||||
const std::vector<wgpu::TextureFormat>& view_formats) {
|
||||
wgpu::Texture texture =
|
||||
dawn_shared_texture_holder_.GetCachedWGPUTexture(device, wgpu_usage);
|
||||
dawn_shared_texture_cache_->GetCachedWGPUTexture(device, wgpu_usage);
|
||||
if (!texture) {
|
||||
texture = CreateDawnSharedTexture(shared_texture_memory, wgpu_usage,
|
||||
wgpu_internal_usage, view_formats);
|
||||
@ -852,7 +880,7 @@ wgpu::Texture D3DImageBacking::GetOrCreateDawnTexture(
|
||||
std::string label = base::StrCat({GetName(), "_", debug_label()});
|
||||
texture.SetLabel(label.c_str());
|
||||
|
||||
dawn_shared_texture_holder_.MaybeCacheWGPUTexture(device, texture);
|
||||
dawn_shared_texture_cache_->MaybeCacheWGPUTexture(device, texture);
|
||||
}
|
||||
|
||||
return texture;
|
||||
@ -1068,7 +1096,7 @@ wgpu::Texture D3DImageBacking::BeginAccessDawn(
|
||||
if (shared_texture_memory.BeginAccess(texture, &desc) !=
|
||||
wgpu::Status::Success) {
|
||||
LOG(ERROR) << "SharedTextureMemory::BeginAccess() failed.";
|
||||
dawn_shared_texture_holder_.RemoveWGPUTextureFromCache(device, texture);
|
||||
dawn_shared_texture_cache_->RemoveWGPUTextureFromCache(device, texture);
|
||||
TrackEndAccessToWGPUTexture(texture);
|
||||
return nullptr;
|
||||
}
|
||||
@ -1162,11 +1190,36 @@ void D3DImageBacking::EndAccessDawn(const wgpu::Device& device,
|
||||
|
||||
CheckForDawnDeviceLoss(device, shared_texture_memory);
|
||||
|
||||
dawn_shared_texture_holder_.DestroyWGPUTextureIfNotCached(device, texture);
|
||||
dawn_shared_texture_cache_->DestroyWGPUTextureIfNotCached(device, texture);
|
||||
|
||||
EndAccessCommon(signaled_fences);
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<SkiaImageRepresentation::GraphiteTextureHolder>>
|
||||
D3DImageBacking::CreateGraphiteTextureHolders(
|
||||
wgpu::Device device,
|
||||
wgpu::Texture texture,
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures) {
|
||||
AutoLock auto_lock(this);
|
||||
// Make sure that the texture is cached inside the dawn_shared_texture_cache_
|
||||
DCHECK(texture);
|
||||
DCHECK(dawn_shared_texture_cache_
|
||||
->GetCachedWGPUTexture(device, texture.GetUsage())
|
||||
.Get() == texture.Get());
|
||||
|
||||
std::vector<scoped_refptr<SkiaImageRepresentation::GraphiteTextureHolder>>
|
||||
graphite_holders;
|
||||
graphite_holders.reserve(backend_textures.size());
|
||||
|
||||
for (auto& backend_texture : backend_textures) {
|
||||
graphite_holders.emplace_back(base::MakeRefCounted<GraphiteTextureHolder>(
|
||||
dawn_shared_texture_cache_, persistent_graphite_dawn_access_,
|
||||
std::move(backend_texture)));
|
||||
}
|
||||
|
||||
return graphite_holders;
|
||||
}
|
||||
|
||||
void D3DImageBacking::CheckForDawnDeviceLoss(
|
||||
const wgpu::Device& device,
|
||||
const wgpu::SharedTextureMemory& shared_texture_memory) {
|
||||
@ -1176,7 +1229,7 @@ void D3DImageBacking::CheckForDawnDeviceLoss(
|
||||
|
||||
// Erase from cache if shared texture memory is invalid i.e. device was lost.
|
||||
if (shared_texture_memory.IsDeviceLost()) {
|
||||
dawn_shared_texture_holder_.EraseDataIfDeviceLost();
|
||||
dawn_shared_texture_cache_->EraseDataIfDeviceLost();
|
||||
dawn_signaled_fences_map_.erase(device.Get());
|
||||
if (dxgi_shared_handle_state_) {
|
||||
dxgi_shared_handle_state_->EraseDawnSharedTextureMemory(device);
|
||||
@ -1209,7 +1262,7 @@ wgpu::SharedTextureMemory D3DImageBacking::GetSharedTextureMemory(
|
||||
if (dxgi_shared_handle_state_) {
|
||||
return dxgi_shared_handle_state_->GetSharedTextureMemory(device);
|
||||
}
|
||||
return dawn_shared_texture_holder_.GetSharedTextureMemory(device);
|
||||
return dawn_shared_texture_cache_->GetSharedTextureMemory(device);
|
||||
}
|
||||
|
||||
bool D3DImageBacking::BeginAccessD3D11(
|
||||
@ -1651,7 +1704,7 @@ D3DImageBacking::ProduceSkiaGraphite(
|
||||
LOG(ERROR) << "Could not create Dawn Representation";
|
||||
return nullptr;
|
||||
}
|
||||
return D3DSkiaGraphiteDawnImageRepresentation::Create(
|
||||
return std::make_unique<D3DSkiaGraphiteDawnImageRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker,
|
||||
array_slice_);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "gpu/command_buffer/service/dxgi_shared_handle_manager.h"
|
||||
#include "gpu/command_buffer/service/memory_tracking.h"
|
||||
#include "gpu/command_buffer/service/shared_context_state.h"
|
||||
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_holder.h"
|
||||
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_cache.h"
|
||||
#include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h"
|
||||
#include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
|
||||
#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
|
||||
@ -128,6 +128,12 @@ class GPU_GLES2_EXPORT D3DImageBacking final
|
||||
std::vector<wgpu::TextureFormat> view_formats);
|
||||
void EndAccessDawn(const wgpu::Device& device, wgpu::Texture texture);
|
||||
|
||||
std::vector<scoped_refptr<SkiaImageRepresentation::GraphiteTextureHolder>>
|
||||
CreateGraphiteTextureHolders(
|
||||
wgpu::Device device,
|
||||
wgpu::Texture texture,
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures);
|
||||
|
||||
std::unique_ptr<DawnBufferRepresentation> ProduceDawnBuffer(
|
||||
SharedImageManager* manager,
|
||||
MemoryTypeTracker* tracker,
|
||||
@ -326,7 +332,7 @@ class GPU_GLES2_EXPORT D3DImageBacking final
|
||||
const wgpu::Device& wait_dawn_device,
|
||||
bool write_access) EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||
|
||||
// Uses either DXGISharedHandleState or internal |dawn_shared_texture_holder_|
|
||||
// Uses either DXGISharedHandleState or internal |dawn_shared_texture_cache_|
|
||||
// depending on whether the texture has a shared handle or not.
|
||||
wgpu::SharedTextureMemory GetSharedTextureMemory(const wgpu::Device& device)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||
@ -423,17 +429,18 @@ class GPU_GLES2_EXPORT D3DImageBacking final
|
||||
scoped_refptr<gfx::D3DSharedFence>>
|
||||
d3d11_signaled_fence_map_ GUARDED_BY(lock_);
|
||||
|
||||
// DawnSharedTextureHolder that keeps an internal cache of per-device
|
||||
// DawnSharedTextureCache that keeps an internal cache of per-device
|
||||
// SharedTextureData that vends WebGPU textures for the underlying d3d
|
||||
// texture. Only used if the backing doesn't have a shared handle.
|
||||
DawnSharedTextureHolder dawn_shared_texture_holder_ GUARDED_BY(lock_);
|
||||
scoped_refptr<DawnSharedTextureCache> dawn_shared_texture_cache_
|
||||
GUARDED_BY(lock_);
|
||||
|
||||
// Dawn SharedBufferMemory will exist when backing is being used for buffer
|
||||
// interop.
|
||||
wgpu::SharedBufferMemory dawn_shared_buffer_memory_ GUARDED_BY(lock_);
|
||||
|
||||
// TODO(crbug.com/348598119, hitawala): Move texture begin/end access tracking
|
||||
// to DawnSharedTextureHolder. Tracks the number of currently-ongoing accesses
|
||||
// to DawnSharedTextureCache. Tracks the number of currently-ongoing accesses
|
||||
// to a given WGPU texture.
|
||||
base::flat_map<WGPUTexture, int> wgpu_texture_ongoing_accesses_
|
||||
GUARDED_BY(lock_);
|
||||
@ -451,8 +458,9 @@ class GPU_GLES2_EXPORT D3DImageBacking final
|
||||
// devices. Since no cross device synchronization is needed, it is also safe
|
||||
// to keep this scoped access indefinitely as long as the backing is alive.
|
||||
class PersistentGraphiteDawnAccess;
|
||||
std::unique_ptr<PersistentGraphiteDawnAccess>
|
||||
persistent_graphite_dawn_access_;
|
||||
scoped_refptr<PersistentGraphiteDawnAccess> persistent_graphite_dawn_access_;
|
||||
|
||||
class GraphiteTextureHolder;
|
||||
|
||||
base::WeakPtrFactory<D3DImageBacking> weak_ptr_factory_{this};
|
||||
};
|
||||
|
@ -121,40 +121,14 @@ wgpu::Texture DawnD3DImageRepresentation::BeginAccess(
|
||||
}
|
||||
|
||||
void DawnD3DImageRepresentation::EndAccess() {
|
||||
if (!texture_)
|
||||
if (!texture_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do this before further operations since those could end up destroying the
|
||||
// Dawn device and we want the fence to be duplicated before then.
|
||||
D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
|
||||
d3d_image_backing->EndAccessDawn(device_, texture_);
|
||||
|
||||
texture_ = nullptr;
|
||||
}
|
||||
|
||||
// Enabling this functionality reduces overhead in the compositor by lowering
|
||||
// the frequency of begin/end access pairs. The semantic constraints for a
|
||||
// representation being able to return true are the following:
|
||||
// * It is valid to call BeginScopedReadAccess() concurrently on two
|
||||
// different representations of the same image
|
||||
// * The backing supports true concurrent read access rather than emulating
|
||||
// concurrent reads by "pausing" a first read when a second read of a
|
||||
// different representation type begins, which requires that the second
|
||||
// representation's read finish within the scope of its GPU task in order
|
||||
// to ensure that nothing actually accesses the first representation
|
||||
// while it is paused. Some backings that support only exclusive access
|
||||
// from the SI perspective do the latter (e.g.,
|
||||
// ExternalVulkanImageBacking as its "support" of concurrent GL and
|
||||
// Vulkan access). SupportsMultipleConcurrentReadAccess() results in the
|
||||
// compositor's read access being long-lived (i.e., beyond the scope of
|
||||
// a single GPU task).
|
||||
// The Graphite Skia representation returns true if the underlying Dawn
|
||||
// representation does so. This representation meets both of the above
|
||||
// constraints.
|
||||
bool DawnD3DImageRepresentation::SupportsMultipleConcurrentReadAccess() {
|
||||
D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
|
||||
// KeyedMutex does not support concurrent read access.
|
||||
return !d3d_image_backing->has_keyed_mutex();
|
||||
d3d_image_backing->EndAccessDawn(device_, std::move(texture_));
|
||||
}
|
||||
|
||||
DawnD3DBufferRepresentation::DawnD3DBufferRepresentation(
|
||||
@ -463,44 +437,47 @@ D3D11VideoImageCopyRepresentation::GetD3D11Texture() const {
|
||||
|
||||
// D3DSkiaGraphiteDawnImageRepresentation
|
||||
|
||||
// static
|
||||
std::unique_ptr<D3DSkiaGraphiteDawnImageRepresentation>
|
||||
D3DSkiaGraphiteDawnImageRepresentation::Create(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice) {
|
||||
return base::WrapUnique(new D3DSkiaGraphiteDawnImageRepresentation(
|
||||
std::move(dawn_representation), recorder, std::move(context_state),
|
||||
manager, backing, tracker, array_slice));
|
||||
}
|
||||
|
||||
D3DSkiaGraphiteDawnImageRepresentation::D3DSkiaGraphiteDawnImageRepresentation(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice)
|
||||
: SkiaGraphiteDawnImageRepresentation(std::move(dawn_representation),
|
||||
recorder,
|
||||
std::move(context_state),
|
||||
manager,
|
||||
backing,
|
||||
tracker,
|
||||
array_slice) {}
|
||||
|
||||
D3DSkiaGraphiteDawnImageRepresentation::
|
||||
~D3DSkiaGraphiteDawnImageRepresentation() = default;
|
||||
|
||||
// Enabling this functionality reduces overhead in the compositor by lowering
|
||||
// the frequency of begin/end access pairs. The semantic constraints for a
|
||||
// representation being able to return true are the following:
|
||||
// * It is valid to call BeginScopedReadAccess() concurrently on two
|
||||
// different representations of the same image
|
||||
// * The backing supports true concurrent read access rather than emulating
|
||||
// concurrent reads by "pausing" a first read when a second read of a
|
||||
// different representation type begins, which requires that the second
|
||||
// representation's read finish within the scope of its GPU task in order
|
||||
// to ensure that nothing actually accesses the first representation
|
||||
// while it is paused. Some backings that support only exclusive access
|
||||
// from the SI perspective do the latter (e.g.,
|
||||
// ExternalVulkanImageBacking as its "support" of concurrent GL and
|
||||
// Vulkan access). SupportsMultipleConcurrentReadAccess() results in the
|
||||
// compositor's read access being long-lived (i.e., beyond the scope of
|
||||
// a single GPU task).
|
||||
// This representation meets both of the above constraints.
|
||||
bool D3DSkiaGraphiteDawnImageRepresentation::
|
||||
SupportsMultipleConcurrentReadAccess() {
|
||||
D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
|
||||
// KeyedMutex does not support concurrent read access atm.
|
||||
// TODO(348598119): re-evaluate whether we can return true for keyed mutexes.
|
||||
return !d3d_image_backing->has_keyed_mutex();
|
||||
}
|
||||
|
||||
bool D3DSkiaGraphiteDawnImageRepresentation::
|
||||
NeedGraphiteContextSubmitBeforeEndAccess() {
|
||||
D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
|
||||
return !d3d_image_backing->SupportsDeferredGraphiteSubmit();
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<SkiaImageRepresentation::GraphiteTextureHolder>>
|
||||
D3DSkiaGraphiteDawnImageRepresentation::WrapBackendTextures(
|
||||
wgpu::Texture texture,
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures) {
|
||||
D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
|
||||
return d3d_image_backing->CreateGraphiteTextureHolders(
|
||||
GetDevice(), std::move(texture), std::move(backend_textures));
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
|
@ -62,7 +62,6 @@ class DawnD3DImageRepresentation : public DawnImageRepresentation {
|
||||
wgpu::Texture BeginAccess(wgpu::TextureUsage usage,
|
||||
wgpu::TextureUsage internal_usage) override;
|
||||
void EndAccess() override;
|
||||
bool SupportsMultipleConcurrentReadAccess() override;
|
||||
|
||||
private:
|
||||
const wgpu::Device device_;
|
||||
@ -169,28 +168,17 @@ class D3D11VideoImageCopyRepresentation : public VideoImageRepresentation {
|
||||
class D3DSkiaGraphiteDawnImageRepresentation
|
||||
: public SkiaGraphiteDawnImageRepresentation {
|
||||
public:
|
||||
static std::unique_ptr<D3DSkiaGraphiteDawnImageRepresentation> Create(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice = 0);
|
||||
|
||||
using SkiaGraphiteDawnImageRepresentation::
|
||||
SkiaGraphiteDawnImageRepresentation;
|
||||
~D3DSkiaGraphiteDawnImageRepresentation() override;
|
||||
|
||||
bool SupportsMultipleConcurrentReadAccess() override;
|
||||
bool NeedGraphiteContextSubmitBeforeEndAccess() override;
|
||||
|
||||
private:
|
||||
D3DSkiaGraphiteDawnImageRepresentation(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice);
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> WrapBackendTextures(
|
||||
wgpu::Texture texture,
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures) override;
|
||||
};
|
||||
|
||||
} // namespace gpu
|
||||
|
@ -2,39 +2,33 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_holder.h"
|
||||
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_cache.h"
|
||||
|
||||
#include "base/check_op.h"
|
||||
|
||||
namespace gpu {
|
||||
|
||||
DawnSharedTextureHolder::SharedTextureData::SharedTextureData() = default;
|
||||
DawnSharedTextureCache::SharedTextureData::SharedTextureData() = default;
|
||||
|
||||
DawnSharedTextureHolder::SharedTextureData::~SharedTextureData() {
|
||||
DawnSharedTextureCache::SharedTextureData::~SharedTextureData() {
|
||||
for (auto [texture_usage, texture] : texture_cache) {
|
||||
texture.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
DawnSharedTextureHolder::SharedTextureData::SharedTextureData(
|
||||
DawnSharedTextureCache::SharedTextureData::SharedTextureData(
|
||||
SharedTextureData&&) = default;
|
||||
|
||||
DawnSharedTextureHolder::SharedTextureData&
|
||||
DawnSharedTextureHolder::SharedTextureData::operator=(SharedTextureData&&) =
|
||||
DawnSharedTextureCache::SharedTextureData&
|
||||
DawnSharedTextureCache::SharedTextureData::operator=(SharedTextureData&&) =
|
||||
default;
|
||||
|
||||
DawnSharedTextureHolder::DawnSharedTextureHolder() = default;
|
||||
DawnSharedTextureCache::DawnSharedTextureCache() = default;
|
||||
|
||||
DawnSharedTextureHolder::~DawnSharedTextureHolder() {}
|
||||
DawnSharedTextureCache::~DawnSharedTextureCache() = default;
|
||||
|
||||
DawnSharedTextureHolder::DawnSharedTextureHolder(DawnSharedTextureHolder&&) =
|
||||
default;
|
||||
|
||||
DawnSharedTextureHolder& DawnSharedTextureHolder::operator=(
|
||||
DawnSharedTextureHolder&&) = default;
|
||||
|
||||
DawnSharedTextureHolder::WGPUTextureCache*
|
||||
DawnSharedTextureHolder::GetWGPUTextureCache(const wgpu::Device& device) {
|
||||
DawnSharedTextureCache::WGPUTextureCache*
|
||||
DawnSharedTextureCache::GetWGPUTextureCache(const wgpu::Device& device) {
|
||||
auto iter = shared_texture_data_cache_.find(device.Get());
|
||||
if (iter == shared_texture_data_cache_.end()) {
|
||||
return nullptr;
|
||||
@ -42,7 +36,7 @@ DawnSharedTextureHolder::GetWGPUTextureCache(const wgpu::Device& device) {
|
||||
return &iter->second.texture_cache;
|
||||
}
|
||||
|
||||
wgpu::SharedTextureMemory DawnSharedTextureHolder::GetSharedTextureMemory(
|
||||
wgpu::SharedTextureMemory DawnSharedTextureCache::GetSharedTextureMemory(
|
||||
const wgpu::Device& device) {
|
||||
auto iter = shared_texture_data_cache_.find(device.Get());
|
||||
if (iter == shared_texture_data_cache_.end()) {
|
||||
@ -51,7 +45,7 @@ wgpu::SharedTextureMemory DawnSharedTextureHolder::GetSharedTextureMemory(
|
||||
return iter->second.memory;
|
||||
}
|
||||
|
||||
void DawnSharedTextureHolder::MaybeCacheSharedTextureMemory(
|
||||
void DawnSharedTextureCache::MaybeCacheSharedTextureMemory(
|
||||
const wgpu::Device& device,
|
||||
const wgpu::SharedTextureMemory& memory) {
|
||||
if (!memory) {
|
||||
@ -70,7 +64,7 @@ void DawnSharedTextureHolder::MaybeCacheSharedTextureMemory(
|
||||
std::move(shared_texture_data));
|
||||
}
|
||||
|
||||
wgpu::Texture DawnSharedTextureHolder::GetCachedWGPUTexture(
|
||||
wgpu::Texture DawnSharedTextureCache::GetCachedWGPUTexture(
|
||||
const wgpu::Device& device,
|
||||
wgpu::TextureUsage texture_usage) {
|
||||
auto* texture_cache = GetWGPUTextureCache(device);
|
||||
@ -86,7 +80,7 @@ wgpu::Texture DawnSharedTextureHolder::GetCachedWGPUTexture(
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void DawnSharedTextureHolder::RemoveWGPUTextureFromCache(
|
||||
void DawnSharedTextureCache::RemoveWGPUTextureFromCache(
|
||||
const wgpu::Device& device,
|
||||
const wgpu::Texture& texture) {
|
||||
auto* texture_cache = GetWGPUTextureCache(device);
|
||||
@ -97,7 +91,7 @@ void DawnSharedTextureHolder::RemoveWGPUTextureFromCache(
|
||||
texture_cache->erase(texture.GetUsage());
|
||||
}
|
||||
|
||||
void DawnSharedTextureHolder::MaybeCacheWGPUTexture(
|
||||
void DawnSharedTextureCache::MaybeCacheWGPUTexture(
|
||||
const wgpu::Device& device,
|
||||
const wgpu::Texture& texture) {
|
||||
if (!texture) {
|
||||
@ -115,7 +109,7 @@ void DawnSharedTextureHolder::MaybeCacheWGPUTexture(
|
||||
CHECK_EQ(texture.Get(), iter->second.Get());
|
||||
}
|
||||
|
||||
void DawnSharedTextureHolder::DestroyWGPUTextureIfNotCached(
|
||||
void DawnSharedTextureCache::DestroyWGPUTextureIfNotCached(
|
||||
const wgpu::Device& device,
|
||||
const wgpu::Texture& texture) {
|
||||
if (auto cached_texture = GetCachedWGPUTexture(device, texture.GetUsage())) {
|
||||
@ -126,7 +120,7 @@ void DawnSharedTextureHolder::DestroyWGPUTextureIfNotCached(
|
||||
texture.Destroy();
|
||||
}
|
||||
|
||||
void DawnSharedTextureHolder::EraseDataIfDeviceLost() {
|
||||
void DawnSharedTextureCache::EraseDataIfDeviceLost() {
|
||||
// Clear out any cached SharedTextureMemory instances for which the
|
||||
// associated Device has been lost. This both saves memory and more
|
||||
// importantly ensures that a new SharedTextureMemory instance will be
|
@ -2,16 +2,18 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DAWN_SHARED_TEXTURE_HOLDER_H_
|
||||
#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DAWN_SHARED_TEXTURE_HOLDER_H_
|
||||
#ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DAWN_SHARED_TEXTURE_CACHE_H_
|
||||
#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DAWN_SHARED_TEXTURE_CACHE_H_
|
||||
|
||||
#include <dawn/webgpu_cpp.h>
|
||||
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class DawnSharedTextureHolder {
|
||||
class DawnSharedTextureCache
|
||||
: public base::RefCountedThreadSafe<DawnSharedTextureCache> {
|
||||
public:
|
||||
using WGPUTextureCache = base::flat_map<wgpu::TextureUsage, wgpu::Texture>;
|
||||
|
||||
@ -25,10 +27,7 @@ class DawnSharedTextureHolder {
|
||||
WGPUTextureCache texture_cache;
|
||||
};
|
||||
|
||||
DawnSharedTextureHolder();
|
||||
~DawnSharedTextureHolder();
|
||||
DawnSharedTextureHolder(DawnSharedTextureHolder&&);
|
||||
DawnSharedTextureHolder& operator=(DawnSharedTextureHolder&&);
|
||||
DawnSharedTextureCache();
|
||||
|
||||
// Returns a SharedTextureMemory for this device, or nullptr if there is no
|
||||
// instance.
|
||||
@ -54,6 +53,10 @@ class DawnSharedTextureHolder {
|
||||
void EraseDataIfDeviceLost();
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<DawnSharedTextureCache>;
|
||||
|
||||
~DawnSharedTextureCache();
|
||||
|
||||
// Returns a pointer to the WGPUTextureCache instance for this device, or
|
||||
// nullptr if there is no instance.
|
||||
WGPUTextureCache* GetWGPUTextureCache(const wgpu::Device& device);
|
||||
@ -72,4 +75,4 @@ class DawnSharedTextureHolder {
|
||||
|
||||
} // namespace gpu
|
||||
|
||||
#endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DAWN_SHARED_TEXTURE_HOLDER_H_
|
||||
#endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DAWN_SHARED_TEXTURE_CACHE_H_
|
@ -287,7 +287,7 @@ DCompSurfaceImageBacking::ProduceSkiaGraphite(
|
||||
auto dawn_representation =
|
||||
std::make_unique<DCompSurfaceDawnImageRepresentation>(
|
||||
manager, this, tracker, device, wgpu::BackendType::D3D11);
|
||||
return SkiaGraphiteDawnImageRepresentation::Create(
|
||||
return std::make_unique<SkiaGraphiteDawnImageRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker);
|
||||
#else
|
||||
|
@ -383,7 +383,7 @@ DXGISwapChainImageBacking::ProduceSkiaGraphite(
|
||||
auto dawn_representation = std::make_unique<DawnRepresentationDXGISwapChain>(
|
||||
manager, this, tracker, device, wgpu::BackendType::D3D11);
|
||||
|
||||
return SkiaGraphiteDawnImageRepresentation::Create(
|
||||
return std::make_unique<SkiaGraphiteDawnImageRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker);
|
||||
#else
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "build/build_config.h"
|
||||
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_holder.h"
|
||||
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_cache.h"
|
||||
#include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
|
||||
#include "gpu/command_buffer/service/texture_manager.h"
|
||||
#include "gpu/config/gpu_preferences.h"
|
||||
@ -142,8 +142,9 @@ class GPU_GLES2_EXPORT IOSurfaceImageBacking
|
||||
private:
|
||||
class GLTextureIRepresentation;
|
||||
class DawnRepresentation;
|
||||
class SkiaGraphiteDawnMetalRepresentation;
|
||||
class SkiaGaneshRepresentation;
|
||||
class SkiaGraphiteRepresentation;
|
||||
class SkiaGraphiteMetalRepresentation;
|
||||
class OverlayRepresentation;
|
||||
|
||||
// SharedImageBacking:
|
||||
@ -211,11 +212,11 @@ class GPU_GLES2_EXPORT IOSurfaceImageBacking
|
||||
const uint32_t io_surface_format_;
|
||||
const gfx::GenericSharedMemoryId io_surface_id_;
|
||||
|
||||
// DawnSharedTextureHolder that keeps an internal cache of per-device
|
||||
// DawnSharedTextureCache that keeps an internal cache of per-device
|
||||
// SharedTextureData that vends WebGPU textures for the underlying IOSurface.
|
||||
std::unique_ptr<DawnSharedTextureHolder> dawn_texture_holder_;
|
||||
scoped_refptr<DawnSharedTextureCache> dawn_texture_cache_;
|
||||
|
||||
DawnSharedTextureHolder* GetDawnTextureHolder();
|
||||
const scoped_refptr<DawnSharedTextureCache>& GetDawnTextureCache();
|
||||
|
||||
// Tracks the number of currently-ongoing accesses to a given WGPU texture.
|
||||
base::flat_map<WGPUTexture, int> wgpu_texture_ongoing_accesses_;
|
||||
|
@ -513,14 +513,14 @@ void IOSurfaceImageBacking::SkiaGaneshRepresentation::CheckContext() {
|
||||
|
||||
#if BUILDFLAG(SKIA_USE_METAL)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SkiaGraphiteRepresentation
|
||||
// SkiaGraphiteMetalRepresentation
|
||||
|
||||
class IOSurfaceImageBacking::SkiaGraphiteRepresentation final
|
||||
class IOSurfaceImageBacking::SkiaGraphiteMetalRepresentation final
|
||||
: public SkiaGraphiteImageRepresentation {
|
||||
public:
|
||||
// Graphite does not keep track of the MetalTexture like Ganesh, so the
|
||||
// representation/backing needs to keep the Metal texture alive.
|
||||
SkiaGraphiteRepresentation(
|
||||
SkiaGraphiteMetalRepresentation(
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
@ -532,7 +532,7 @@ class IOSurfaceImageBacking::SkiaGraphiteRepresentation final
|
||||
CHECK_EQ(mtl_textures_.size(), NumPlanesExpected());
|
||||
}
|
||||
|
||||
~SkiaGraphiteRepresentation() override {
|
||||
~SkiaGraphiteMetalRepresentation() override {
|
||||
if (!write_surfaces_.empty()) {
|
||||
DLOG(ERROR) << "SkiaImageRepresentation was destroyed while still "
|
||||
<< "open for write access.";
|
||||
@ -559,7 +559,7 @@ class IOSurfaceImageBacking::SkiaGraphiteRepresentation final
|
||||
};
|
||||
|
||||
std::vector<sk_sp<SkSurface>>
|
||||
IOSurfaceImageBacking::SkiaGraphiteRepresentation::BeginWriteAccess(
|
||||
IOSurfaceImageBacking::SkiaGraphiteMetalRepresentation::BeginWriteAccess(
|
||||
const SkSurfaceProps& surface_props,
|
||||
const gfx::Rect& update_rect) {
|
||||
if (!write_surfaces_.empty()) {
|
||||
@ -593,14 +593,14 @@ IOSurfaceImageBacking::SkiaGraphiteRepresentation::BeginWriteAccess(
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>>
|
||||
IOSurfaceImageBacking::SkiaGraphiteRepresentation::BeginWriteAccess() {
|
||||
IOSurfaceImageBacking::SkiaGraphiteMetalRepresentation::BeginWriteAccess() {
|
||||
if (!backing_impl()->BeginAccess(/*readonly=*/false)) {
|
||||
return {};
|
||||
}
|
||||
return CreateGraphiteMetalTextures(mtl_textures_, format(), size());
|
||||
}
|
||||
|
||||
void IOSurfaceImageBacking::SkiaGraphiteRepresentation::EndWriteAccess() {
|
||||
void IOSurfaceImageBacking::SkiaGraphiteMetalRepresentation::EndWriteAccess() {
|
||||
#if DCHECK_IS_ON()
|
||||
for (auto& surface : write_surfaces_) {
|
||||
DCHECK(surface->unique());
|
||||
@ -611,14 +611,14 @@ void IOSurfaceImageBacking::SkiaGraphiteRepresentation::EndWriteAccess() {
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>>
|
||||
IOSurfaceImageBacking::SkiaGraphiteRepresentation::BeginReadAccess() {
|
||||
IOSurfaceImageBacking::SkiaGraphiteMetalRepresentation::BeginReadAccess() {
|
||||
if (!backing_impl()->BeginAccess(/*readonly=*/true)) {
|
||||
return {};
|
||||
}
|
||||
return CreateGraphiteMetalTextures(mtl_textures_, format(), size());
|
||||
}
|
||||
|
||||
void IOSurfaceImageBacking::SkiaGraphiteRepresentation::EndReadAccess() {
|
||||
void IOSurfaceImageBacking::SkiaGraphiteMetalRepresentation::EndReadAccess() {
|
||||
backing_impl()->EndAccess(/*readonly=*/true);
|
||||
}
|
||||
#endif
|
||||
@ -732,7 +732,6 @@ class IOSurfaceImageBacking::DawnRepresentation final
|
||||
wgpu::Texture BeginAccess(wgpu::TextureUsage usage,
|
||||
wgpu::TextureUsage internal_usage) final;
|
||||
void EndAccess() final;
|
||||
bool SupportsMultipleConcurrentReadAccess() final;
|
||||
|
||||
private:
|
||||
static constexpr wgpu::TextureUsage kReadOnlyUsage =
|
||||
@ -774,14 +773,14 @@ wgpu::Texture IOSurfaceImageBacking::DawnRepresentation::BeginAccess(
|
||||
usage_ = wgpu_texture_usage;
|
||||
internal_usage_ = internal_usage;
|
||||
|
||||
texture_ = iosurface_backing->GetDawnTextureHolder()->GetCachedWGPUTexture(
|
||||
texture_ = iosurface_backing->GetDawnTextureCache()->GetCachedWGPUTexture(
|
||||
device_, usage_);
|
||||
if (!texture_) {
|
||||
texture_ = CreateWGPUTexture(shared_texture_memory_, usage(),
|
||||
io_surface_size_, wgpu_format_, view_formats_,
|
||||
wgpu_texture_usage, internal_usage);
|
||||
iosurface_backing->GetDawnTextureHolder()->MaybeCacheWGPUTexture(device_,
|
||||
texture_);
|
||||
iosurface_backing->GetDawnTextureCache()->MaybeCacheWGPUTexture(device_,
|
||||
texture_);
|
||||
}
|
||||
|
||||
// If there is already an ongoing Dawn access for this texture, then the
|
||||
@ -842,14 +841,14 @@ wgpu::Texture IOSurfaceImageBacking::DawnRepresentation::BeginAccess(
|
||||
// handling.
|
||||
LOG(ERROR) << "SharedTextureMemory::BeginAccess() failed";
|
||||
iosurface_backing->TrackEndAccessToWGPUTexture(texture_);
|
||||
iosurface_backing->GetDawnTextureHolder()->RemoveWGPUTextureFromCache(
|
||||
iosurface_backing->GetDawnTextureCache()->RemoveWGPUTextureFromCache(
|
||||
device_, texture_);
|
||||
texture_ = {};
|
||||
texture_ = nullptr;
|
||||
|
||||
iosurface_backing->EndAccess(readonly);
|
||||
}
|
||||
|
||||
return texture_.Get();
|
||||
return texture_;
|
||||
}
|
||||
|
||||
void IOSurfaceImageBacking::DawnRepresentation::EndAccess() {
|
||||
@ -884,7 +883,7 @@ void IOSurfaceImageBacking::DawnRepresentation::EndAccess() {
|
||||
}
|
||||
|
||||
wgpu::SharedTextureMemoryEndAccessState end_access_desc;
|
||||
CHECK_EQ(shared_texture_memory_.EndAccess(texture_.Get(), &end_access_desc),
|
||||
CHECK_EQ(shared_texture_memory_.EndAccess(texture_, &end_access_desc),
|
||||
wgpu::Status::Success);
|
||||
|
||||
if (end_access_desc.initialized) {
|
||||
@ -912,7 +911,7 @@ void IOSurfaceImageBacking::DawnRepresentation::EndAccess() {
|
||||
readonly);
|
||||
}
|
||||
|
||||
iosurface_backing->GetDawnTextureHolder()->DestroyWGPUTextureIfNotCached(
|
||||
iosurface_backing->GetDawnTextureCache()->DestroyWGPUTextureIfNotCached(
|
||||
device_, texture_);
|
||||
|
||||
if (end_access_desc.fenceCount > 0) {
|
||||
@ -930,6 +929,19 @@ void IOSurfaceImageBacking::DawnRepresentation::EndAccess() {
|
||||
usage_ = internal_usage_ = wgpu::TextureUsage::None;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SkiaGraphiteDawnMetalRepresentation
|
||||
|
||||
class IOSurfaceImageBacking::SkiaGraphiteDawnMetalRepresentation
|
||||
: public SkiaGraphiteDawnImageRepresentation {
|
||||
public:
|
||||
using SkiaGraphiteDawnImageRepresentation::
|
||||
SkiaGraphiteDawnImageRepresentation;
|
||||
~SkiaGraphiteDawnMetalRepresentation() override = default;
|
||||
|
||||
bool SupportsMultipleConcurrentReadAccess() final;
|
||||
};
|
||||
|
||||
// Enabling this functionality reduces overhead in the compositor by lowering
|
||||
// the frequency of begin/end access pairs. The semantic constraints for a
|
||||
// representation being able to return true are the following:
|
||||
@ -946,10 +958,8 @@ void IOSurfaceImageBacking::DawnRepresentation::EndAccess() {
|
||||
// Vulkan access). SupportsMultipleConcurrentReadAccess() results in the
|
||||
// compositor's read access being long-lived (i.e., beyond the scope of
|
||||
// a single GPU task).
|
||||
// The Graphite Skia representation returns true if the underlying Dawn
|
||||
// representation does so. This representation meets both of the above
|
||||
// constraints.
|
||||
bool IOSurfaceImageBacking::DawnRepresentation::
|
||||
// This representation meets both of the above constraints.
|
||||
bool IOSurfaceImageBacking::SkiaGraphiteDawnMetalRepresentation::
|
||||
SupportsMultipleConcurrentReadAccess() {
|
||||
return true;
|
||||
}
|
||||
@ -989,7 +999,7 @@ IOSurfaceImageBacking::IOSurfaceImageBacking(
|
||||
IOSurfaceGetHeight(io_surface_.get())),
|
||||
io_surface_format_(IOSurfaceGetPixelFormat(io_surface_.get())),
|
||||
io_surface_id_(io_surface_id),
|
||||
dawn_texture_holder_(std::make_unique<DawnSharedTextureHolder>()),
|
||||
dawn_texture_cache_(base::MakeRefCounted<DawnSharedTextureCache>()),
|
||||
gl_target_(gl_target),
|
||||
framebuffer_attachment_angle_(framebuffer_attachment_angle),
|
||||
cleared_rect_(is_cleared ? gfx::Rect(size) : gfx::Rect()),
|
||||
@ -1280,8 +1290,9 @@ int IOSurfaceImageBacking::TrackEndAccessToWGPUTexture(wgpu::Texture texture) {
|
||||
return num_outstanding_accesses;
|
||||
}
|
||||
|
||||
DawnSharedTextureHolder* IOSurfaceImageBacking::GetDawnTextureHolder() {
|
||||
return dawn_texture_holder_.get();
|
||||
const scoped_refptr<DawnSharedTextureCache>&
|
||||
IOSurfaceImageBacking::GetDawnTextureCache() {
|
||||
return dawn_texture_cache_;
|
||||
}
|
||||
|
||||
void IOSurfaceImageBacking::AddWGPUDeviceWithPendingCommands(
|
||||
@ -1351,12 +1362,12 @@ std::unique_ptr<DawnImageRepresentation> IOSurfaceImageBacking::ProduceDawn(
|
||||
// importantly ensures that a new SharedTextureMemory instance will be
|
||||
// created if another Device occupies the same memory as a previously-used,
|
||||
// now-lost Device.
|
||||
dawn_texture_holder_->EraseDataIfDeviceLost();
|
||||
dawn_texture_cache_->EraseDataIfDeviceLost();
|
||||
|
||||
CHECK(device.HasFeature(wgpu::FeatureName::SharedTextureMemoryIOSurface));
|
||||
|
||||
wgpu::SharedTextureMemory shared_texture_memory =
|
||||
dawn_texture_holder_->GetSharedTextureMemory(device);
|
||||
dawn_texture_cache_->GetSharedTextureMemory(device);
|
||||
if (!shared_texture_memory) {
|
||||
// NOTE: `shared_dawn_context` may be null if Graphite is not being used.
|
||||
const auto* shared_dawn_context = context_state->dawn_context_provider();
|
||||
@ -1390,7 +1401,7 @@ std::unique_ptr<DawnImageRepresentation> IOSurfaceImageBacking::ProduceDawn(
|
||||
if (is_graphite_device) {
|
||||
// This is the Graphite device, so we cache its SharedTextureMemory
|
||||
// instance.
|
||||
dawn_texture_holder_->MaybeCacheSharedTextureMemory(
|
||||
dawn_texture_cache_->MaybeCacheSharedTextureMemory(
|
||||
device, shared_texture_memory);
|
||||
}
|
||||
}
|
||||
@ -1460,9 +1471,18 @@ IOSurfaceImageBacking::ProduceSkiaGraphite(
|
||||
LOG(ERROR) << "Could not create Dawn Representation";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Use GPU main recorder since this should only be called for
|
||||
// fulfilling Graphite promise images on GPU main thread.
|
||||
return SkiaGraphiteDawnImageRepresentation::Create(
|
||||
if (backend_type == wgpu::BackendType::Metal) {
|
||||
return std::make_unique<SkiaGraphiteDawnMetalRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker);
|
||||
}
|
||||
|
||||
// Use default skia representation
|
||||
CHECK_EQ(backend_type, wgpu::BackendType::Vulkan);
|
||||
return std::make_unique<SkiaGraphiteDawnImageRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker);
|
||||
#else
|
||||
@ -1489,7 +1509,7 @@ IOSurfaceImageBacking::ProduceSkiaGraphite(
|
||||
|
||||
// Use GPU main recorder since this should only be called for
|
||||
// fulfilling Graphite promise images on GPU main thread.
|
||||
return std::make_unique<SkiaGraphiteRepresentation>(
|
||||
return std::make_unique<SkiaGraphiteMetalRepresentation>(
|
||||
manager, this, tracker, context_state->gpu_main_graphite_recorder(),
|
||||
std::move(mtl_textures));
|
||||
#else
|
||||
|
@ -195,7 +195,7 @@ OzoneImageBacking::ProduceSkiaGraphite(
|
||||
|
||||
// Use GPU main recorder since this should only be called for
|
||||
// fulfilling Graphite promise images on GPU main thread.
|
||||
return SkiaGraphiteDawnImageRepresentation::Create(
|
||||
return std::make_unique<SkiaGraphiteDawnImageRepresentation>(
|
||||
std::move(dawn_representation), context_state,
|
||||
context_state->gpu_main_graphite_recorder(), manager, this, tracker);
|
||||
#else
|
||||
|
@ -940,10 +940,6 @@ wgpu::Texture DawnImageRepresentation::BeginAccess(
|
||||
return this->BeginAccess(usage, internal_usage);
|
||||
}
|
||||
|
||||
bool DawnImageRepresentation::SupportsMultipleConcurrentReadAccess() {
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// DawnBufferRepresentation
|
||||
|
||||
|
@ -867,8 +867,6 @@ class GPU_GLES2_EXPORT DawnImageRepresentation
|
||||
AllowUnclearedAccess allow_uncleared,
|
||||
const gfx::Rect& update_rect);
|
||||
|
||||
virtual bool SupportsMultipleConcurrentReadAccess();
|
||||
|
||||
private:
|
||||
friend class WrappedDawnCompoundImageRepresentation;
|
||||
|
||||
|
@ -54,28 +54,13 @@ wgpu::TextureUsage GetSupportedDawnTextureUsage(
|
||||
backing->format(), backing->format().is_multi_plane(), is_dcomp_surface,
|
||||
supports_multiplanar_rendering, supports_multiplanar_copy);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// static method.
|
||||
std::unique_ptr<SkiaGraphiteDawnImageRepresentation>
|
||||
SkiaGraphiteDawnImageRepresentation::Create(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice) {
|
||||
CHECK(dawn_representation);
|
||||
return base::WrapUnique(new SkiaGraphiteDawnImageRepresentation(
|
||||
std::move(dawn_representation), recorder, std::move(context_state),
|
||||
manager, backing, tracker, array_slice));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SkiaGraphiteDawnImageRepresentation::SkiaGraphiteDawnImageRepresentation(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
@ -99,11 +84,15 @@ SkiaGraphiteDawnImageRepresentation::~SkiaGraphiteDawnImageRepresentation() {
|
||||
}
|
||||
}
|
||||
|
||||
wgpu::Device SkiaGraphiteDawnImageRepresentation::GetDevice() const {
|
||||
return context_state_->dawn_context_provider()->GetDevice();
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>>
|
||||
SkiaGraphiteDawnImageRepresentation::CreateBackendTextures(
|
||||
SkiaGraphiteDawnImageRepresentation::CreateBackendTextureHolders(
|
||||
wgpu::Texture texture,
|
||||
bool readonly) {
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> backend_textures;
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures;
|
||||
const bool supports_multiplanar_rendering =
|
||||
SupportsMultiplanarRendering(context_state_.get());
|
||||
const bool supports_multiplanar_copy =
|
||||
@ -126,16 +115,31 @@ SkiaGraphiteDawnImageRepresentation::CreateBackendTextures(
|
||||
/*mipmapped=*/false,
|
||||
/*scanout_dcomp_surface=*/false, supports_multiplanar_rendering,
|
||||
supports_multiplanar_copy);
|
||||
backend_textures.emplace_back(base::MakeRefCounted<GraphiteTextureHolder>(
|
||||
skgpu::graphite::BackendTextures::MakeDawn(plane_size, plane_info,
|
||||
texture.Get())));
|
||||
backend_textures.emplace_back(skgpu::graphite::BackendTextures::MakeDawn(
|
||||
plane_size, plane_info, texture.Get()));
|
||||
}
|
||||
} else {
|
||||
backend_textures = {base::MakeRefCounted<GraphiteTextureHolder>(
|
||||
skgpu::graphite::BackendTextures::MakeDawn(texture.Get()))};
|
||||
backend_textures = {
|
||||
skgpu::graphite::BackendTextures::MakeDawn(texture.Get())};
|
||||
}
|
||||
|
||||
return backend_textures;
|
||||
return WrapBackendTextures(std::move(texture), std::move(backend_textures));
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<SkiaImageRepresentation::GraphiteTextureHolder>>
|
||||
SkiaGraphiteDawnImageRepresentation::WrapBackendTextures(
|
||||
wgpu::Texture texture,
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures) {
|
||||
// Default implementation. Create non-owning wrappers.
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> graphite_holders;
|
||||
graphite_holders.reserve(backend_textures.size());
|
||||
|
||||
for (auto& backend_texture : backend_textures) {
|
||||
graphite_holders.emplace_back(base::MakeRefCounted<GraphiteTextureHolder>(
|
||||
std::move(backend_texture)));
|
||||
}
|
||||
|
||||
return graphite_holders;
|
||||
}
|
||||
|
||||
std::vector<sk_sp<SkSurface>>
|
||||
@ -151,8 +155,9 @@ SkiaGraphiteDawnImageRepresentation::BeginWriteAccess(
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> backend_textures =
|
||||
CreateBackendTextures(dawn_scoped_access_->texture(), /*readonly=*/false);
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> graphite_texture_holders =
|
||||
CreateBackendTextureHolders(dawn_scoped_access_->texture(),
|
||||
/*readonly=*/false);
|
||||
|
||||
std::vector<sk_sp<SkSurface>> surfaces;
|
||||
surfaces.reserve(format().NumberOfPlanes());
|
||||
@ -162,12 +167,18 @@ SkiaGraphiteDawnImageRepresentation::BeginWriteAccess(
|
||||
if (sk_color_type == kGray_8_SkColorType) {
|
||||
sk_color_type = kAlpha_8_SkColorType;
|
||||
}
|
||||
void* release_context =
|
||||
scoped_refptr<GraphiteTextureHolder>(graphite_texture_holders[plane])
|
||||
.release();
|
||||
auto release_proc = [](void* context) {
|
||||
static_cast<GraphiteTextureHolder*>(context)->Release();
|
||||
};
|
||||
|
||||
auto surface = SkSurfaces::WrapBackendTexture(
|
||||
recorder_, backend_textures[plane]->texture(), sk_color_type,
|
||||
recorder_, graphite_texture_holders[plane]->texture(), sk_color_type,
|
||||
backing()->color_space().GetAsFullRangeRGB().ToSkColorSpace(),
|
||||
&surface_props, /*textureReleaseProc=*/nullptr,
|
||||
/*releaseContext=*/nullptr, WrappedTextureDebugLabel(plane));
|
||||
&surface_props, release_proc, release_context,
|
||||
WrappedTextureDebugLabel(plane));
|
||||
if (!surface) {
|
||||
DLOG(ERROR) << "Could not create SkSurface";
|
||||
dawn_scoped_access_.reset();
|
||||
@ -193,8 +204,8 @@ SkiaGraphiteDawnImageRepresentation::BeginWriteAccess() {
|
||||
}
|
||||
|
||||
mode_ = RepresentationAccessMode::kWrite;
|
||||
return CreateBackendTextures(dawn_scoped_access_->texture(),
|
||||
/*readonly=*/false);
|
||||
return CreateBackendTextureHolders(dawn_scoped_access_->texture(),
|
||||
/*readonly=*/false);
|
||||
}
|
||||
|
||||
void SkiaGraphiteDawnImageRepresentation::EndWriteAccess() {
|
||||
@ -217,8 +228,8 @@ SkiaGraphiteDawnImageRepresentation::BeginReadAccess() {
|
||||
}
|
||||
|
||||
mode_ = RepresentationAccessMode::kRead;
|
||||
return CreateBackendTextures(dawn_scoped_access_->texture(),
|
||||
/*readonly=*/true);
|
||||
return CreateBackendTextureHolders(dawn_scoped_access_->texture(),
|
||||
/*readonly=*/true);
|
||||
}
|
||||
|
||||
void SkiaGraphiteDawnImageRepresentation::EndReadAccess() {
|
||||
@ -227,9 +238,4 @@ void SkiaGraphiteDawnImageRepresentation::EndReadAccess() {
|
||||
mode_ = RepresentationAccessMode::kNone;
|
||||
}
|
||||
|
||||
bool SkiaGraphiteDawnImageRepresentation::
|
||||
SupportsMultipleConcurrentReadAccess() {
|
||||
return dawn_representation_->SupportsMultipleConcurrentReadAccess();
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
|
@ -16,7 +16,7 @@ namespace gpu {
|
||||
class GPU_GLES2_EXPORT SkiaGraphiteDawnImageRepresentation
|
||||
: public SkiaGraphiteImageRepresentation {
|
||||
public:
|
||||
static std::unique_ptr<SkiaGraphiteDawnImageRepresentation> Create(
|
||||
SkiaGraphiteDawnImageRepresentation(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
@ -24,7 +24,6 @@ class GPU_GLES2_EXPORT SkiaGraphiteDawnImageRepresentation
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice = 0);
|
||||
|
||||
~SkiaGraphiteDawnImageRepresentation() override;
|
||||
|
||||
std::vector<sk_sp<SkSurface>> BeginWriteAccess(
|
||||
@ -35,22 +34,24 @@ class GPU_GLES2_EXPORT SkiaGraphiteDawnImageRepresentation
|
||||
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> BeginReadAccess() override;
|
||||
void EndReadAccess() override;
|
||||
bool SupportsMultipleConcurrentReadAccess() override;
|
||||
|
||||
wgpu::Device GetDevice() const;
|
||||
|
||||
protected:
|
||||
SkiaGraphiteDawnImageRepresentation(
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation,
|
||||
skgpu::graphite::Recorder* recorder,
|
||||
scoped_refptr<SharedContextState> context_state,
|
||||
SharedImageManager* manager,
|
||||
SharedImageBacking* backing,
|
||||
MemoryTypeTracker* tracker,
|
||||
int array_slice);
|
||||
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> CreateBackendTextures(
|
||||
// This will create a list of non-owning or owning BackendTexture wrappers
|
||||
// depending on the implementation defined function below which will be
|
||||
// invoked by this function.
|
||||
std::vector<scoped_refptr<GraphiteTextureHolder>> CreateBackendTextureHolders(
|
||||
wgpu::Texture texture,
|
||||
bool readonly);
|
||||
|
||||
// Implementation defined function to create a list of GraphiteTextureHolder.
|
||||
// The default implementation will return a list of non owning BackendTexture
|
||||
// wrappers which will only be safe to be used inside the access scope.
|
||||
virtual std::vector<scoped_refptr<GraphiteTextureHolder>> WrapBackendTextures(
|
||||
wgpu::Texture texture,
|
||||
std::vector<skgpu::graphite::BackendTexture> backend_textures);
|
||||
|
||||
std::unique_ptr<DawnImageRepresentation> dawn_representation_;
|
||||
std::unique_ptr<DawnImageRepresentation::ScopedAccess> dawn_scoped_access_;
|
||||
scoped_refptr<SharedContextState> context_state_;
|
||||
|
Reference in New Issue
Block a user