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 278 of file khr_swapchain_impl_vk.cc.

278  {
280 }
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 347 of file khr_swapchain_impl_vk.cc.

347  {
348  auto context_strong = context_.lock();
349  if (!context_strong) {
350  return KHRSwapchainImplVK::AcquireResult{};
351  }
352 
353  const auto& context = ContextVK::Cast(*context_strong);
354 
355  current_frame_ = (current_frame_ + 1u) % synchronizers_.size();
356 
357  const auto& sync = synchronizers_[current_frame_];
358 
359  //----------------------------------------------------------------------------
360  /// Wait on the host for the synchronizer fence.
361  ///
362  if (!sync->WaitForFence(context.GetDevice())) {
363  VALIDATION_LOG << "Could not wait for fence.";
364  return KHRSwapchainImplVK::AcquireResult{};
365  }
366 
367  //----------------------------------------------------------------------------
368  /// Get the next image index.
369  ///
370  /// @bug Non-infinite timeouts are not supported on some older Android
371  /// devices and the only indication we get is log spam which serves to
372  /// add confusion. Just use an infinite timeout instead of being
373  /// defensive.
374  auto [acq_result, index] = context.GetDevice().acquireNextImageKHR(
375  *swapchain_, // swapchain
376  std::numeric_limits<uint64_t>::max(), // timeout (ns)
377  *sync->render_ready, // signal semaphore
378  nullptr // fence
379  );
380 
381  switch (acq_result) {
382  case vk::Result::eSuccess:
383  // Keep going.
384  break;
385  case vk::Result::eSuboptimalKHR:
386  case vk::Result::eErrorOutOfDateKHR:
387  // A recoverable error. Just say we are out of date.
388  return AcquireResult{true /* out of date */};
389  break;
390  default:
391  // An unrecoverable error.
392  VALIDATION_LOG << "Could not acquire next swapchain image: "
393  << vk::to_string(acq_result);
394  return AcquireResult{false /* out of date */};
395  }
396 
397  if (index >= images_.size()) {
398  VALIDATION_LOG << "Swapchain returned an invalid image index.";
399  return KHRSwapchainImplVK::AcquireResult{};
400  }
401 
402  /// Record all subsequent cmd buffers as part of the current frame.
403  context.GetGPUTracer()->MarkFrameStart();
404 
405  auto image = images_[index % images_.size()];
406  uint32_t image_index = index;
407  return AcquireResult{SurfaceVK::WrapSwapchainImage(
408  transients_, // transients
409  image, // swapchain image
410  [weak_swapchain = weak_from_this(), image, image_index]() -> bool {
411  auto swapchain = weak_swapchain.lock();
412  if (!swapchain) {
413  return false;
414  }
415  return swapchain->Present(image, image_index);
416  } // swap callback
417  )};
418 }
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 420 of file khr_swapchain_impl_vk.cc.

421  {
422  const auto& sync = synchronizers_[current_frame_];
423  sync->final_cmd_buffer = std::move(cmd_buffer);
424  sync->has_onscreen = true;
425 }

◆ 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 111 of file khr_swapchain_impl_vk.cc.

116  {
117  return std::shared_ptr<KHRSwapchainImplVK>(new KHRSwapchainImplVK(
118  context, std::move(surface), size, enable_msaa, old_swapchain));
119 }

◆ DestroySwapchain()

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

Definition at line 330 of file khr_swapchain_impl_vk.cc.

330  {
331  WaitIdle();
332  is_valid_ = false;
333  synchronizers_.clear();
334  images_.clear();
335  context_.reset();
336  return {std::move(surface_), std::move(swapchain_)};
337 }

Referenced by ~KHRSwapchainImplVK().

◆ GetContext()

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

Definition at line 343 of file khr_swapchain_impl_vk.cc.

343  {
344  return context_.lock();
345 }

◆ GetCurrentUnderlyingSurfaceSize()

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

Definition at line 286 of file khr_swapchain_impl_vk.cc.

287  {
288  if (!IsValid()) {
289  return std::nullopt;
290  }
291 
292  auto context = context_.lock();
293  if (!context) {
294  return std::nullopt;
295  }
296 
297  auto& vk_context = ContextVK::Cast(*context);
298  const auto [result, surface_caps] =
299  vk_context.GetPhysicalDevice().getSurfaceCapabilitiesKHR(surface_.get());
300  if (result != vk::Result::eSuccess) {
301  return std::nullopt;
302  }
303 
304  // From the spec: `currentExtent` is the current width and height of the
305  // surface, or the special value (0xFFFFFFFF, 0xFFFFFFFF) indicating that the
306  // surface size will be determined by the extent of a swapchain targeting the
307  // surface.
308  constexpr uint32_t kCurrentExtentsPlaceholder = 0xFFFFFFFF;
309  if (surface_caps.currentExtent.width == kCurrentExtentsPlaceholder ||
310  surface_caps.currentExtent.height == kCurrentExtentsPlaceholder) {
311  return std::nullopt;
312  }
313 
314  return ISize::MakeWH(surface_caps.currentExtent.width,
315  surface_caps.currentExtent.height);
316 }
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 282 of file khr_swapchain_impl_vk.cc.

282  {
283  return size_;
284 }

◆ GetSurfaceFormat()

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

Definition at line 339 of file khr_swapchain_impl_vk.cc.

339  {
340  return surface_format_;
341 }

◆ IsValid()

bool impeller::KHRSwapchainImplVK::IsValid ( ) const

Definition at line 318 of file khr_swapchain_impl_vk.cc.

318  {
319  return is_valid_;
320 }

Referenced by GetCurrentUnderlyingSurfaceSize().


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