Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Replace Vulkan rotation checks with polling #44361

Merged
merged 9 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 45 additions & 22 deletions impeller/renderer/backend/vulkan/swapchain_impl_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/surface_vk.h"
#include "impeller/renderer/backend/vulkan/swapchain_image_vk.h"
#include "vulkan/vulkan_structs.hpp"

namespace impeller {

static constexpr size_t kMaxFramesInFlight = 3u;

// Number of frames to poll for orientation changes. For example `1u` means
// that the orientation will be polled every frame, while `2u` means that the
// orientation will be polled every other frame.
static constexpr size_t kPollFramesForOrientation = 1u;

struct FrameSynchronizer {
vk::UniqueFence acquire;
vk::UniqueSemaphore render_ready;
Expand Down Expand Up @@ -124,16 +130,17 @@ static std::optional<vk::Queue> ChoosePresentQueue(
std::shared_ptr<SwapchainImplVK> SwapchainImplVK::Create(
const std::shared_ptr<Context>& context,
vk::UniqueSurfaceKHR surface,
bool was_rotated,
vk::SwapchainKHR old_swapchain) {
vk::SwapchainKHR old_swapchain,
vk::SurfaceTransformFlagBitsKHR last_transform) {
return std::shared_ptr<SwapchainImplVK>(new SwapchainImplVK(
context, std::move(surface), was_rotated, old_swapchain));
context, std::move(surface), old_swapchain, last_transform));
}

SwapchainImplVK::SwapchainImplVK(const std::shared_ptr<Context>& context,
vk::UniqueSurfaceKHR surface,
bool was_rotated,
vk::SwapchainKHR old_swapchain) {
SwapchainImplVK::SwapchainImplVK(
const std::shared_ptr<Context>& context,
vk::UniqueSurfaceKHR surface,
vk::SwapchainKHR old_swapchain,
vk::SurfaceTransformFlagBitsKHR last_transform) {
if (!context) {
return;
}
Expand Down Expand Up @@ -278,8 +285,7 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr<Context>& context,
synchronizers_ = std::move(synchronizers);
current_frame_ = synchronizers_.size() - 1u;
is_valid_ = true;
was_rotated_ = was_rotated;
is_rotated_ = was_rotated;
transform_if_changed_discard_swapchain_ = last_transform;
}

SwapchainImplVK::~SwapchainImplVK() {
Expand Down Expand Up @@ -311,6 +317,10 @@ vk::Format SwapchainImplVK::GetSurfaceFormat() const {
return surface_format_;
}

vk::SurfaceTransformFlagBitsKHR SwapchainImplVK::GetLastTransform() const {
return transform_if_changed_discard_swapchain_;
}

std::shared_ptr<Context> SwapchainImplVK::GetContext() const {
return context_.lock();
}
Expand All @@ -321,10 +331,6 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() {
return {};
}

if (was_rotated_ != is_rotated_) {
return AcquireResult{true /* out of date */};
}

const auto& context = ContextVK::Cast(*context_strong);

current_frame_ = (current_frame_ + 1u) % synchronizers_.size();
Expand All @@ -339,6 +345,26 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() {
return {};
}

//----------------------------------------------------------------------------
/// Poll to see if the orientation has changed.
///
/// https://developer.android.com/games/optimize/vulkan-prerotation#using_polling
current_transform_poll_count_++;
if (current_transform_poll_count_ >= kPollFramesForOrientation) {
current_transform_poll_count_ = 0u;
auto [caps_result, caps] =
context.GetPhysicalDevice().getSurfaceCapabilitiesKHR(*surface_);
if (caps_result != vk::Result::eSuccess) {
VALIDATION_LOG << "Could not get surface capabilities: "
<< vk::to_string(caps_result);
return {};
}
if (caps.currentTransform != transform_if_changed_discard_swapchain_) {
transform_if_changed_discard_swapchain_ = caps.currentTransform;
return AcquireResult{true /* out of date */};
}
}

//----------------------------------------------------------------------------
/// Get the next image index.
///
Expand All @@ -349,11 +375,6 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() {
nullptr // fence
);

if (acq_result == vk::Result::eSuboptimalKHR) {
is_rotated_ = true;
return AcquireResult{true /* out of date */};
}

if (acq_result == vk::Result::eErrorOutOfDateKHR) {
return AcquireResult{true /* out of date */};
}
Expand Down Expand Up @@ -469,11 +490,13 @@ bool SwapchainImplVK::Present(const std::shared_ptr<SwapchainImageVK>& image,
// Vulkan guarantees that the set of queue operations will still
// complete successfully.
[[fallthrough]];
case vk::Result::eSuccess:
is_rotated_ = false;
return;
case vk::Result::eSuboptimalKHR:
is_rotated_ = true;
// Even though we're handling rotation changes via polling, we
// still need to handle the case where the swapchain signals that
// it's suboptimal (i.e. every frame when we are rotated given we
// aren't doing Vulkan pre-rotation).
[[fallthrough]];
case vk::Result::eSuccess:
return;
default:
VALIDATION_LOG << "Could not present queue: "
Expand Down
19 changes: 10 additions & 9 deletions impeller/renderer/backend/vulkan/swapchain_impl_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "flutter/fml/macros.h"
#include "impeller/renderer/backend/vulkan/vk.h"
#include "vulkan/vulkan_enums.hpp"

namespace impeller {

Expand All @@ -31,8 +32,9 @@ class SwapchainImplVK final
static std::shared_ptr<SwapchainImplVK> Create(
const std::shared_ptr<Context>& context,
vk::UniqueSurfaceKHR surface,
bool was_rotated,
vk::SwapchainKHR old_swapchain = VK_NULL_HANDLE);
vk::SwapchainKHR old_swapchain = VK_NULL_HANDLE,
vk::SurfaceTransformFlagBitsKHR last_transform =
vk::SurfaceTransformFlagBitsKHR::eIdentity);

~SwapchainImplVK();

Expand All @@ -48,12 +50,12 @@ class SwapchainImplVK final
: surface(std::move(p_surface)) {}
};

bool GetIsRotated() const { return is_rotated_; }

AcquireResult AcquireNextDrawable();

vk::Format GetSurfaceFormat() const;

vk::SurfaceTransformFlagBitsKHR GetLastTransform() const;

std::shared_ptr<Context> GetContext() const;

std::pair<vk::UniqueSurfaceKHR, vk::UniqueSwapchainKHR> DestroySwapchain();
Expand All @@ -68,14 +70,13 @@ class SwapchainImplVK final
std::vector<std::unique_ptr<FrameSynchronizer>> synchronizers_;
size_t current_frame_ = 0u;
bool is_valid_ = false;

bool was_rotated_ = false;
bool is_rotated_ = false;
size_t current_transform_poll_count_ = 0u;
vk::SurfaceTransformFlagBitsKHR transform_if_changed_discard_swapchain_;

SwapchainImplVK(const std::shared_ptr<Context>& context,
vk::UniqueSurfaceKHR surface,
bool was_rotated,
vk::SwapchainKHR old_swapchain);
vk::SwapchainKHR old_swapchain,
vk::SurfaceTransformFlagBitsKHR last_transform);

bool Present(const std::shared_ptr<SwapchainImageVK>& image, uint32_t index);

Expand Down
12 changes: 5 additions & 7 deletions impeller/renderer/backend/vulkan/swapchain_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ namespace impeller {
std::shared_ptr<SwapchainVK> SwapchainVK::Create(
const std::shared_ptr<Context>& context,
vk::UniqueSurfaceKHR surface) {
auto impl = SwapchainImplVK::Create(context, std::move(surface),
/*was_rotated=*/false);
auto impl = SwapchainImplVK::Create(context, std::move(surface));
if (!impl || !impl->IsValid()) {
return nullptr;
}
Expand Down Expand Up @@ -46,13 +45,12 @@ std::unique_ptr<Surface> SwapchainVK::AcquireNextDrawable() {
// This swapchain implementation indicates that it is out of date. Tear it
// down and make a new one.
auto context = impl_->GetContext();
auto was_rotated = impl_->GetIsRotated();
auto [surface, old_swapchain] = impl_->DestroySwapchain();

auto new_impl = SwapchainImplVK::Create(context, //
std::move(surface), //
was_rotated, //
*old_swapchain //
auto new_impl = SwapchainImplVK::Create(context, //
std::move(surface), //
*old_swapchain, //
impl_->GetLastTransform() //
);
if (!new_impl || !new_impl->IsValid()) {
VALIDATION_LOG << "Could not update swapchain.";
Expand Down