7#include <fuchsia/sysmem/cpp/fidl.h>
8#include <lib/async/default.h>
12#include "flutter/fml/logging.h"
13#include "flutter/fml/trace_event.h"
25#include "vulkan/vulkan_fuchsia.h"
27#define LOG_AND_RETURN(cond, msg) \
29 FML_LOG(ERROR) << msg; \
44const VkSysmemColorSpaceFUCHSIA kSrgbColorSpace = {
47 .colorSpace =
static_cast<uint32_t
>(fuchsia::sysmem::ColorSpaceType::SRGB),
54 VulkanImage* out_vulkan_image) {
60 out_vulkan_image->vk_collection_image_create_info = {
63 .collection = collection_,
67 out_vulkan_image->vk_image_create_info = {
69 .pNext = &out_vulkan_image->vk_collection_image_create_info,
70 .flags = kVulkanImageCreateFlags,
72 .format = kVulkanFormat,
74 static_cast<uint32_t
>(
size.height()), 1},
79 .usage = kVkImageUsage,
81 .queueFamilyIndexCount = 0,
82 .pQueueFamilyIndices =
nullptr,
86 const VkImageFormatConstraintsInfoFUCHSIA format_constraints = {
89 .imageCreateInfo = out_vulkan_image->vk_image_create_info,
92 .sysmemPixelFormat = {},
94 .pColorSpaces = &kSrgbColorSpace,
97 const VkImageConstraintsInfoFUCHSIA image_constraints = {
100 .formatConstraintsCount = 1,
101 .pFormatConstraints = &format_constraints,
102 .bufferCollectionConstraints =
111 .minBufferCountForCamping = 0,
112 .minBufferCountForDedicatedSlack = 0,
113 .minBufferCountForSharedSlack = 0,
119 vulkan_provider.
vk().SetBufferCollectionImageConstraintsFUCHSIA(
120 vulkan_provider.
vk_device(), collection_, &image_constraints)) !=
129 &out_vulkan_image->vk_image_create_info,
nullptr, &vk_image)) !=
135 vk_image, [&vulkan_provider = vulkan_provider](VkImage
image) {
136 vulkan_provider.vk().DestroyImage(vulkan_provider.vk_device(),
image,
141 vulkan_provider.
vk().GetImageMemoryRequirements(
142 vulkan_provider.
vk_device(), out_vulkan_image->vk_image,
143 &out_vulkan_image->vk_memory_requirements);
150 fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
151 fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
154 : vulkan_provider_(vulkan_provider), wait_(this) {
155 FML_CHECK(flatland_allocator.is_bound());
158 if (!AllocateDeviceMemory(sysmem_allocator, flatland_allocator,
159 std::move(context),
size)) {
160 FML_LOG(
ERROR) <<
"VulkanSurface: Could not allocate device memory.";
164 if (!CreateFences()) {
165 FML_LOG(
ERROR) <<
"VulkanSurface: Could not create signal fences.";
171 wait_.set_object(release_event_.get());
172 wait_.set_trigger(ZX_EVENT_SIGNALED);
179 if (release_image_callback_) {
180 release_image_callback_();
183 wait_.set_object(ZX_HANDLE_INVALID);
201 VkSemaphore semaphore;
204 zx_status_t status =
event.duplicate(ZX_RIGHT_SAME_RIGHTS, &semaphore_event);
205 if (status != ZX_OK) {
206 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to duplicate semaphore event";
217 vulkan_provider_.
vk_device(), &create_info,
nullptr, &semaphore));
222 VkImportSemaphoreZirconHandleInfoFUCHSIA import_info = {
225 .semaphore = semaphore,
227 .zirconHandle =
static_cast<uint32_t
>(semaphore_event.release())};
230 vulkan_provider_.
vk().ImportSemaphoreZirconHandleFUCHSIA(
231 vulkan_provider_.
vk_device(), &import_info));
237 semaphore, [&vulkan_provider = vulkan_provider_](VkSemaphore semaphore) {
238 vulkan_provider.
vk().DestroySemaphore(vulkan_provider.
vk_device(),
243bool VulkanSurface::CreateFences() {
245 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to create acquire event";
249 acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
250 if (!acquire_semaphore_) {
251 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to create acquire semaphore";
256 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to create release event";
260 command_buffer_fence_ = vulkan_provider_.
CreateFence();
265bool VulkanSurface::AllocateDeviceMemory(
266 fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
267 fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
270 if (
size.isEmpty()) {
272 <<
"VulkanSurface: Failed to allocate surface, size is empty";
276 fuchsia::sysmem::BufferCollectionTokenSyncPtr vulkan_token;
278 sysmem_allocator->AllocateSharedCollection(vulkan_token.NewRequest());
280 "VulkanSurface: Failed to allocate collection");
281 fuchsia::sysmem::BufferCollectionTokenSyncPtr scenic_token;
283 scenic_token.NewRequest());
285 "VulkanSurface: Failed to duplicate collection token");
286 status = vulkan_token->Sync();
288 "VulkanSurface: Failed to sync collection token");
290 fuchsia::ui::composition::BufferCollectionExportToken export_token;
293 fuchsia::ui::composition::RegisterBufferCollectionArgs
args;
294 args.set_export_token(std::move(export_token));
295 args.set_buffer_collection_token(std::move(scenic_token));
297 fuchsia::ui::composition::RegisterBufferCollectionUsage::DEFAULT);
298 flatland_allocator->RegisterBufferCollection(
300 [](fuchsia::ui::composition::Allocator_RegisterBufferCollection_Result
304 <<
"RegisterBufferCollection call to Scenic Allocator failed";
308 VkBufferCollectionCreateInfoFUCHSIA import_info{
311 .collectionToken = vulkan_token.Unbind().TakeChannel().release(),
313 VkBufferCollectionFUCHSIA collection;
315 vulkan_provider_.
vk_device(), &import_info,
nullptr, &collection)) !=
321 collection, [&vulkan_provider =
322 vulkan_provider_](VkBufferCollectionFUCHSIA collection) {
323 vulkan_provider.vk().DestroyBufferCollectionFUCHSIA(
324 vulkan_provider.vk_device(), collection,
nullptr);
327 VulkanImage vulkan_image;
329 "VulkanSurface: Failed to create VkImage");
331 vulkan_image_ = std::move(vulkan_image);
336 VkBufferCollectionPropertiesFUCHSIA properties{
339 vulkan_provider_.
vk().GetBufferCollectionPropertiesFUCHSIA(
340 vulkan_provider_.
vk_device(), collection_, &properties)) !=
345 VkImportMemoryBufferCollectionFUCHSIA import_memory_info = {
348 .collection = collection_,
355 .pNext = &import_memory_info,
356 .allocationSize = memory_requirements.
size,
357 .memoryTypeIndex =
static_cast<uint32_t
>(__builtin_ctz(
bits)),
361 TRACE_EVENT1(
"flutter",
"vkAllocateMemory",
"allocationSize",
365 vulkan_provider_.
vk_device(), &allocation_info, NULL,
372 [&vulkan_provider = vulkan_provider_](VkDeviceMemory memory) {
373 vulkan_provider.vk().FreeMemory(vulkan_provider.vk_device(), memory,
377 vk_memory_info_ = allocation_info;
387 return SetupSkiaSurface(std::move(context),
size, kSkiaColorType,
388 image_create_info, memory_requirements);
406 image_info.
fAlloc = alloc;
414 auto sk_render_target =
428 if (!sk_surface || sk_surface->getCanvas() ==
nullptr) {
430 <<
"VulkanSurface: SkSurfaces::WrapBackendRenderTarget failed";
433 sk_surface_ = std::move(sk_surface);
440 image_id_ = image_id;
448 return valid_ ? sk_surface_ :
nullptr;
451fuchsia::ui::composition::BufferCollectionImportToken
453 fuchsia::ui::composition::BufferCollectionImportToken import_dup;
454 import_token_.value.duplicate(ZX_RIGHT_SAME_RIGHTS, &import_dup.value);
460 acquire_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
466 release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
471 release_image_callback_ = release_image_callback;
475 size_history_[size_history_index_] =
GetSize();
476 size_history_index_ = (size_history_index_ + 1) % kSizeHistorySize;
491 on_writes_committed();
495 FML_CHECK(pending_on_writes_committed_ ==
nullptr)
496 <<
"Attempted to signal a write on the surface when the "
497 "previous write has not yet been acknowledged by the "
500 pending_on_writes_committed_ = on_writes_committed;
503void VulkanSurface::Reset() {
504 if (acquire_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK ||
505 release_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK) {
507 FML_LOG(
ERROR) <<
"Could not reset fences. The surface is no longer valid.";
510 VkFence fence = command_buffer_fence_;
512 if (command_buffer_) {
515 command_buffer_.reset();
519 vulkan_provider_.
vk_device(), 1, &fence));
523 acquire_semaphore_.
Reset();
524 acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
525 if (!acquire_semaphore_) {
529 wait_.Begin(async_get_default_dispatcher());
532 auto callback = pending_on_writes_committed_;
533 pending_on_writes_committed_ =
nullptr;
539void VulkanSurface::OnHandleReady(async_dispatcher_t* dispatcher,
540 async::WaitBase* wait,
542 const zx_packet_signal_t* signal) {
545 FML_DCHECK(signal->observed & ZX_EVENT_SIGNALED);
@ kTopLeft_GrSurfaceOrigin
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kUnknown_SkPixelGeometry
static sk_sp< SkColorSpace > MakeSRGB()
void SetReleaseImageCallback(ReleaseImageCallback release_image_callback) override
fuchsia::ui::composition::BufferCollectionImportToken GetBufferCollectionImportToken() override
bool IsValid() const override
zx::event GetAcquireFence() override
~VulkanSurface() override
void SignalWritesFinished(const std::function< void(void)> &on_writes_committed) override
SkISize GetSize() const override
bool FlushSessionAcquireAndReleaseEvents() override
uint32_t GetImageId() override
void SetImageId(uint32_t image_id) override
size_t AdvanceAndGetAge() override
sk_sp< SkSurface > GetSkiaSurface() const override
zx::event GetReleaseFence() override
VulkanSurface(vulkan::VulkanProvider &vulkan_provider, fuchsia::sysmem::AllocatorSyncPtr &sysmem_allocator, fuchsia::ui::composition::AllocatorPtr &flatland_allocator, sk_sp< GrDirectContext > context, const SkISize &size)
vulkan::VulkanHandle< VkFence > CreateFence()
virtual const vulkan::VulkanProcTable & vk()=0
virtual const vulkan::VulkanHandle< VkDevice > & vk_device()=0
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
Dart_NativeFunction function
static float max(float r, float g, float b)
SK_API GrBackendRenderTarget MakeVk(int width, int height, const GrVkImageInfo &)
sk_sp< const SkImage > image
SK_API sk_sp< SkSurface > WrapBackendRenderTarget(GrRecordingContext *context, const GrBackendRenderTarget &backendRenderTarget, GrSurfaceOrigin origin, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, RenderTargetReleaseProc releaseProc=nullptr, ReleaseContext releaseContext=nullptr)
std::function< void()> ReleaseImageCallback
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
skgpu::VulkanAlloc fAlloc
VkImageLayout fImageLayout
VkImageUsageFlags fImageUsageFlags
VkImageTiling fImageTiling
static constexpr SkISize MakeEmpty()
static constexpr SkISize Make(int32_t w, int32_t h)
VkImageLayout initialLayout
VkDeviceSize allocationSize
VkImageCreateInfo vk_image_create_info
VkMemoryRequirements vk_memory_requirements
vulkan::VulkanHandle< VkImage > vk_image
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
@ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_SHARING_MODE_EXCLUSIVE
VkFlags VkImageUsageFlags
@ VK_IMAGE_TILING_OPTIMAL
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_SAMPLED_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
VkFlags VkImageCreateFlags
@ VK_FORMAT_R8G8B8A8_UNORM
@ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA
@ VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA
@ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
@ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA
@ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA
@ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA
@ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
@ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA
@ VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA
@ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
@ VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA
@ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA
@ VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA
#define VK_CALL_LOG_FATAL(expression)
#define VK_CALL_LOG_ERROR(expression)