Flutter Impeller
khr_swapchain_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "flutter/fml/build_config.h"
8 #include "flutter/fml/trace_event.h"
11 
12 namespace impeller {
13 
14 KHRSwapchainVK::KHRSwapchainVK(const std::shared_ptr<Context>& context,
15  vk::UniqueSurfaceKHR surface,
16  const ISize& size,
17  bool enable_msaa)
18  : size_(size), enable_msaa_(enable_msaa) {
19  auto impl = KHRSwapchainImplVK::Create(context, //
20  std::move(surface), //
21  size_, //
22  enable_msaa_ //
23  );
24  if (!impl || !impl->IsValid()) {
25  VALIDATION_LOG << "Failed to create SwapchainVK implementation.";
26  return;
27  }
28  impl_ = std::move(impl);
29 }
30 
31 KHRSwapchainVK::~KHRSwapchainVK() = default;
32 
33 bool KHRSwapchainVK::IsValid() const {
34  return impl_ ? impl_->IsValid() : false;
35 }
36 
37 void KHRSwapchainVK::UpdateSurfaceSize(const ISize& size) {
38  // Update the size of the swapchain. On the next acquired drawable,
39  // the sizes may no longer match, forcing the swapchain to be recreated.
40  size_ = size;
41 }
42 
43 void KHRSwapchainVK::AddFinalCommandBuffer(
44  std::shared_ptr<CommandBuffer> cmd_buffer) const {
45  impl_->AddFinalCommandBuffer(std::move(cmd_buffer));
46 }
47 
48 std::unique_ptr<Surface> KHRSwapchainVK::AcquireNextDrawable() {
49  return AcquireNextDrawable(0u);
50 }
51 
52 std::unique_ptr<Surface> KHRSwapchainVK::AcquireNextDrawable(
53  size_t resize_retry_count) {
54  if (!IsValid()) {
55  return nullptr;
56  }
57 
58  TRACE_EVENT0("impeller", __FUNCTION__);
59 
60  auto result = impl_->AcquireNextDrawable();
61  if (!result.out_of_date && size_ == impl_->GetSize()) {
62  return std::move(result.surface);
63  }
64 
65 // When the swapchain says its out-of-date, we attempt to read the underlying
66 // surface size and re-create the swapchain at that size automatically (subject
67 // to a specific number of retries). However, on some platforms, the surface
68 // size reported by the Vulkan API may be stale for several frames. Those
69 // platforms must explicitly set the swapchain size using out-of-band (to
70 // Vulkan) APIs.
71 //
72 // TODO(163070): Expose the API to set surface size in impeller.h
73 #if !FML_OS_ANDROID
74  constexpr const size_t kMaxResizeAttempts = 3u;
75  if (resize_retry_count == kMaxResizeAttempts) {
76  VALIDATION_LOG << "Attempted to resize the swapchain" << kMaxResizeAttempts
77  << " time unsuccessfully. This platform likely doesn't "
78  "support returning the current swapchain extents and "
79  "must recreate the swapchain using the actual size.";
80  return nullptr;
81  }
82 
83  size_ = impl_->GetCurrentUnderlyingSurfaceSize().value_or(size_);
84 #endif // !FML_OS_ANDROID
85 
86  TRACE_EVENT0("impeller", "RecreateSwapchain");
87 
88  // This swapchain implementation indicates that it is out of date. Tear it
89  // down and make a new one.
90  auto context = impl_->GetContext();
91  auto [surface, old_swapchain] = impl_->DestroySwapchain();
92 
93  auto new_impl = KHRSwapchainImplVK::Create(context, //
94  std::move(surface), //
95  size_, //
96  enable_msaa_, //
97  *old_swapchain //
98  );
99  if (!new_impl || !new_impl->IsValid()) {
100  VALIDATION_LOG << "Could not update swapchain.";
101  // The old swapchain is dead because we took its surface. This is
102  // unrecoverable.
103  impl_.reset();
104  return nullptr;
105  }
106  impl_ = std::move(new_impl);
107 
108  //----------------------------------------------------------------------------
109  /// We managed to recreate the swapchain in the new configuration. Try again.
110  ///
111  return AcquireNextDrawable(resize_retry_count + 1);
112 }
113 
114 vk::Format KHRSwapchainVK::GetSurfaceFormat() const {
115  return IsValid() ? impl_->GetSurfaceFormat() : vk::Format::eUndefined;
116 }
117 
118 } // namespace impeller
ScopedObject< Object > Create(CtorArgs &&... args)
Definition: object.h:161
ISize64 ISize
Definition: size.h:162
#define VALIDATION_LOG
Definition: validation.h:91