diff --git a/shell/platform/fuchsia/flutter/compositor_context.cc b/shell/platform/fuchsia/flutter/compositor_context.cc index da27e102d96a5..b53297d1a9a96 100644 --- a/shell/platform/fuchsia/flutter/compositor_context.cc +++ b/shell/platform/fuchsia/flutter/compositor_context.cc @@ -93,7 +93,7 @@ class ScopedFrame final : public flutter::CompositorContext::ScopedFrame { "of size: " << physical_size.width() << "x" << physical_size.height(); } else { - task.material.SetTexture(*(surface->GetImage())); + task.material.SetTexture(surface->GetImageId()); } frame_surfaces.emplace_back(std::move(surface)); diff --git a/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc b/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc index afebc157dcbd1..7effe497324b2 100644 --- a/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc +++ b/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc @@ -299,8 +299,8 @@ void FuchsiaExternalViewEmbedder::SubmitFrame( if (layer->second.canvas_spy->DidDrawIntoCanvas()) { const auto& surface_index = frame_surface_indices.find(layer_id); FML_DCHECK(surface_index != frame_surface_indices.end()); - scenic::Image* surface_image = - frame_surfaces[surface_index->second]->GetImage(); + uint32_t surface_image_id = + frame_surfaces[surface_index->second]->GetImageId(); // Create a new layer if needed for the surface. FML_DCHECK(scenic_layer_index <= scenic_layers_.size()); @@ -363,7 +363,7 @@ void FuchsiaExternalViewEmbedder::SubmitFrame( layer->second.surface_size.height() * 0.5f, -layer_elevation); scenic_layer.material.SetColor(SK_AlphaOPAQUE, SK_AlphaOPAQUE, SK_AlphaOPAQUE, SK_AlphaOPAQUE - 1); - scenic_layer.material.SetTexture(*surface_image); + scenic_layer.material.SetTexture(surface_image_id); // Only the first (i.e. the bottom-most) layer should receive input. // TODO: Workaround for invisible overlays stealing input. Remove when diff --git a/shell/platform/fuchsia/flutter/vulkan_surface.cc b/shell/platform/fuchsia/flutter/vulkan_surface.cc index a28b4dad7293c..0ba60f4b1b518 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface.cc +++ b/shell/platform/fuchsia/flutter/vulkan_surface.cc @@ -5,6 +5,7 @@ #include "vulkan_surface.h" #include +#include #include @@ -15,52 +16,51 @@ #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" +#define LOG_AND_RETURN(cond, msg) \ + if (cond) { \ + FML_DLOG(ERROR) << msg; \ + return false; \ + } + namespace flutter_runner { namespace { -// Immutable format is technically limited to R8G8B8A8_SRGB but -// R8G8B8A8_UNORM works with existing ARM drivers so we allow that -// until we have a more reliable API for creating external Vulkan -// images using sysmem. TODO(fxb/52835) -#if defined(__aarch64__) constexpr SkColorType kSkiaColorType = kRGBA_8888_SkColorType; -constexpr fuchsia::images::PixelFormat kPixelFormat = - fuchsia::images::PixelFormat::R8G8B8A8; +constexpr fuchsia::sysmem::PixelFormatType kSysmemPixelFormat = + fuchsia::sysmem::PixelFormatType::R8G8B8A8; constexpr VkFormat kVulkanFormat = VK_FORMAT_R8G8B8A8_UNORM; constexpr VkImageCreateFlags kVulkanImageCreateFlags = 0; -#else -constexpr SkColorType kSkiaColorType = kBGRA_8888_SkColorType; -constexpr fuchsia::images::PixelFormat kPixelFormat = - fuchsia::images::PixelFormat::BGRA_8; -constexpr VkFormat kVulkanFormat = VK_FORMAT_B8G8R8A8_UNORM; -constexpr VkImageCreateFlags kVulkanImageCreateFlags = - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; -#endif +// TODO: We should only keep usages that are actually required by Skia. +constexpr VkImageUsageFlags kVkImageUsage = + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; +constexpr uint32_t kSysmemImageUsage = + fuchsia::sysmem::VULKAN_IMAGE_USAGE_COLOR_ATTACHMENT | + fuchsia::sysmem::VULKAN_IMAGE_USAGE_TRANSFER_DST | + fuchsia::sysmem::VULKAN_IMAGE_USAGE_TRANSFER_SRC | + fuchsia::sysmem::VULKAN_IMAGE_USAGE_SAMPLED; } // namespace -bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider, - const SkISize& size, - VulkanImage* out_vulkan_image) { +bool VulkanSurface::CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider, + const SkISize& size, + VulkanImage* out_vulkan_image) { TRACE_EVENT0("flutter", "CreateVulkanImage"); FML_DCHECK(!size.isEmpty()); FML_DCHECK(out_vulkan_image != nullptr); - // The image creation parameters need to be the same as those in scenic - // (src/ui/scenic/lib/gfx/resources/gpu_image.cc and - // src/ui/lib/escher/util/image_utils.cc) or else the different vulkan - // devices may interpret the bytes differently. - // TODO(SCN-1369): Use API to coordinate this with scenic. - out_vulkan_image->vk_external_image_create_info = { - .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + out_vulkan_image->vk_collection_image_create_info = { + .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA, .pNext = nullptr, - .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA, + .collection = collection_, + .index = 0, }; + out_vulkan_image->vk_image_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = &out_vulkan_image->vk_external_image_create_info, + .pNext = &out_vulkan_image->vk_collection_image_create_info, .flags = kVulkanImageCreateFlags, .imageType = VK_IMAGE_TYPE_2D, .format = kVulkanFormat, @@ -70,18 +70,22 @@ bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + .usage = kVkImageUsage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; + if (VK_CALL_LOG_ERROR( + vulkan_provider.vk().SetBufferCollectionConstraintsFUCHSIA( + vulkan_provider.vk_device(), collection_, + &out_vulkan_image->vk_image_create_info)) != VK_SUCCESS) { + return false; + } + { VkImage vk_image = VK_NULL_HANDLE; - if (VK_CALL_LOG_ERROR(vulkan_provider.vk().CreateImage( vulkan_provider.vk_device(), &out_vulkan_image->vk_image_create_info, nullptr, &vk_image)) != @@ -103,35 +107,30 @@ bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider, return true; } -VulkanSurface::VulkanSurface(vulkan::VulkanProvider& vulkan_provider, - sk_sp context, - scenic::Session* session, - const SkISize& size) - : vulkan_provider_(vulkan_provider), session_(session), wait_(this) { +VulkanSurface::VulkanSurface( + vulkan::VulkanProvider& vulkan_provider, + fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator, + sk_sp context, + scenic::Session* session, + const SkISize& size, + uint32_t buffer_id) + : vulkan_provider_(vulkan_provider), + session_(session), + buffer_id_(buffer_id), + wait_(this) { FML_DCHECK(session_); - zx::vmo exported_vmo; - if (!AllocateDeviceMemory(std::move(context), size, exported_vmo)) { + if (!AllocateDeviceMemory(sysmem_allocator, std::move(context), size)) { FML_DLOG(INFO) << "Could not allocate device memory."; return; } - uint64_t vmo_size; - zx_status_t status = exported_vmo.get_size(&vmo_size); - FML_DCHECK(status == ZX_OK); - if (!CreateFences()) { FML_DLOG(INFO) << "Could not create signal fences."; return; } - scenic_memory_ = std::make_unique( - session, std::move(exported_vmo), vmo_size, - fuchsia::images::MemoryType::VK_DEVICE_MEMORY); - if (!PushSessionImageSetupOps(session)) { - FML_DLOG(INFO) << "Could not push session image setup ops."; - return; - } + PushSessionImageSetupOps(session); std::fill(size_history_.begin(), size_history_.end(), SkISize::MakeEmpty()); @@ -226,57 +225,100 @@ bool VulkanSurface::CreateFences() { return true; } -bool VulkanSurface::AllocateDeviceMemory(sk_sp context, - const SkISize& size, - zx::vmo& exported_vmo) { +bool VulkanSurface::AllocateDeviceMemory( + fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator, + sk_sp context, + const SkISize& size) { if (size.isEmpty()) { return false; } - VulkanImage vulkan_image; - if (!CreateVulkanImage(vulkan_provider_, size, &vulkan_image)) { - FML_DLOG(ERROR) << "Failed to create VkImage"; + fuchsia::sysmem::BufferCollectionTokenSyncPtr local_token; + zx_status_t status = + sysmem_allocator->AllocateSharedCollection(local_token.NewRequest()); + LOG_AND_RETURN(status != ZX_OK, "Failed to allocate collection"); + fuchsia::sysmem::BufferCollectionTokenSyncPtr scenic_token; + status = local_token->Duplicate(std::numeric_limits::max(), + scenic_token.NewRequest()); + LOG_AND_RETURN(status != ZX_OK, "Failed to duplicate token"); + status = local_token->Sync(); + LOG_AND_RETURN(status != ZX_OK, "Failed to sync token"); + fuchsia::sysmem::BufferCollectionTokenSyncPtr vulkan_token; + status = local_token->Duplicate(std::numeric_limits::max(), + vulkan_token.NewRequest()); + LOG_AND_RETURN(status != ZX_OK, "Failed to duplicate token"); + status = local_token->Sync(); + LOG_AND_RETURN(status != ZX_OK, "Failed to sync token"); + + session_->RegisterBufferCollection(buffer_id_, std::move(scenic_token)); + + fuchsia::sysmem::BufferCollectionSyncPtr buffer_collection; + status = sysmem_allocator->BindSharedCollection( + std::move(local_token), buffer_collection.NewRequest()); + LOG_AND_RETURN(status != ZX_OK, "Failed to bind collection"); + + fuchsia::sysmem::BufferCollectionConstraints constraints; + constraints.min_buffer_count = 1; + constraints.usage.vulkan = kSysmemImageUsage; + + constraints.image_format_constraints_count = 1; + fuchsia::sysmem::ImageFormatConstraints& image_constraints = + constraints.image_format_constraints[0]; + image_constraints = fuchsia::sysmem::ImageFormatConstraints(); + image_constraints.min_coded_width = size.width(); + image_constraints.min_coded_height = size.height(); + image_constraints.max_coded_width = size.width(); + image_constraints.max_coded_height = size.height(); + image_constraints.min_bytes_per_row = 0; + image_constraints.pixel_format.type = kSysmemPixelFormat; + image_constraints.color_spaces_count = 1; + image_constraints.color_space[0].type = fuchsia::sysmem::ColorSpaceType::SRGB; + + status = buffer_collection->SetConstraints(true, constraints); + LOG_AND_RETURN(status != ZX_OK, "Failed to set constraints"); + + VkBufferCollectionCreateInfoFUCHSIA import_info; + import_info.collectionToken = vulkan_token.Unbind().TakeChannel().release(); + if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().CreateBufferCollectionFUCHSIA( + vulkan_provider_.vk_device(), &import_info, nullptr, &collection_)) != + VK_SUCCESS) { return false; } + VulkanImage vulkan_image; + LOG_AND_RETURN(!CreateVulkanImage(vulkan_provider_, size, &vulkan_image), + "Failed to create VkImage"); + + status = buffer_collection->Close(); + LOG_AND_RETURN(status != ZX_OK, "Failed to close collection"); + vulkan_image_ = std::move(vulkan_image); - const VkMemoryRequirements& memory_reqs = + const VkMemoryRequirements& memory_requirements = vulkan_image_.vk_memory_requirements; - const VkImageCreateInfo& image_create_info = - vulkan_image_.vk_image_create_info; - - uint32_t memory_type = 0; - for (; memory_type < 32; memory_type++) { - if ((memory_reqs.memoryTypeBits & (1 << memory_type))) { - break; - } - } + VkImageCreateInfo& image_create_info = vulkan_image_.vk_image_create_info; - VkMemoryDedicatedAllocateInfo dedicated_allocate_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + VkImportMemoryBufferCollectionFUCHSIA import_memory_info = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA, .pNext = nullptr, - .image = vulkan_image_.vk_image, - .buffer = VK_NULL_HANDLE}; - VkExportMemoryAllocateInfoKHR export_allocate_info = { - .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, - .pNext = &dedicated_allocate_info, - .handleTypes = - VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA}; - - const VkMemoryAllocateInfo alloc_info = { + .collection = collection_, + .index = 0, + }; + auto bits = memory_requirements.memoryTypeBits; + FML_DCHECK(bits != 0); + VkMemoryAllocateInfo allocation_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = &export_allocate_info, - .allocationSize = memory_reqs.size, - .memoryTypeIndex = memory_type, + .pNext = &import_memory_info, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = static_cast(__builtin_ctz(bits)), }; { TRACE_EVENT1("flutter", "vkAllocateMemory", "allocationSize", - alloc_info.allocationSize); + allocation_info.allocationSize); VkDeviceMemory vk_memory = VK_NULL_HANDLE; if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().AllocateMemory( - vulkan_provider_.vk_device(), &alloc_info, NULL, &vk_memory)) != - VK_SUCCESS) { + vulkan_provider_.vk_device(), &allocation_info, NULL, + &vk_memory)) != VK_SUCCESS) { return false; } @@ -286,7 +328,7 @@ bool VulkanSurface::AllocateDeviceMemory(sk_sp context, memory, NULL); }}; - vk_memory_info_ = alloc_info; + vk_memory_info_ = allocation_info; } // Bind image memory. @@ -296,31 +338,8 @@ bool VulkanSurface::AllocateDeviceMemory(sk_sp context, return false; } - { - // Acquire the VMO for the device memory. - uint32_t vmo_handle = 0; - - VkMemoryGetZirconHandleInfoFUCHSIA get_handle_info = { - VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA, nullptr, - vk_memory_, VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA}; - if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().GetMemoryZirconHandleFUCHSIA( - vulkan_provider_.vk_device(), &get_handle_info, &vmo_handle)) != - VK_SUCCESS) { - return false; - } - - exported_vmo.reset(static_cast(vmo_handle)); - } - - // Assert that the VMO size was sufficient. - size_t vmo_size = 0; - if (exported_vmo.get_size(&vmo_size) != ZX_OK || - vmo_size < memory_reqs.size) { - return false; - } - return SetupSkiaSurface(std::move(context), size, kSkiaColorType, - image_create_info, memory_reqs); + image_create_info, memory_requirements); } bool VulkanSurface::SetupSkiaSurface(sk_sp context, @@ -370,89 +389,21 @@ bool VulkanSurface::SetupSkiaSurface(sk_sp context, return true; } -bool VulkanSurface::PushSessionImageSetupOps(scenic::Session* session) { - FML_DCHECK(scenic_memory_ != nullptr); - - if (sk_surface_ == nullptr) { - return false; - } - - fuchsia::images::ImageInfo image_info; - image_info.width = sk_surface_->width(); - image_info.height = sk_surface_->height(); - image_info.stride = 4 * sk_surface_->width(); - image_info.pixel_format = kPixelFormat; - image_info.color_space = fuchsia::images::ColorSpace::SRGB; - switch (vulkan_image_.vk_image_create_info.tiling) { - case VK_IMAGE_TILING_OPTIMAL: - image_info.tiling = fuchsia::images::Tiling::GPU_OPTIMAL; - break; - case VK_IMAGE_TILING_LINEAR: - image_info.tiling = fuchsia::images::Tiling::LINEAR; - break; - default: - FML_DLOG(ERROR) << "Bad image tiling: " - << vulkan_image_.vk_image_create_info.tiling; - return false; - } - - session_image_ = std::make_unique( - *scenic_memory_, 0 /* memory offset */, std::move(image_info)); - - return session_image_ != nullptr; +void VulkanSurface::PushSessionImageSetupOps(scenic::Session* session) { + if (image_id_ == 0) + image_id_ = session->AllocResourceId(); + session->Enqueue(scenic::NewCreateImage2Cmd( + image_id_, sk_surface_->width(), sk_surface_->height(), buffer_id_, 0)); } -scenic::Image* VulkanSurface::GetImage() { - if (!valid_) { - return 0; - } - return session_image_.get(); +uint32_t VulkanSurface::GetImageId() { + return image_id_; } sk_sp VulkanSurface::GetSkiaSurface() const { return valid_ ? sk_surface_ : nullptr; } -bool VulkanSurface::BindToImage(sk_sp context, - VulkanImage vulkan_image) { - FML_DCHECK(vulkan_image.vk_memory_requirements.size <= - vk_memory_info_.allocationSize); - - vulkan_image_ = std::move(vulkan_image); - - // Bind image memory. - if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().BindImageMemory( - vulkan_provider_.vk_device(), vulkan_image_.vk_image, vk_memory_, - 0)) != VK_SUCCESS) { - valid_ = false; - return false; - } - - const auto& extent = vulkan_image.vk_image_create_info.extent; - auto size = SkISize::Make(extent.width, extent.height); - - if (!SetupSkiaSurface(std::move(context), size, kSkiaColorType, - vulkan_image.vk_image_create_info, - vulkan_image.vk_memory_requirements)) { - FML_DLOG(ERROR) << "Failed to setup skia surface"; - valid_ = false; - return false; - } - - if (sk_surface_ == nullptr) { - valid_ = false; - return false; - } - - if (!PushSessionImageSetupOps(session_)) { - FML_DLOG(ERROR) << "Could not push session image setup ops."; - valid_ = false; - return false; - } - - return true; -} - size_t VulkanSurface::AdvanceAndGetAge() { size_history_[size_history_index_] = GetSize(); size_history_index_ = (size_history_index_ + 1) % kSizeHistorySize; diff --git a/shell/platform/fuchsia/flutter/vulkan_surface.h b/shell/platform/fuchsia/flutter/vulkan_surface.h index bff2713a011c9..45ad52a45f5b2 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface.h +++ b/shell/platform/fuchsia/flutter/vulkan_surface.h @@ -37,7 +37,7 @@ class SurfaceProducerSurface { virtual void SignalWritesFinished( const std::function& on_writes_committed) = 0; - virtual scenic::Image* GetImage() = 0; + virtual uint32_t GetImageId() = 0; virtual sk_sp GetSkiaSurface() const = 0; }; @@ -59,7 +59,7 @@ struct VulkanImage { VulkanImage(VulkanImage&&) = default; VulkanImage& operator=(VulkanImage&&) = default; - VkExternalMemoryImageCreateInfo vk_external_image_create_info; + VkBufferCollectionImageCreateInfoFUCHSIA vk_collection_image_create_info; VkImageCreateInfo vk_image_create_info; VkMemoryRequirements vk_memory_requirements; vulkan::VulkanHandle vk_image; @@ -67,19 +67,14 @@ struct VulkanImage { FML_DISALLOW_COPY_AND_ASSIGN(VulkanImage); }; -// Create a new |VulkanImage| of size |size|, stored in -// |out_vulkan_image|. Returns whether creation of the |VkImage| was -// successful. -bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider, - const SkISize& size, - VulkanImage* out_vulkan_image); - class VulkanSurface final : public SurfaceProducerSurface { public: VulkanSurface(vulkan::VulkanProvider& vulkan_provider, + fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator, sk_sp context, scenic::Session* session, - const SkISize& size); + const SkISize& size, + uint32_t buffer_id); ~VulkanSurface() override; @@ -101,7 +96,7 @@ class VulkanSurface final : public SurfaceProducerSurface { const std::function& on_writes_committed) override; // |SurfaceProducerSurface| - scenic::Image* GetImage() override; + uint32_t GetImageId() override; // |SurfaceProducerSurface| sk_sp GetSkiaSurface() const override; @@ -141,13 +136,6 @@ class VulkanSurface final : public SurfaceProducerSurface { size_history_.begin()); } - // Bind |vulkan_image| to |vk_memory_| and create a new skia surface, - // replacing the previous |vk_image_|. |vulkan_image| MUST require less - // than or equal the amount of memory contained in |vk_memory_|. Returns - // whether the swap was successful. The |VulkanSurface| will become invalid - // if the swap was not successful. - bool BindToImage(sk_sp context, VulkanImage vulkan_image); - private: static constexpr int kSizeHistorySize = 4; @@ -156,9 +144,13 @@ class VulkanSurface final : public SurfaceProducerSurface { zx_status_t status, const zx_packet_signal_t* signal); - bool AllocateDeviceMemory(sk_sp context, - const SkISize& size, - zx::vmo& exported_vmo); + bool AllocateDeviceMemory(fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator, + sk_sp context, + const SkISize& size); + + bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider, + const SkISize& size, + VulkanImage* out_vulkan_image); bool SetupSkiaSurface(sk_sp context, const SkISize& size, @@ -168,7 +160,7 @@ class VulkanSurface final : public SurfaceProducerSurface { bool CreateFences(); - bool PushSessionImageSetupOps(scenic::Session* session); + void PushSessionImageSetupOps(scenic::Session* session); void Reset(); @@ -182,9 +174,9 @@ class VulkanSurface final : public SurfaceProducerSurface { VkMemoryAllocateInfo vk_memory_info_; vulkan::VulkanHandle command_buffer_fence_; sk_sp sk_surface_; - // TODO: Don't heap allocate this once SCN-268 is resolved. - std::unique_ptr scenic_memory_; - std::unique_ptr session_image_; + const uint32_t buffer_id_; + uint32_t image_id_ = 0; + VkBufferCollectionFUCHSIA collection_; zx::event acquire_event_; vulkan::VulkanHandle acquire_semaphore_; std::unique_ptr command_buffer_; diff --git a/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc b/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc index 1b85a957898bd..bd3ffb4810da6 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc +++ b/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc @@ -4,6 +4,8 @@ #include "vulkan_surface_pool.h" +#include + #include #include @@ -12,21 +14,17 @@ namespace flutter_runner { -namespace { - -std::string ToString(const SkISize& size) { - return "{width: " + std::to_string(size.width()) + - ", height: " + std::to_string(size.height()) + "}"; -} - -} // namespace - VulkanSurfacePool::VulkanSurfacePool(vulkan::VulkanProvider& vulkan_provider, sk_sp context, scenic::Session* scenic_session) : vulkan_provider_(vulkan_provider), context_(std::move(context)), - scenic_session_(scenic_session) {} + scenic_session_(scenic_session) { + zx_status_t status = fdio_service_connect( + "/svc/fuchsia.sysmem.Allocator", + sysmem_allocator_.NewRequest().TakeChannel().release()); + FML_DCHECK(status != ZX_OK); +} VulkanSurfacePool::~VulkanSurfacePool() {} @@ -66,49 +64,7 @@ std::unique_ptr VulkanSurfacePool::GetCachedOrCreateSurface( } } - // Then, look for a surface that has enough |VkDeviceMemory| to hold a - // |VkImage| of size |size|, but is currently holding a |VkImage| of a - // different size. - VulkanImage vulkan_image; - if (!CreateVulkanImage(vulkan_provider_, size, &vulkan_image)) { - FML_DLOG(ERROR) << "Failed to create a VkImage of size: " << ToString(size); - return nullptr; - } - - auto best_it = available_surfaces_.end(); - for (auto it = available_surfaces_.begin(); it != available_surfaces_.end(); - ++it) { - const auto& surface = *it; - if (!surface->IsValid() || surface->GetAllocationSize() < - vulkan_image.vk_memory_requirements.size) { - continue; - } - if (best_it == available_surfaces_.end() || - surface->GetAllocationSize() < (*best_it)->GetAllocationSize()) { - best_it = it; - } - } - - // If no such surface exists, then create a new one. - if (best_it == available_surfaces_.end()) { - TRACE_EVENT_INSTANT0("flutter", "No available surfaces"); - return CreateSurface(size); - } - - auto acquired_surface = std::move(*best_it); - available_surfaces_.erase(best_it); - bool swap_succeeded = - acquired_surface->BindToImage(context_, std::move(vulkan_image)); - if (!swap_succeeded) { - FML_DLOG(ERROR) << "Failed to swap VulkanSurface to new VkImage of size: " - << ToString(size); - TRACE_EVENT_INSTANT0("flutter", "failed to swap, making new"); - return CreateSurface(size); - } - TRACE_EVENT_INSTANT0("flutter", "Using differently sized image"); - FML_DCHECK(acquired_surface->IsValid()); - trace_surfaces_reused_++; - return acquired_surface; + return CreateSurface(size); } void VulkanSurfacePool::SubmitSurface( @@ -140,8 +96,9 @@ std::unique_ptr VulkanSurfacePool::CreateSurface( const SkISize& size) { TRACE_EVENT2("flutter", "VulkanSurfacePool::CreateSurface", "width", size.width(), "height", size.height()); - auto surface = std::make_unique(vulkan_provider_, context_, - scenic_session_, size); + auto surface = std::make_unique( + vulkan_provider_, sysmem_allocator_, context_, scenic_session_, size, + buffer_id_++); if (!surface->IsValid()) { return nullptr; } diff --git a/shell/platform/fuchsia/flutter/vulkan_surface_pool.h b/shell/platform/fuchsia/flutter/vulkan_surface_pool.h index f98d45216f4a6..00686f54183ac 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface_pool.h +++ b/shell/platform/fuchsia/flutter/vulkan_surface_pool.h @@ -41,9 +41,11 @@ class VulkanSurfacePool final { vulkan::VulkanProvider& vulkan_provider_; sk_sp context_; scenic::Session* scenic_session_; + fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator_; std::vector> available_surfaces_; std::unordered_map> pending_surfaces_; + uint32_t buffer_id_ = 1; size_t trace_surfaces_created_ = 0; size_t trace_surfaces_reused_ = 0; diff --git a/vulkan/vulkan_device.cc b/vulkan/vulkan_device.cc index e2d45bb5e1f2d..fbc9aaa13e862 100644 --- a/vulkan/vulkan_device.cc +++ b/vulkan/vulkan_device.cc @@ -69,6 +69,7 @@ VulkanDevice::VulkanDevice(VulkanProcTable& p_vk, VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, + VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME, #endif }; diff --git a/vulkan/vulkan_proc_table.cc b/vulkan/vulkan_proc_table.cc index 9ed7c40b5c9ae..6d8d93686a883 100644 --- a/vulkan/vulkan_proc_table.cc +++ b/vulkan/vulkan_proc_table.cc @@ -137,8 +137,10 @@ bool VulkanProcTable::SetupDeviceProcAddresses( ACQUIRE_PROC(QueuePresentKHR, handle); #endif // OS_ANDROID #if OS_FUCHSIA + ACQUIRE_PROC(CreateBufferCollectionFUCHSIA, handle); ACQUIRE_PROC(GetMemoryZirconHandleFUCHSIA, handle); ACQUIRE_PROC(ImportSemaphoreZirconHandleFUCHSIA, handle); + ACQUIRE_PROC(SetBufferCollectionConstraintsFUCHSIA, handle); #endif // OS_FUCHSIA device_ = {handle, nullptr}; return true; diff --git a/vulkan/vulkan_proc_table.h b/vulkan/vulkan_proc_table.h index b9d000887ca19..b6f90b758ecaa 100644 --- a/vulkan/vulkan_proc_table.h +++ b/vulkan/vulkan_proc_table.h @@ -115,8 +115,10 @@ class VulkanProcTable : public fml::RefCountedThreadSafe { DEFINE_PROC(CreateAndroidSurfaceKHR); #endif // OS_ANDROID #if OS_FUCHSIA + DEFINE_PROC(CreateBufferCollectionFUCHSIA); DEFINE_PROC(GetMemoryZirconHandleFUCHSIA); DEFINE_PROC(ImportSemaphoreZirconHandleFUCHSIA); + DEFINE_PROC(SetBufferCollectionConstraintsFUCHSIA); #endif // OS_FUCHSIA #undef DEFINE_PROC