7#include <lib/fdio/directory.h>
8#include <lib/zx/process.h>
14#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
19 char name[ZX_MAX_NAME_LEN];
21 zx::process::self()->get_property(ZX_PROP_NAME,
name,
sizeof(
name));
22 return status == ZX_OK ? std::string(
name) : std::string();
26 zx_info_handle_basic_t info;
27 zx_status_t status = zx::process::self()->get_info(
28 ZX_INFO_HANDLE_BASIC, &info,
sizeof(info),
nullptr,
nullptr);
29 return status == ZX_OK ? info.koid : ZX_KOID_INVALID;
33 sk_sp<GrDirectContext> context)
34 : vulkan_provider_(vulkan_provider), context_(
std::move(context)) {
37 zx_status_t status = fdio_service_connect(
38 "/svc/fuchsia.sysmem2.Allocator",
39 sysmem_allocator_.NewRequest().TakeChannel().release());
40 sysmem_allocator_->SetDebugClientInfo(
41 std::move(fuchsia::sysmem2::AllocatorSetDebugClientInfoRequest{}
46 status = fdio_service_connect(
47 "/svc/fuchsia.ui.composition.Allocator",
48 flatland_allocator_.NewRequest().TakeChannel().release());
55 const SkISize& size) {
56 auto surface = GetCachedOrCreateSurface(size);
59 FML_LOG(ERROR) <<
"VulkanSurfaceProducer: Could not acquire surface";
63 if (!
surface->FlushSessionAcquireAndReleaseEvents()) {
64 FML_LOG(ERROR) <<
"VulkanSurfaceProducer: Could not flush acquire/release "
72std::unique_ptr<VulkanSurface> VulkanSurfacePool::GetCachedOrCreateSurface(
73 const SkISize& size) {
74 TRACE_EVENT2(
"flutter",
"VulkanSurfacePool::GetCachedOrCreateSurface",
75 "width", size.width(),
"height", size.height());
79 std::find_if(available_surfaces_.begin(), available_surfaces_.end(),
80 [&size](
const auto& surface) {
81 return surface->IsValid() && surface->GetSize() == size;
83 if (exact_match_it != available_surfaces_.end()) {
84 auto acquired_surface = std::move(*exact_match_it);
85 available_surfaces_.erase(exact_match_it);
87 return acquired_surface;
95 std::unique_ptr<SurfaceProducerSurface> p_surface) {
96 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::SubmitSurface");
102 auto vulkan_surface = std::unique_ptr<VulkanSurface>(
104 if (!vulkan_surface) {
108 uintptr_t surface_key =
reinterpret_cast<uintptr_t
>(vulkan_surface.get());
109 auto insert_iterator = pending_surfaces_.insert(std::make_pair(
111 std::move(vulkan_surface)
113 if (insert_iterator.second) {
114 insert_iterator.first->second->SignalWritesFinished(std::bind(
115 &VulkanSurfacePool::RecyclePendingSurface,
this, surface_key));
120 const SkISize& size) {
121 TRACE_EVENT2(
"flutter",
"VulkanSurfacePool::CreateSurface",
"width",
122 size.width(),
"height", size.height());
123 auto surface = std::make_unique<VulkanSurface>(
124 vulkan_provider_, sysmem_allocator_, flatland_allocator_, context_, size);
126 FML_LOG(ERROR) <<
"VulkanSurfaceProducer: Created surface is invalid";
129 trace_surfaces_created_++;
133void VulkanSurfacePool::RecyclePendingSurface(uintptr_t surface_key) {
136 auto found_in_pending = pending_surfaces_.find(surface_key);
137 if (found_in_pending == pending_surfaces_.end()) {
143 auto surface_to_recycle = std::move(found_in_pending->second);
144 pending_surfaces_.erase(found_in_pending);
146 RecycleSurface(std::move(surface_to_recycle));
149void VulkanSurfacePool::RecycleSurface(std::unique_ptr<VulkanSurface> surface) {
156 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::RecycleSurface");
160 available_surfaces_.push_back(std::move(surface));
168 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::AgeAndCollectOldBuffers");
171 size_t size_before = available_surfaces_.size();
172 available_surfaces_.erase(
173 std::remove_if(available_surfaces_.begin(), available_surfaces_.end(),
175 return !surface->IsValid() ||
176 surface->AdvanceAndGetAge() >= kMaxSurfaceAge;
178 available_surfaces_.end());
179 TRACE_EVENT1(
"flutter",
"AgeAndCollect",
"aged surfaces",
180 (size_before - available_surfaces_.size()));
184 auto surface_to_remove_it = std::find_if(
185 available_surfaces_.begin(), available_surfaces_.end(),
187 return surface->IsOversized() && surface->HasStableSizeHistory();
191 if (surface_to_remove_it != available_surfaces_.end()) {
193 auto size = (*surface_to_remove_it)->GetSize();
194 available_surfaces_.erase(surface_to_remove_it);
196 if (new_surface !=
nullptr) {
197 available_surfaces_.push_back(std::move(new_surface));
200 <<
"VulkanSurfaceProducer: Failed to create a new shrunk surface";
208 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::ShrinkToFit");
212 std::vector<SkISize> sizes_to_recreate;
213 for (
auto&
surface : available_surfaces_) {
215 sizes_to_recreate.push_back(
surface->GetSize());
219 available_surfaces_.erase(std::remove(available_surfaces_.begin(),
220 available_surfaces_.end(),
nullptr),
221 available_surfaces_.end());
222 for (
const auto& size : sizes_to_recreate) {
225 available_surfaces_.push_back(std::move(
surface));
228 <<
"VulkanSurfaceProducer: Failed to create resized surface";
235void VulkanSurfacePool::TraceStats() {
237 size_t cached_surfaces_bytes = 0;
238 for (
const auto& surface : available_surfaces_) {
239 cached_surfaces_bytes +=
surface->GetAllocationSize();
243 int skia_resources = 0;
244 size_t skia_bytes = 0;
245 context_->getResourceCacheUsage(&skia_resources, &skia_bytes);
246 const size_t skia_cache_purgeable =
247 context_->getResourceCachePurgeableBytes();
249 TRACE_COUNTER(
"flutter",
"SurfacePoolCounts", 0u,
"CachedCount",
250 available_surfaces_.size(),
251 "Created", trace_surfaces_created_,
252 "Reused", trace_surfaces_reused_,
253 "PendingInCompositor", pending_surfaces_.size(),
255 "SkiaCacheResources", skia_resources
258 TRACE_COUNTER(
"flutter",
"SurfacePoolBytes", 0u,
259 "CachedBytes", cached_surfaces_bytes,
261 "SkiaCacheBytes", skia_bytes,
262 "SkiaCachePurgeable", skia_cache_purgeable
266 trace_surfaces_created_ = 0;
267 trace_surfaces_reused_ = 0;
void AgeAndCollectOldBuffers()
std::unique_ptr< VulkanSurface > CreateSurface(const SkISize &size)
static constexpr int kMaxSurfaces
void SubmitSurface(std::unique_ptr< SurfaceProducerSurface > surface)
VulkanSurfacePool(vulkan::VulkanProvider &vulkan_provider, sk_sp< GrDirectContext > context)
std::unique_ptr< VulkanSurface > AcquireSurface(const SkISize &size)
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
static zx_koid_t GetCurrentProcessId()
static std::string GetCurrentProcessName()
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_INSTANT0(category_group, name)
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)