7#include "flutter/vulkan/procs/vulkan_proc_table.h"
49 std::unique_ptr<VulkanSwapchain> old_swapchain,
56 current_backbuffer_index_(0),
57 current_image_index_(0),
59 if (!device_.IsValid() || !
surface.IsValid() || skia_context ==
nullptr) {
60 FML_DLOG(INFO) <<
"Device or surface is invalid.";
64 if (!device_.GetSurfaceCapabilities(
surface, &capabilities_)) {
65 FML_DLOG(INFO) <<
"Could not find surface capabilities.";
70 std::vector<VkFormat> desired_formats(format_infos.size());
71 for (
size_t i = 0;
i < format_infos.size(); ++
i) {
73 format_infos[
i].color_type_)) {
74 desired_formats[
i] = format_infos[
i].format_;
81 device_.ChooseSurfaceFormat(
surface, desired_formats, &surface_format_);
82 if (format_index < 0) {
83 FML_DLOG(INFO) <<
"Could not choose surface format.";
88 if (!device_.ChoosePresentMode(
surface, &present_mode)) {
89 FML_DLOG(INFO) <<
"Could not choose present mode.";
97 device_.GetPhysicalDeviceHandle(),
101 FML_DLOG(INFO) <<
"Could not get physical device surface support.";
106 FML_DLOG(INFO) <<
"Surface was not supported by the physical device.";
114 if (old_swapchain !=
nullptr && old_swapchain->IsValid()) {
115 old_swapchain_handle = old_swapchain->swapchain_;
120 VkSurfaceKHR surface_handle =
surface.Handle();
130 .surface = surface_handle,
131 .minImageCount = capabilities_.minImageCount,
132 .imageFormat = surface_format_.format,
133 .imageColorSpace = surface_format_.colorSpace,
134 .imageExtent = capabilities_.currentExtent,
135 .imageArrayLayers = 1,
136 .imageUsage = usage_flags,
138 .queueFamilyIndexCount = 0,
139 .pQueueFamilyIndices =
nullptr,
142 .presentMode = present_mode,
144 .oldSwapchain = old_swapchain_handle,
152 FML_DLOG(INFO) <<
"Could not create the swapchain.";
159 vk.DestroySwapchainKHR(device_.GetHandle(),
swapchain,
nullptr);
162 if (!CreateSwapchainImages(
163 skia_context, format_infos[format_index].
color_type_,
164 format_infos[format_index].
color_space_, usage_flags)) {
165 FML_DLOG(INFO) <<
"Could not create swapchain images.";
178std::vector<VkImage> VulkanSwapchain::GetImages()
const {
189 std::vector<VkImage>
images;
194 device_.GetHandle(), swapchain_, &
count,
images.data())) !=
203 VkExtent2D extents = capabilities_.currentExtent;
205 if (extents.
width < capabilities_.minImageExtent.width) {
206 extents.
width = capabilities_.minImageExtent.width;
207 }
else if (extents.
width > capabilities_.maxImageExtent.width) {
208 extents.
width = capabilities_.maxImageExtent.width;
211 if (extents.
height < capabilities_.minImageExtent.height) {
212 extents.
height = capabilities_.minImageExtent.height;
213 }
else if (extents.
height > capabilities_.maxImageExtent.height) {
214 extents.
height = capabilities_.maxImageExtent.height;
227 if (gr_context ==
nullptr) {
240 image_info.
fFormat = surface_format_.format;
246 auto backend_render_target =
252 backend_render_target,
255 std::move(color_space),
260bool VulkanSwapchain::CreateSwapchainImages(
265 std::vector<VkImage>
images = GetImages();
275 auto backbuffer = std::make_unique<VulkanBackbuffer>(
276 vk, device_.GetHandle(), device_.GetCommandPool());
278 if (!backbuffer->IsValid()) {
282 backbuffers_.emplace_back(std::move(backbuffer));
285 VulkanHandle<VkImage> image_handle = VulkanHandle<VkImage>{
287 vk.DestroyImage(device_.GetHandle(),
image,
nullptr);
289 auto vulkan_image = std::make_unique<VulkanImage>(std::move(image_handle));
291 if (!vulkan_image->IsValid()) {
295 images_.emplace_back(std::move(vulkan_image));
298 auto surface = CreateSkiaSurface(skia_context,
image, usage_flags,
305 surfaces_.emplace_back(std::move(
surface));
308 FML_DCHECK(backbuffers_.size() == images_.size());
309 FML_DCHECK(images_.size() == surfaces_.size());
314VulkanBackbuffer* VulkanSwapchain::GetNextBackbuffer() {
315 auto available_backbuffers = backbuffers_.size();
317 if (available_backbuffers == 0) {
321 auto next_backbuffer_index =
322 (current_backbuffer_index_ + 1) % backbuffers_.size();
324 auto& backbuffer = backbuffers_[next_backbuffer_index];
326 if (!backbuffer->IsValid()) {
330 current_backbuffer_index_ = next_backbuffer_index;
331 return backbuffer.get();
338 FML_DLOG(INFO) <<
"Swapchain was invalid.";
346 auto backbuffer = GetNextBackbuffer();
348 if (backbuffer ==
nullptr) {
349 FML_DLOG(INFO) <<
"Could not get the next backbuffer.";
357 if (!backbuffer->WaitFences()) {
358 FML_DLOG(INFO) <<
"Failed waiting on fences.";
366 if (!backbuffer->ResetFences()) {
367 FML_DLOG(INFO) <<
"Could not reset fences.";
375 uint32_t next_image_index = 0;
378 vk.AcquireNextImageKHR(device_.GetHandle(),
381 backbuffer->GetUsageSemaphore(),
385 switch (acquire_result) {
393 FML_LOG(INFO) <<
"Unexpected result from AcquireNextImageKHR: "
399 if (next_image_index >= images_.size()) {
400 FML_DLOG(INFO) <<
"Image index returned was out-of-bounds.";
404 auto&
image = images_[next_image_index];
405 if (!
image->IsValid()) {
406 FML_DLOG(INFO) <<
"Image at index was invalid.";
414 if (!backbuffer->GetUsageCommandBuffer().Begin()) {
415 FML_DLOG(INFO) <<
"Could not begin recording to the command buffer.";
428 if (!
image->InsertImageMemoryBarrier(
429 backbuffer->GetUsageCommandBuffer(),
430 current_pipeline_stage_,
431 destination_pipeline_stage,
433 destination_image_layout
435 FML_DLOG(INFO) <<
"Could not insert image memory barrier.";
438 current_pipeline_stage_ = destination_pipeline_stage;
445 if (!backbuffer->GetUsageCommandBuffer().End()) {
446 FML_DLOG(INFO) <<
"Could not end recording to the command buffer.";
454 std::vector<VkSemaphore> wait_semaphores = {backbuffer->GetUsageSemaphore()};
455 std::vector<VkSemaphore> signal_semaphores = {};
456 std::vector<VkCommandBuffer> command_buffers = {
457 backbuffer->GetUsageCommandBuffer().Handle()};
459 if (!device_.QueueSubmit(
460 {destination_pipeline_stage},
464 backbuffer->GetUsageFence()
466 FML_DLOG(INFO) <<
"Could not submit to the device queue.";
477 FML_DLOG(INFO) <<
"Could not access surface at the image index.";
484 FML_DLOG(INFO) <<
"Could not get backend render target.";
488 destination_image_layout);
490 current_image_index_ = next_image_index;
497 FML_DLOG(INFO) <<
"Swapchain was invalid.";
502 const std::unique_ptr<VulkanImage>&
image = images_[current_image_index_];
503 auto backbuffer = backbuffers_[current_backbuffer_index_].
get();
515 if (!backbuffer->GetRenderCommandBuffer().Begin()) {
516 FML_DLOG(INFO) <<
"Could not start recording to the command buffer.";
528 if (!
image->InsertImageMemoryBarrier(
529 backbuffer->GetRenderCommandBuffer(),
530 current_pipeline_stage_,
531 destination_pipeline_stage,
533 destination_image_layout
535 FML_DLOG(INFO) <<
"Could not insert memory barrier.";
538 current_pipeline_stage_ = destination_pipeline_stage;
545 if (!backbuffer->GetRenderCommandBuffer().End()) {
546 FML_DLOG(INFO) <<
"Could not end recording to the command buffer.";
555 std::vector<VkSemaphore> wait_semaphores = {};
556 std::vector<VkSemaphore> queue_signal_semaphores = {
557 backbuffer->GetRenderSemaphore()};
558 std::vector<VkCommandBuffer> command_buffers = {
559 backbuffer->GetRenderCommandBuffer().Handle()};
561 if (!device_.QueueSubmit(
564 queue_signal_semaphores,
566 backbuffer->GetRenderFence()
568 FML_DLOG(INFO) <<
"Could not submit to the device queue.";
577 uint32_t present_image_index =
static_cast<uint32_t
>(current_image_index_);
581 .waitSemaphoreCount =
582 static_cast<uint32_t
>(queue_signal_semaphores.size()),
583 .pWaitSemaphores = queue_signal_semaphores.data(),
586 .pImageIndices = &present_image_index,
592 FML_DLOG(INFO) <<
"Could not submit the present operation.";
@ kTopLeft_GrSurfaceOrigin
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kUnknown_SkColorType
uninitialized
@ kUnknown_SkPixelGeometry
SK_API bool colorTypeSupportedAsSurface(SkColorType colorType) const
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > MakeSRGBLinear()
@ kFlushRead
back-end object is readable
AcquireResult AcquireSurface()
std::pair< AcquireStatus, sk_sp< SkSurface > > AcquireResult
@ Success
A valid SkSurface was acquired successfully from the swapchain.
VulkanSwapchain(const VulkanProcTable &vk, const VulkanDevice &device, const VulkanSurface &surface, GrDirectContext *skia_context, std::unique_ptr< VulkanSwapchain > old_swapchain, uint32_t queue_family_index)
uint32_t queue_family_index
const uint8_t uint32_t uint32_t GError ** error
#define FML_ALLOW_UNUSED_LOCAL(x)
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_DCHECK(condition)
static float max(float r, float g, float b)
std::array< MockImage, 3 > images
SK_API void SetVkImageLayout(GrBackendRenderTarget *, VkImageLayout)
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)
SK_API GrBackendRenderTarget GetBackendRenderTarget(SkSurface *, BackendHandleAccess)
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
SK_API void FlushAndSubmit(sk_sp< SkSurface >)
static std::vector< FormatInfo > DesiredFormatInfos()
VkImageLayout fImageLayout
VkImageUsageFlags fImageUsageFlags
VkImageTiling fImageTiling
static constexpr SkISize Make(int32_t w, int32_t h)
@ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
@ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_SHARING_MODE_EXCLUSIVE
VkFlags VkImageUsageFlags
@ VK_IMAGE_TILING_OPTIMAL
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
@ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
@ VK_ERROR_OUT_OF_DATE_KHR
@ VK_ERROR_SURFACE_LOST_KHR
@ VK_ACCESS_MEMORY_READ_BIT
@ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
@ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
@ VK_PRESENT_MODE_FIFO_KHR
@ VK_FORMAT_R8G8B8A8_SRGB
@ VK_FORMAT_B8G8R8A8_UNORM
@ VK_FORMAT_B8G8R8A8_SRGB
@ VK_FORMAT_R8G8B8A8_UNORM
@ VK_FORMAT_R16G16B16A16_SFLOAT
@ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
@ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
@ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
@ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
@ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR
#define VK_CALL_LOG_ERROR(expression)
sk_sp< SkColorSpace > color_space_