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  default:
395  // An unrecoverable error.
396  VALIDATION_LOG << "Could not acquire next swapchain image: "
397  << vk::to_string(acq_result);
398  return AcquireResult{false /* out of date */};
399  }
400 
401  if (index >= images_.size()) {
402  VALIDATION_LOG << "Swapchain returned an invalid image index.";
403  return KHRSwapchainImplVK::AcquireResult{};
404  }
405 
406  /// Record all subsequent cmd buffers as part of the current frame.
407  context.GetGPUTracer()->MarkFrameStart();
408 
409  auto image = images_[index % images_.size()];
410  uint32_t image_index = index;
411  return AcquireResult{SurfaceVK::WrapSwapchainImage(
412  transients_, // transients
413  image, // swapchain image
414  [weak_swapchain = weak_from_this(), image, image_index]() -> bool {
415  auto swapchain = weak_swapchain.lock();
416  if (!swapchain) {
417  return false;
418  }
419  return swapchain->Present(image, image_index);
420  } // swap callback
421  )};
422 }
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 424 of file khr_swapchain_impl_vk.cc.

425  {
426  const auto& sync = synchronizers_[current_frame_];
427  sync->final_cmd_buffer = std::move(cmd_buffer);
428  sync->has_onscreen = true;
429 }

◆ 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: