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

273  {
275 }
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 342 of file khr_swapchain_impl_vk.cc.

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

416  {
417  const auto& sync = synchronizers_[current_frame_];
418  sync->final_cmd_buffer = std::move(cmd_buffer);
419  sync->has_onscreen = true;
420 }

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

325  {
326  WaitIdle();
327  is_valid_ = false;
328  synchronizers_.clear();
329  images_.clear();
330  context_.reset();
331  return {std::move(surface_), std::move(swapchain_)};
332 }

Referenced by ~KHRSwapchainImplVK().

◆ GetContext()

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

Definition at line 338 of file khr_swapchain_impl_vk.cc.

338  {
339  return context_.lock();
340 }

◆ GetCurrentUnderlyingSurfaceSize()

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

Definition at line 281 of file khr_swapchain_impl_vk.cc.

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

277  {
278  return size_;
279 }

◆ GetSurfaceFormat()

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

Definition at line 334 of file khr_swapchain_impl_vk.cc.

334  {
335  return surface_format_;
336 }

◆ IsValid()

bool impeller::KHRSwapchainImplVK::IsValid ( ) const

Definition at line 313 of file khr_swapchain_impl_vk.cc.

313  {
314  return is_valid_;
315 }

Referenced by GetCurrentUnderlyingSurfaceSize().


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