7#include <lib/fdio/directory.h>
8#include <lib/zx/process.h>
13#include "flutter/fml/trace_event.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;
34 : vulkan_provider_(vulkan_provider), context_(
std::move(context)) {
37 zx_status_t status = fdio_service_connect(
38 "/svc/fuchsia.sysmem.Allocator",
39 sysmem_allocator_.NewRequest().TakeChannel().release());
44 status = fdio_service_connect(
45 "/svc/fuchsia.ui.composition.Allocator",
46 flatland_allocator_.NewRequest().TakeChannel().release());
54 auto surface = GetCachedOrCreateSurface(size);
57 FML_LOG(
ERROR) <<
"VulkanSurfaceProducer: Could not acquire surface";
61 if (!
surface->FlushSessionAcquireAndReleaseEvents()) {
62 FML_LOG(
ERROR) <<
"VulkanSurfaceProducer: Could not flush acquire/release "
70std::unique_ptr<VulkanSurface> VulkanSurfacePool::GetCachedOrCreateSurface(
72 TRACE_EVENT2(
"flutter",
"VulkanSurfacePool::GetCachedOrCreateSurface",
73 "width", size.width(),
"height", size.height());
77 std::find_if(available_surfaces_.begin(), available_surfaces_.end(),
79 return surface->IsValid() && surface->GetSize() == size;
81 if (exact_match_it != available_surfaces_.end()) {
82 auto acquired_surface = std::move(*exact_match_it);
83 available_surfaces_.erase(exact_match_it);
85 return acquired_surface;
93 std::unique_ptr<SurfaceProducerSurface> p_surface) {
94 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::SubmitSurface");
100 auto vulkan_surface = std::unique_ptr<VulkanSurface>(
102 if (!vulkan_surface) {
106 uintptr_t surface_key =
reinterpret_cast<uintptr_t
>(vulkan_surface.get());
107 auto insert_iterator = pending_surfaces_.insert(std::make_pair(
109 std::move(vulkan_surface)
111 if (insert_iterator.second) {
112 insert_iterator.first->second->SignalWritesFinished(std::bind(
113 &VulkanSurfacePool::RecyclePendingSurface,
this, surface_key));
119 TRACE_EVENT2(
"flutter",
"VulkanSurfacePool::CreateSurface",
"width",
120 size.width(),
"height", size.height());
121 auto surface = std::make_unique<VulkanSurface>(
122 vulkan_provider_, sysmem_allocator_, flatland_allocator_, context_, size);
124 FML_LOG(
ERROR) <<
"VulkanSurfaceProducer: Created surface is invalid";
127 trace_surfaces_created_++;
131void VulkanSurfacePool::RecyclePendingSurface(uintptr_t surface_key) {
134 auto found_in_pending = pending_surfaces_.find(surface_key);
135 if (found_in_pending == pending_surfaces_.end()) {
141 auto surface_to_recycle = std::move(found_in_pending->second);
142 pending_surfaces_.erase(found_in_pending);
144 RecycleSurface(std::move(surface_to_recycle));
147void VulkanSurfacePool::RecycleSurface(std::unique_ptr<VulkanSurface>
surface) {
154 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::RecycleSurface");
158 available_surfaces_.push_back(std::move(
surface));
166 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::AgeAndCollectOldBuffers");
169 size_t size_before = available_surfaces_.size();
170 available_surfaces_.erase(
171 std::remove_if(available_surfaces_.begin(), available_surfaces_.end(),
173 return !surface->IsValid() ||
174 surface->AdvanceAndGetAge() >= kMaxSurfaceAge;
176 available_surfaces_.end());
177 TRACE_EVENT1(
"flutter",
"AgeAndCollect",
"aged surfaces",
178 (size_before - available_surfaces_.size()));
182 auto surface_to_remove_it = std::find_if(
183 available_surfaces_.begin(), available_surfaces_.end(),
185 return surface->IsOversized() && surface->HasStableSizeHistory();
189 if (surface_to_remove_it != available_surfaces_.end()) {
191 auto size = (*surface_to_remove_it)->GetSize();
192 available_surfaces_.erase(surface_to_remove_it);
195 available_surfaces_.push_back(std::move(
new_surface));
198 <<
"VulkanSurfaceProducer: Failed to create a new shrunk surface";
206 TRACE_EVENT0(
"flutter",
"VulkanSurfacePool::ShrinkToFit");
210 std::vector<SkISize> sizes_to_recreate;
211 for (
auto&
surface : available_surfaces_) {
213 sizes_to_recreate.push_back(
surface->GetSize());
217 available_surfaces_.erase(std::remove(available_surfaces_.begin(),
218 available_surfaces_.end(),
nullptr),
219 available_surfaces_.end());
220 for (
const auto& size : sizes_to_recreate) {
223 available_surfaces_.push_back(std::move(
surface));
226 <<
"VulkanSurfaceProducer: Failed to create resized surface";
233void VulkanSurfacePool::TraceStats() {
235 size_t cached_surfaces_bytes = 0;
236 for (
const auto&
surface : available_surfaces_) {
237 cached_surfaces_bytes +=
surface->GetAllocationSize();
241 int skia_resources = 0;
242 size_t skia_bytes = 0;
244 const size_t skia_cache_purgeable =
247 TRACE_COUNTER(
"flutter",
"SurfacePoolCounts", 0u,
"CachedCount",
248 available_surfaces_.size(),
249 "Created", trace_surfaces_created_,
250 "Reused", trace_surfaces_reused_,
251 "PendingInCompositor", pending_surfaces_.size(),
253 "SkiaCacheResources", skia_resources
256 TRACE_COUNTER(
"flutter",
"SurfacePoolBytes", 0u,
257 "CachedBytes", cached_surfaces_bytes,
259 "SkiaCacheBytes", skia_bytes,
260 "SkiaCachePurgeable", skia_cache_purgeable
264 trace_surfaces_created_ = 0;
265 trace_surfaces_reused_ = 0;
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
size_t getResourceCachePurgeableBytes() const
void getResourceCacheUsage(int *resourceCount, size_t *resourceBytes) const
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)
static sk_sp< SkSurface > new_surface(int width, int height)
#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)