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];
22 return status == ZX_OK ? std::string(
name) : std::string();
26 zx_info_handle_basic_t
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());
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()
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
#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)