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"
24#include "vulkan/vulkan_fuchsia.h"
26#define LOG_AND_RETURN(cond, msg) \
28 FML_LOG(ERROR) << msg; \
43const VkSysmemColorSpaceFUCHSIA kSrgbColorSpace = {
46 .colorSpace =
static_cast<uint32_t
>(fuchsia::sysmem::ColorSpaceType::SRGB),
53 VulkanImage* out_vulkan_image) {
59 out_vulkan_image->vk_collection_image_create_info = {
62 .collection = collection_,
66 out_vulkan_image->vk_image_create_info = {
68 .pNext = &out_vulkan_image->vk_collection_image_create_info,
69 .flags = kVulkanImageCreateFlags,
71 .format = kVulkanFormat,
72 .extent =
VkExtent3D{
static_cast<uint32_t
>(size.width()),
73 static_cast<uint32_t
>(size.height()), 1},
78 .usage = kVkImageUsage,
80 .queueFamilyIndexCount = 0,
81 .pQueueFamilyIndices =
nullptr,
85 const VkImageFormatConstraintsInfoFUCHSIA format_constraints = {
88 .imageCreateInfo = out_vulkan_image->vk_image_create_info,
91 .sysmemPixelFormat = {},
93 .pColorSpaces = &kSrgbColorSpace,
96 const VkImageConstraintsInfoFUCHSIA image_constraints = {
99 .formatConstraintsCount = 1,
100 .pFormatConstraints = &format_constraints,
101 .bufferCollectionConstraints =
110 .minBufferCountForCamping = 0,
111 .minBufferCountForDedicatedSlack = 0,
112 .minBufferCountForSharedSlack = 0,
118 vulkan_provider.
vk().SetBufferCollectionImageConstraintsFUCHSIA(
119 vulkan_provider.
vk_device(), collection_, &image_constraints)) !=
128 &out_vulkan_image->vk_image_create_info,
nullptr, &vk_image)) !=
134 vk_image, [&vulkan_provider = vulkan_provider](VkImage
image) {
135 vulkan_provider.vk().DestroyImage(vulkan_provider.vk_device(),
image,
140 vulkan_provider.
vk().GetImageMemoryRequirements(
141 vulkan_provider.
vk_device(), out_vulkan_image->vk_image,
142 &out_vulkan_image->vk_memory_requirements);
149 fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
150 fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
153 : vulkan_provider_(vulkan_provider), wait_(this) {
154 FML_CHECK(flatland_allocator.is_bound());
157 if (!AllocateDeviceMemory(sysmem_allocator, flatland_allocator,
158 std::move(context), size)) {
159 FML_LOG(
ERROR) <<
"VulkanSurface: Could not allocate device memory.";
163 if (!CreateFences()) {
164 FML_LOG(
ERROR) <<
"VulkanSurface: Could not create signal fences.";
170 wait_.set_object(release_event_.get());
171 wait_.set_trigger(ZX_EVENT_SIGNALED);
178 if (release_image_callback_) {
179 release_image_callback_();
182 wait_.set_object(ZX_HANDLE_INVALID);
198 const zx::event&
event)
const {
200 VkSemaphore semaphore;
202 zx::event semaphore_event;
203 zx_status_t status =
event.duplicate(ZX_RIGHT_SAME_RIGHTS, &semaphore_event);
204 if (status != ZX_OK) {
205 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to duplicate semaphore event";
216 vulkan_provider_.
vk_device(), &create_info,
nullptr, &semaphore));
221 VkImportSemaphoreZirconHandleInfoFUCHSIA import_info = {
224 .semaphore = semaphore,
226 .zirconHandle =
static_cast<uint32_t
>(semaphore_event.release())};
229 vulkan_provider_.
vk().ImportSemaphoreZirconHandleFUCHSIA(
230 vulkan_provider_.
vk_device(), &import_info));
236 semaphore, [&vulkan_provider = vulkan_provider_](VkSemaphore semaphore) {
237 vulkan_provider.
vk().DestroySemaphore(vulkan_provider.
vk_device(),
242bool VulkanSurface::CreateFences() {
243 if (zx::event::create(0, &acquire_event_) != ZX_OK) {
244 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to create acquire event";
248 acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
249 if (!acquire_semaphore_) {
250 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to create acquire semaphore";
254 if (zx::event::create(0, &release_event_) != ZX_OK) {
255 FML_LOG(
ERROR) <<
"VulkanSurface: Failed to create release event";
259 command_buffer_fence_ = vulkan_provider_.
CreateFence();
264bool VulkanSurface::AllocateDeviceMemory(
265 fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
266 fuchsia::ui::composition::AllocatorPtr& flatland_allocator,
269 if (
size.isEmpty()) {
271 <<
"VulkanSurface: Failed to allocate surface, size is empty";
275 fuchsia::sysmem::BufferCollectionTokenSyncPtr vulkan_token;
277 sysmem_allocator->AllocateSharedCollection(vulkan_token.NewRequest());
279 "VulkanSurface: Failed to allocate collection");
280 fuchsia::sysmem::BufferCollectionTokenSyncPtr scenic_token;
281 status = vulkan_token->Duplicate(std::numeric_limits<uint32_t>::max(),
282 scenic_token.NewRequest());
284 "VulkanSurface: Failed to duplicate collection token");
285 status = vulkan_token->Sync();
287 "VulkanSurface: Failed to sync collection token");
289 fuchsia::ui::composition::BufferCollectionExportToken export_token;
290 status = zx::eventpair::create(0, &export_token.value, &import_token_.value);
292 fuchsia::ui::composition::RegisterBufferCollectionArgs
args;
293 args.set_export_token(std::move(export_token));
294 args.set_buffer_collection_token(std::move(scenic_token));
296 fuchsia::ui::composition::RegisterBufferCollectionUsage::DEFAULT);
297 flatland_allocator->RegisterBufferCollection(
299 [](fuchsia::ui::composition::Allocator_RegisterBufferCollection_Result
303 <<
"RegisterBufferCollection call to Scenic Allocator failed";
307 VkBufferCollectionCreateInfoFUCHSIA import_info{
310 .collectionToken = vulkan_token.Unbind().TakeChannel().release(),
312 VkBufferCollectionFUCHSIA collection;
314 vulkan_provider_.
vk_device(), &import_info,
nullptr, &collection)) !=
320 collection, [&vulkan_provider =
321 vulkan_provider_](VkBufferCollectionFUCHSIA collection) {
322 vulkan_provider.vk().DestroyBufferCollectionFUCHSIA(
323 vulkan_provider.vk_device(), collection,
nullptr);
326 VulkanImage vulkan_image;
327 LOG_AND_RETURN(!CreateVulkanImage(vulkan_provider_, size, &vulkan_image),
328 "VulkanSurface: Failed to create VkImage");
330 vulkan_image_ = std::move(vulkan_image);
335 VkBufferCollectionPropertiesFUCHSIA properties{
338 vulkan_provider_.
vk().GetBufferCollectionPropertiesFUCHSIA(
339 vulkan_provider_.
vk_device(), collection_, &properties)) !=
344 VkImportMemoryBufferCollectionFUCHSIA import_memory_info = {
347 .collection = collection_,
354 .pNext = &import_memory_info,
355 .allocationSize = memory_requirements.
size,
356 .memoryTypeIndex =
static_cast<uint32_t
>(__builtin_ctz(bits)),
360 TRACE_EVENT1(
"flutter",
"vkAllocateMemory",
"allocationSize",
364 vulkan_provider_.
vk_device(), &allocation_info, NULL,
371 [&vulkan_provider = vulkan_provider_](VkDeviceMemory memory) {
372 vulkan_provider.vk().FreeMemory(vulkan_provider.vk_device(), memory,
376 vk_memory_info_ = allocation_info;
386 return SetupSkiaSurface(std::move(context), size, kSkiaColorType,
387 image_create_info, memory_requirements);
405 image_info.
fAlloc = alloc;
413 auto sk_render_target =
427 if (!sk_surface || sk_surface->getCanvas() ==
nullptr) {
429 <<
"VulkanSurface: SkSurfaces::WrapBackendRenderTarget failed";
432 sk_surface_ = std::move(sk_surface);
439 image_id_ = image_id;
447 return valid_ ? sk_surface_ :
nullptr;
450fuchsia::ui::composition::BufferCollectionImportToken
452 fuchsia::ui::composition::BufferCollectionImportToken import_dup;
453 import_token_.value.duplicate(ZX_RIGHT_SAME_RIGHTS, &import_dup.value);
459 acquire_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
465 release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
470 release_image_callback_ = release_image_callback;
474 size_history_[size_history_index_] =
GetSize();
475 size_history_index_ = (size_history_index_ + 1) % kSizeHistorySize;
486 const std::function<
void(
void)>& on_writes_committed) {
490 on_writes_committed();
494 FML_CHECK(pending_on_writes_committed_ ==
nullptr)
495 <<
"Attempted to signal a write on the surface when the "
496 "previous write has not yet been acknowledged by the "
499 pending_on_writes_committed_ = on_writes_committed;
502void VulkanSurface::Reset() {
503 if (acquire_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK ||
504 release_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK) {
506 FML_LOG(
ERROR) <<
"Could not reset fences. The surface is no longer valid.";
509 VkFence fence = command_buffer_fence_;
511 if (command_buffer_) {
514 command_buffer_.reset();
518 vulkan_provider_.
vk_device(), 1, &fence));
522 acquire_semaphore_.
Reset();
523 acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
524 if (!acquire_semaphore_) {
528 wait_.Begin(async_get_default_dispatcher());
531 auto callback = pending_on_writes_committed_;
532 pending_on_writes_committed_ =
nullptr;
538void VulkanSurface::OnHandleReady(async_dispatcher_t* dispatcher,
539 async::WaitBase* wait,
541 const zx_packet_signal_t* signal) {
544 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)
SK_API GrBackendRenderTarget MakeVk(int width, int height, const GrVkImageInfo &)
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)