Flutter Impeller
impeller::KHRSwapchainImplVK Class Referencefinal

An instance of a swapchain that does NOT adapt to going out of date with the underlying surface. Errors will be indicated when the next drawable is acquired from this implementation of the swapchain. If the error is due the swapchain going out of date, the caller must recreate another instance by optionally stealing this implementations guts. More...

#include <khr_swapchain_impl_vk.h>

Inheritance diagram for impeller::KHRSwapchainImplVK:

Classes

struct  AcquireResult
 

Public Member Functions

 ~KHRSwapchainImplVK ()
 
bool IsValid () const
 
AcquireResult AcquireNextDrawable ()
 
vk::Format GetSurfaceFormat () const
 
std::shared_ptr< ContextGetContext () const
 
std::pair< vk::UniqueSurfaceKHR, vk::UniqueSwapchainKHR > DestroySwapchain ()
 
const ISizeGetSize () const
 
void AddFinalCommandBuffer (std::shared_ptr< CommandBuffer > cmd_buffer)
 
std::optional< ISizeGetCurrentUnderlyingSurfaceSize () const
 

Static Public Member Functions

static std::shared_ptr< KHRSwapchainImplVKCreate (const std::shared_ptr< Context > &context, vk::UniqueSurfaceKHR surface, const ISize &size, bool enable_msaa=true, vk::SwapchainKHR old_swapchain=VK_NULL_HANDLE)
 

Detailed Description

An instance of a swapchain that does NOT adapt to going out of date with the underlying surface. Errors will be indicated when the next drawable is acquired from this implementation of the swapchain. If the error is due the swapchain going out of date, the caller must recreate another instance by optionally stealing this implementations guts.

Definition at line 30 of file khr_swapchain_impl_vk.h.

Constructor & Destructor Documentation

◆ ~KHRSwapchainImplVK()

impeller::KHRSwapchainImplVK::~KHRSwapchainImplVK ( )

Definition at line 282 of file khr_swapchain_impl_vk.cc.

282  {
284 }
std::pair< vk::UniqueSurfaceKHR, vk::UniqueSwapchainKHR > DestroySwapchain()

References DestroySwapchain().

Member Function Documentation

◆ AcquireNextDrawable()

KHRSwapchainImplVK::AcquireResult impeller::KHRSwapchainImplVK::AcquireNextDrawable ( )

Wait on the host for the synchronizer fence.

Get the next image index.

Record all subsequent cmd buffers as part of the current frame.

Definition at line 351 of file khr_swapchain_impl_vk.cc.

351  {
352  auto context_strong = context_.lock();
353  if (!context_strong) {
354  return KHRSwapchainImplVK::AcquireResult{};
355  }
356 
357  const auto& context = ContextVK::Cast(*context_strong);
358 
359  current_frame_ = (current_frame_ + 1u) % synchronizers_.size();
360 
361  const auto& sync = synchronizers_[current_frame_];
362 
363  //----------------------------------------------------------------------------
364  /// Wait on the host for the synchronizer fence.
365  ///
366  if (!sync->WaitForFence(context.GetDevice())) {
367  VALIDATION_LOG << "Could not wait for fence.";
368  return KHRSwapchainImplVK::AcquireResult{};
369  }
370 
371  //----------------------------------------------------------------------------
372  /// Get the next image index.
373  ///
374  /// @bug Non-infinite timeouts are not supported on some older Android
375  /// devices and the only indication we get is log spam which serves to
376  /// add confusion. Just use an infinite timeout instead of being
377  /// defensive.
378  auto [acq_result, index] = context.GetDevice().acquireNextImageKHR(
379  *swapchain_, // swapchain
380  std::numeric_limits<uint64_t>::max(), // timeout (ns)
381  *sync->render_ready, // signal semaphore
382  nullptr // fence
383  );
384 
385  switch (acq_result) {
386  case vk::Result::eSuccess:
387  // Keep going.
388  break;
389  case vk::Result::eSuboptimalKHR:
390  case vk::Result::eErrorOutOfDateKHR:
391  // A recoverable error. Just say we are out of date.
392  return AcquireResult{true /* out of date */};
393  break;
394  case vk::Result::eErrorSurfaceLostKHR:
395  // This error code is returned by Android for some situations that are
396  // recoverable but do not require recreating the swapchain.
397  return AcquireResult{false /* out of date */};
398  default:
399  // An unrecoverable error.
400  VALIDATION_LOG << "Could not acquire next swapchain image: "
401  << vk::to_string(acq_result);
402  return AcquireResult{false /* out of date */};
403  }
404 
405  if (index >= images_.size()) {
406  VALIDATION_LOG << "Swapchain returned an invalid image index.";
407  return KHRSwapchainImplVK::AcquireResult{};
408  }
409 
410  /// Record all subsequent cmd buffers as part of the current frame.
411  context.GetGPUTracer()->MarkFrameStart();
412 
413  auto image = images_[index % images_.size()];
414  uint32_t image_index = index;
415  return AcquireResult{SurfaceVK::WrapSwapchainImage(
416  transients_, // transients
417  image, // swapchain image
418  [weak_swapchain = weak_from_this(), image, image_index]() -> bool {
419  auto swapchain = weak_swapchain.lock();
420  if (!swapchain) {
421  return false;
422  }
423  return swapchain->Present(image, image_index);
424  } // swap callback
425  )};
426 }
static ContextVK & Cast(Context &base)
Definition: backend_cast.h:13
static std::unique_ptr< SurfaceVK > WrapSwapchainImage(const std::shared_ptr< SwapchainTransientsVK > &transients, const std::shared_ptr< TextureSourceVK > &swapchain_image, SwapCallback swap_callback)
Wrap the swapchain image in a Surface, which provides the additional configuration required for usage...
Definition: surface_vk.cc:13
#define VALIDATION_LOG
Definition: validation.h:91

References impeller::BackendCast< ContextVK, Context >::Cast(), VALIDATION_LOG, and impeller::SurfaceVK::WrapSwapchainImage().

◆ AddFinalCommandBuffer()

void impeller::KHRSwapchainImplVK::AddFinalCommandBuffer ( std::shared_ptr< CommandBuffer cmd_buffer)

Definition at line 428 of file khr_swapchain_impl_vk.cc.

429  {
430  const auto& sync = synchronizers_[current_frame_];
431  sync->final_cmd_buffer = std::move(cmd_buffer);
432  sync->has_onscreen = true;
433 }

◆ Create()

std::shared_ptr< KHRSwapchainImplVK > impeller::KHRSwapchainImplVK::Create ( const std::shared_ptr< Context > &  context,
vk::UniqueSurfaceKHR  surface,
const ISize size,
bool  enable_msaa = true,
vk::SwapchainKHR  old_swapchain = VK_NULL_HANDLE 
)
static

Definition at line 115 of file khr_swapchain_impl_vk.cc.

120  {
121  return std::shared_ptr<KHRSwapchainImplVK>(new KHRSwapchainImplVK(
122  context, std::move(surface), size, enable_msaa, old_swapchain));
123 }

◆ DestroySwapchain()

std::pair< vk::UniqueSurfaceKHR, vk::UniqueSwapchainKHR > impeller::KHRSwapchainImplVK::DestroySwapchain ( )

Definition at line 334 of file khr_swapchain_impl_vk.cc.

334  {
335  WaitIdle();
336  is_valid_ = false;
337  synchronizers_.clear();
338  images_.clear();
339  context_.reset();
340  return {std::move(surface_), std::move(swapchain_)};
341 }

Referenced by ~KHRSwapchainImplVK().

◆ GetContext()

std::shared_ptr< Context > impeller::KHRSwapchainImplVK::GetContext ( ) const

Definition at line 347 of file khr_swapchain_impl_vk.cc.

347  {
348  return context_.lock();
349 }

◆ GetCurrentUnderlyingSurfaceSize()

std::optional< ISize > impeller::KHRSwapchainImplVK::GetCurrentUnderlyingSurfaceSize ( ) const

Definition at line 290 of file khr_swapchain_impl_vk.cc.

291  {
292  if (!IsValid()) {
293  return std::nullopt;
294  }
295 
296  auto context = context_.lock();
297  if (!context) {
298  return std::nullopt;
299  }
300 
301  auto& vk_context = ContextVK::Cast(*context);
302  const auto [result, surface_caps] =
303  vk_context.GetPhysicalDevice().getSurfaceCapabilitiesKHR(surface_.get());
304  if (result != vk::Result::eSuccess) {
305  return std::nullopt;
306  }
307 
308  // From the spec: `currentExtent` is the current width and height of the
309  // surface, or the special value (0xFFFFFFFF, 0xFFFFFFFF) indicating that the
310  // surface size will be determined by the extent of a swapchain targeting the
311  // surface.
312  constexpr uint32_t kCurrentExtentsPlaceholder = 0xFFFFFFFF;
313  if (surface_caps.currentExtent.width == kCurrentExtentsPlaceholder ||
314  surface_caps.currentExtent.height == kCurrentExtentsPlaceholder) {
315  return std::nullopt;
316  }
317 
318  return ISize::MakeWH(surface_caps.currentExtent.width,
319  surface_caps.currentExtent.height);
320 }
static constexpr TSize MakeWH(Type width, Type height)
Definition: size.h:43

References impeller::BackendCast< ContextVK, Context >::Cast(), IsValid(), and impeller::TSize< T >::MakeWH().

◆ GetSize()

const ISize & impeller::KHRSwapchainImplVK::GetSize ( ) const

Definition at line 286 of file khr_swapchain_impl_vk.cc.

286  {
287  return size_;
288 }

◆ GetSurfaceFormat()

vk::Format impeller::KHRSwapchainImplVK::GetSurfaceFormat ( ) const

Definition at line 343 of file khr_swapchain_impl_vk.cc.

343  {
344  return surface_format_;
345 }

◆ IsValid()

bool impeller::KHRSwapchainImplVK::IsValid ( ) const

Definition at line 322 of file khr_swapchain_impl_vk.cc.

322  {
323  return is_valid_;
324 }

Referenced by GetCurrentUnderlyingSurfaceSize().


The documentation for this class was generated from the following files: