[Impeller] use 3 fences to synchronize AHB swapchains (like we do for KHR). (#161767)
Testing on a newer Adreno, I can still see rendering artifacts. This change matches the syncrhonization to what we do for KHR, and on the Adreno I see no more rendering artifacts.
This commit is contained in:
parent
095f46c4a7
commit
32ef7f8e2e
@ -42719,8 +42719,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swap
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_texture_pool_vk.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_texture_pool_vk.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_fence_vk.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_fence_vk.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc + ../../../flutter/LICENSE
|
||||
@ -45665,8 +45665,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapch
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_texture_pool_vk.cc
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_texture_pool_vk.h
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_fence_vk.cc
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_fence_vk.h
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.cc
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.h
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h
|
||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc
|
||||
|
@ -141,8 +141,8 @@ impeller_component("vulkan") {
|
||||
"swapchain/ahb/ahb_swapchain_vk.h",
|
||||
"swapchain/ahb/ahb_texture_pool_vk.cc",
|
||||
"swapchain/ahb/ahb_texture_pool_vk.h",
|
||||
"swapchain/ahb/external_fence_vk.cc",
|
||||
"swapchain/ahb/external_fence_vk.h",
|
||||
"swapchain/ahb/external_semaphore_vk.cc",
|
||||
"swapchain/ahb/external_semaphore_vk.h",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -4,24 +4,16 @@
|
||||
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.h"
|
||||
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "impeller/base/validation.h"
|
||||
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_formats.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/surface_vk.h"
|
||||
#include "impeller/toolkit/android/surface_transaction.h"
|
||||
#include "impeller/toolkit/android/surface_transaction_stats.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// The maximum number of presents pending in the compositor after which the
|
||||
/// acquire calls will block. This value is 2 images given to the system
|
||||
/// compositor and one for the raster thread, Because the semaphore is acquired
|
||||
/// when the CPU begins working on the texture
|
||||
///
|
||||
static constexpr const size_t kMaxPendingPresents = 3u;
|
||||
|
||||
static TextureDescriptor ToSwapchainTextureDescriptor(
|
||||
const android::HardwareBufferDescriptor& ahb_desc) {
|
||||
TextureDescriptor desc;
|
||||
@ -36,6 +28,41 @@ static TextureDescriptor ToSwapchainTextureDescriptor(
|
||||
return desc;
|
||||
}
|
||||
|
||||
AHBFrameSynchronizerVK::AHBFrameSynchronizerVK(const vk::Device& device) {
|
||||
auto acquire_res = device.createFenceUnique(
|
||||
vk::FenceCreateInfo{vk::FenceCreateFlagBits::eSignaled});
|
||||
if (acquire_res.result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Could not create synchronizer.";
|
||||
return;
|
||||
}
|
||||
acquire = std::move(acquire_res.value);
|
||||
is_valid = true;
|
||||
}
|
||||
|
||||
AHBFrameSynchronizerVK::~AHBFrameSynchronizerVK() = default;
|
||||
|
||||
bool AHBFrameSynchronizerVK::IsValid() const {
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
bool AHBFrameSynchronizerVK::WaitForFence(const vk::Device& device) {
|
||||
if (auto result = device.waitForFences(
|
||||
*acquire, // fence
|
||||
true, // wait all
|
||||
std::numeric_limits<uint64_t>::max() // timeout (ns)
|
||||
);
|
||||
result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Fence wait failed: " << vk::to_string(result);
|
||||
return false;
|
||||
}
|
||||
if (auto result = device.resetFences(*acquire);
|
||||
result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Could not reset fence: " << vk::to_string(result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<AHBSwapchainImplVK> AHBSwapchainImplVK::Create(
|
||||
const std::weak_ptr<Context>& context,
|
||||
std::weak_ptr<android::SurfaceControl> surface_control,
|
||||
@ -54,8 +81,7 @@ AHBSwapchainImplVK::AHBSwapchainImplVK(
|
||||
const ISize& size,
|
||||
bool enable_msaa,
|
||||
size_t swapchain_image_count)
|
||||
: surface_control_(std::move(surface_control)),
|
||||
pending_presents_(std::make_shared<fml::Semaphore>(kMaxPendingPresents)) {
|
||||
: surface_control_(std::move(surface_control)) {
|
||||
desc_ = android::HardwareBufferDescriptor::MakeForSwapchainImage(size);
|
||||
pool_ =
|
||||
std::make_shared<AHBTexturePoolVK>(context, desc_, swapchain_image_count);
|
||||
@ -65,6 +91,15 @@ AHBSwapchainImplVK::AHBSwapchainImplVK(
|
||||
transients_ = std::make_shared<SwapchainTransientsVK>(
|
||||
context, ToSwapchainTextureDescriptor(desc_), enable_msaa);
|
||||
|
||||
for (auto i = 0u; i < kMaxPendingPresents; i++) {
|
||||
auto sync = std::make_unique<AHBFrameSynchronizerVK>(
|
||||
ContextVK::Cast(*context.lock()).GetDeviceHolder()->GetDevice());
|
||||
if (!sync->IsValid()) {
|
||||
return;
|
||||
}
|
||||
frame_data_.push_back(std::move(sync));
|
||||
}
|
||||
|
||||
auto control = surface_control_.lock();
|
||||
is_valid_ = control && control->IsValid();
|
||||
}
|
||||
@ -85,17 +120,17 @@ const android::HardwareBufferDescriptor& AHBSwapchainImplVK::GetDescriptor()
|
||||
}
|
||||
|
||||
std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
||||
{
|
||||
TRACE_EVENT0("impeller", "CompositorPendingWait");
|
||||
if (!pending_presents_->Wait()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto context = transients_->GetContext().lock();
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
frame_index_ = (frame_index_ + 1) % kMaxPendingPresents;
|
||||
AutoSemaSignaler auto_sema_signaler =
|
||||
std::make_shared<fml::ScopedCleanupClosure>(
|
||||
[sema = pending_presents_]() { sema->Signal(); });
|
||||
|
||||
if (!frame_data_[frame_index_]->WaitForFence(
|
||||
ContextVK::Cast(*context).GetDevice())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!is_valid_) {
|
||||
return nullptr;
|
||||
@ -110,14 +145,12 @@ std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
||||
|
||||
// Import the render ready semaphore that will block onscreen rendering until
|
||||
// it is ready.
|
||||
if (!SubmitWaitForRenderReady(pool_entry.render_ready_fence,
|
||||
pool_entry.texture)) {
|
||||
if (!ImportRenderReady(pool_entry.render_ready_fence, pool_entry.texture)) {
|
||||
VALIDATION_LOG << "Could wait on render ready fence.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if IMPELLER_DEBUG
|
||||
auto context = transients_->GetContext().lock();
|
||||
if (context) {
|
||||
ContextVK::Cast(*context).GetGPUTracer()->MarkFrameStart();
|
||||
}
|
||||
@ -125,14 +158,13 @@ std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
||||
|
||||
auto surface = SurfaceVK::WrapSwapchainImage(
|
||||
transients_, pool_entry.texture,
|
||||
[signaler = auto_sema_signaler, weak = weak_from_this(),
|
||||
texture = pool_entry.texture]() {
|
||||
[weak = weak_from_this(), texture = pool_entry.texture]() {
|
||||
auto thiz = weak.lock();
|
||||
if (!thiz) {
|
||||
VALIDATION_LOG << "Swapchain died before image could be presented.";
|
||||
return false;
|
||||
}
|
||||
return thiz->Present(signaler, texture);
|
||||
return thiz->Present(texture);
|
||||
});
|
||||
|
||||
if (!surface) {
|
||||
@ -143,7 +175,6 @@ std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
||||
}
|
||||
|
||||
bool AHBSwapchainImplVK::Present(
|
||||
const AutoSemaSignaler& signaler,
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture) {
|
||||
auto control = surface_control_.lock();
|
||||
if (!control || !control->IsValid()) {
|
||||
@ -163,9 +194,9 @@ bool AHBSwapchainImplVK::Present(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fence = SubmitSignalForPresentReady(texture);
|
||||
auto present_ready = SubmitSignalForPresentReady(texture);
|
||||
|
||||
if (!fence) {
|
||||
if (!present_ready) {
|
||||
VALIDATION_LOG << "Could not submit completion signal.";
|
||||
return false;
|
||||
}
|
||||
@ -173,67 +204,70 @@ bool AHBSwapchainImplVK::Present(
|
||||
android::SurfaceTransaction transaction;
|
||||
if (!transaction.SetContents(control.get(), //
|
||||
texture->GetBackingStore(), //
|
||||
fence->CreateFD() //
|
||||
present_ready->CreateFD() //
|
||||
)) {
|
||||
VALIDATION_LOG << "Could not set swapchain image contents on the surface "
|
||||
"control.";
|
||||
return false;
|
||||
}
|
||||
return transaction.Apply([signaler, texture, weak = weak_from_this()](
|
||||
ASurfaceTransactionStats* stats) {
|
||||
auto thiz = weak.lock();
|
||||
if (!thiz) {
|
||||
return;
|
||||
}
|
||||
thiz->OnTextureUpdatedOnSurfaceControl(signaler, texture, stats);
|
||||
});
|
||||
return transaction.Apply(
|
||||
[texture, weak = weak_from_this()](ASurfaceTransactionStats* stats) {
|
||||
auto thiz = weak.lock();
|
||||
if (!thiz) {
|
||||
return;
|
||||
}
|
||||
thiz->OnTextureUpdatedOnSurfaceControl(texture, stats);
|
||||
});
|
||||
}
|
||||
|
||||
void AHBSwapchainImplVK::AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) {
|
||||
frame_data_[frame_index_].command_buffer = std::move(cmd_buffer);
|
||||
frame_data_[frame_index_]->final_cmd_buffer = std::move(cmd_buffer);
|
||||
}
|
||||
|
||||
std::shared_ptr<ExternalFenceVK>
|
||||
std::shared_ptr<ExternalSemaphoreVK>
|
||||
AHBSwapchainImplVK::SubmitSignalForPresentReady(
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture) const {
|
||||
auto context = transients_->GetContext().lock();
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
auto fence = std::make_shared<ExternalFenceVK>(context);
|
||||
if (!fence || !fence->IsValid()) {
|
||||
|
||||
auto present_ready = std::make_shared<ExternalSemaphoreVK>(context);
|
||||
if (!present_ready || !present_ready->IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto command_buffer = frame_data_[frame_index_].command_buffer;
|
||||
auto& sync = frame_data_[frame_index_];
|
||||
auto command_buffer = sync->final_cmd_buffer;
|
||||
if (!command_buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
CommandBufferVK& command_buffer_vk = CommandBufferVK::Cast(*command_buffer);
|
||||
const auto command_encoder_vk = command_buffer_vk.GetCommandBuffer();
|
||||
command_buffer_vk.Track(fence->GetSharedHandle());
|
||||
|
||||
if (!command_buffer_vk.EndCommandBuffer()) {
|
||||
return nullptr;
|
||||
}
|
||||
sync->present_ready = present_ready;
|
||||
|
||||
vk::SubmitInfo submit_info;
|
||||
vk::PipelineStageFlags wait_stage =
|
||||
vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
if (frame_data_[frame_index_].semaphore) {
|
||||
submit_info.setPWaitSemaphores(&frame_data_[frame_index_].semaphore.get());
|
||||
if (sync->render_ready) {
|
||||
submit_info.setPWaitSemaphores(&sync->render_ready.get());
|
||||
submit_info.setWaitSemaphoreCount(1);
|
||||
submit_info.setWaitDstStageMask(wait_stage);
|
||||
}
|
||||
submit_info.setCommandBuffers(command_encoder_vk);
|
||||
submit_info.setPSignalSemaphores(&sync->present_ready->GetHandle());
|
||||
submit_info.setSignalSemaphoreCount(1);
|
||||
|
||||
auto result = ContextVK::Cast(*context).GetGraphicsQueue()->Submit(
|
||||
submit_info, fence->GetHandle());
|
||||
submit_info, *sync->acquire);
|
||||
if (result != vk::Result::eSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
return fence;
|
||||
return present_ready;
|
||||
}
|
||||
|
||||
vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
||||
@ -251,7 +285,6 @@ vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
||||
const auto& device = context_vk.GetDevice();
|
||||
|
||||
auto signal_wait = device.createSemaphoreUnique({});
|
||||
|
||||
if (signal_wait.result != vk::Result::eSuccess) {
|
||||
return {};
|
||||
}
|
||||
@ -282,33 +315,32 @@ vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
||||
return std::move(signal_wait.value);
|
||||
}
|
||||
|
||||
bool AHBSwapchainImplVK::SubmitWaitForRenderReady(
|
||||
bool AHBSwapchainImplVK::ImportRenderReady(
|
||||
const std::shared_ptr<fml::UniqueFD>& render_ready_fence,
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture) {
|
||||
// If there is no render ready fence, we are already ready to render into
|
||||
// the texture. There is nothing more to do.
|
||||
if (!render_ready_fence || !render_ready_fence->is_valid()) {
|
||||
frame_data_[frame_index_].semaphore = {};
|
||||
return true;
|
||||
}
|
||||
|
||||
auto context = transients_->GetContext().lock();
|
||||
if (!context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no render ready fence, we are already ready to render into
|
||||
// the texture. There is nothing more to do.
|
||||
if (!render_ready_fence || !render_ready_fence->is_valid()) {
|
||||
frame_data_[frame_index_]->render_ready = {};
|
||||
return true;
|
||||
}
|
||||
|
||||
auto semaphore = CreateRenderReadySemaphore(render_ready_fence);
|
||||
if (!semaphore) {
|
||||
return false;
|
||||
}
|
||||
// This semaphore will be later used to block the onscreen render pass
|
||||
// from starting until the system is done reading the onscreen.
|
||||
frame_data_[frame_index_].semaphore = std::move(semaphore);
|
||||
frame_data_[frame_index_]->render_ready = std::move(semaphore);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AHBSwapchainImplVK::OnTextureUpdatedOnSurfaceControl(
|
||||
const AutoSemaSignaler& signaler,
|
||||
std::shared_ptr<AHBTextureSourceVK> texture,
|
||||
ASurfaceTransactionStats* stats) {
|
||||
auto control = surface_control_.lock();
|
||||
|
@ -8,11 +8,10 @@
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/fml/closure.h"
|
||||
#include "flutter/fml/synchronization/semaphore.h"
|
||||
#include "impeller/base/thread.h"
|
||||
#include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_texture_pool_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/external_fence_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/swapchain_transients_vk.h"
|
||||
#include "impeller/renderer/surface.h"
|
||||
#include "impeller/toolkit/android/hardware_buffer.h"
|
||||
@ -21,6 +20,24 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
static constexpr const size_t kMaxPendingPresents = 2u;
|
||||
|
||||
struct AHBFrameSynchronizerVK {
|
||||
vk::UniqueFence acquire;
|
||||
vk::UniqueSemaphore render_ready = {};
|
||||
std::shared_ptr<ExternalSemaphoreVK> present_ready;
|
||||
std::shared_ptr<CommandBuffer> final_cmd_buffer;
|
||||
bool is_valid = false;
|
||||
|
||||
explicit AHBFrameSynchronizerVK(const vk::Device& device);
|
||||
|
||||
~AHBFrameSynchronizerVK();
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
bool WaitForFence(const vk::Device& device);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief The implementation of a swapchain at a specific size. Resizes to
|
||||
/// the surface will cause the instance of the swapchain impl at
|
||||
@ -99,19 +116,14 @@ class AHBSwapchainImplVK final
|
||||
android::HardwareBufferDescriptor desc_;
|
||||
std::shared_ptr<AHBTexturePoolVK> pool_;
|
||||
std::shared_ptr<SwapchainTransientsVK> transients_;
|
||||
|
||||
// In C++20, this mutex can be replaced by the shared pointer specialization
|
||||
// of std::atomic.
|
||||
Mutex currently_displayed_texture_mutex_;
|
||||
std::shared_ptr<AHBTextureSourceVK> currently_displayed_texture_
|
||||
IPLR_GUARDED_BY(currently_displayed_texture_mutex_);
|
||||
std::shared_ptr<fml::Semaphore> pending_presents_;
|
||||
|
||||
struct FrameData {
|
||||
std::shared_ptr<CommandBuffer> command_buffer;
|
||||
vk::UniqueSemaphore semaphore;
|
||||
};
|
||||
|
||||
std::array<FrameData, 3> frame_data_;
|
||||
std::vector<std::unique_ptr<AHBFrameSynchronizerVK>> frame_data_;
|
||||
size_t frame_index_ = 0;
|
||||
bool is_valid_ = false;
|
||||
|
||||
@ -122,21 +134,19 @@ class AHBSwapchainImplVK final
|
||||
bool enable_msaa,
|
||||
size_t swapchain_image_count);
|
||||
|
||||
bool Present(const AutoSemaSignaler& signaler,
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture);
|
||||
bool Present(const std::shared_ptr<AHBTextureSourceVK>& texture);
|
||||
|
||||
vk::UniqueSemaphore CreateRenderReadySemaphore(
|
||||
const std::shared_ptr<fml::UniqueFD>& fd) const;
|
||||
|
||||
bool SubmitWaitForRenderReady(
|
||||
bool ImportRenderReady(
|
||||
const std::shared_ptr<fml::UniqueFD>& render_ready_fence,
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture);
|
||||
|
||||
std::shared_ptr<ExternalFenceVK> SubmitSignalForPresentReady(
|
||||
std::shared_ptr<ExternalSemaphoreVK> SubmitSignalForPresentReady(
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture) const;
|
||||
|
||||
void OnTextureUpdatedOnSurfaceControl(
|
||||
const AutoSemaSignaler& signaler,
|
||||
std::shared_ptr<AHBTextureSourceVK> texture,
|
||||
ASurfaceTransactionStats* stats);
|
||||
};
|
||||
|
@ -1,64 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/external_fence_vk.h"
|
||||
|
||||
#include "impeller/base/validation.h"
|
||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
ExternalFenceVK::ExternalFenceVK(const std::shared_ptr<Context>& context) {
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
vk::StructureChain<vk::FenceCreateInfo, vk::ExportFenceCreateInfoKHR> info;
|
||||
|
||||
info.get<vk::ExportFenceCreateInfoKHR>().handleTypes =
|
||||
vk::ExternalFenceHandleTypeFlagBits::eSyncFd;
|
||||
|
||||
const auto& context_vk = ContextVK::Cast(*context);
|
||||
auto [result, fence] = context_vk.GetDevice().createFenceUnique(info.get());
|
||||
if (result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Could not create external fence: "
|
||||
<< vk::to_string(result);
|
||||
return;
|
||||
}
|
||||
|
||||
context_vk.SetDebugName(fence.get(), "ExternalFenceSyncFD");
|
||||
|
||||
fence_ = MakeSharedVK(std::move(fence));
|
||||
}
|
||||
|
||||
ExternalFenceVK::~ExternalFenceVK() = default;
|
||||
|
||||
bool ExternalFenceVK::IsValid() const {
|
||||
return !!fence_;
|
||||
}
|
||||
|
||||
fml::UniqueFD ExternalFenceVK::CreateFD() const {
|
||||
if (!IsValid()) {
|
||||
return {};
|
||||
}
|
||||
vk::FenceGetFdInfoKHR info;
|
||||
info.fence = fence_->Get();
|
||||
info.handleType = vk::ExternalFenceHandleTypeFlagBits::eSyncFd;
|
||||
auto [result, fd] = fence_->GetUniqueWrapper().getOwner().getFenceFdKHR(info);
|
||||
if (result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Could not export external fence FD: "
|
||||
<< vk::to_string(result);
|
||||
return {};
|
||||
}
|
||||
return fml::UniqueFD{fd};
|
||||
}
|
||||
|
||||
const vk::Fence& ExternalFenceVK::GetHandle() const {
|
||||
return fence_->Get();
|
||||
}
|
||||
|
||||
const SharedHandleVK<vk::Fence>& ExternalFenceVK::GetSharedHandle() const {
|
||||
return fence_;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
@ -0,0 +1,70 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/external_semaphore_vk.h"
|
||||
|
||||
#include "impeller/base/validation.h"
|
||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||
#include "vulkan/vulkan_handles.hpp"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
ExternalSemaphoreVK::ExternalSemaphoreVK(
|
||||
const std::shared_ptr<Context>& context) {
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
vk::StructureChain<vk::SemaphoreCreateInfo, vk::ExportSemaphoreCreateInfoKHR>
|
||||
info;
|
||||
|
||||
info.get<vk::ExportSemaphoreCreateInfoKHR>().handleTypes =
|
||||
vk::ExternalSemaphoreHandleTypeFlagBits::eSyncFd;
|
||||
|
||||
const auto& context_vk = ContextVK::Cast(*context);
|
||||
auto [result, semaphore] =
|
||||
context_vk.GetDevice().createSemaphoreUnique(info.get());
|
||||
if (result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Could not create external fence: "
|
||||
<< vk::to_string(result);
|
||||
return;
|
||||
}
|
||||
|
||||
context_vk.SetDebugName(semaphore.get(), "ExternalSemaphoreSyncFD");
|
||||
|
||||
semaphore_ = MakeSharedVK(std::move(semaphore));
|
||||
}
|
||||
|
||||
ExternalSemaphoreVK::~ExternalSemaphoreVK() = default;
|
||||
|
||||
bool ExternalSemaphoreVK::IsValid() const {
|
||||
return !!semaphore_;
|
||||
}
|
||||
|
||||
fml::UniqueFD ExternalSemaphoreVK::CreateFD() const {
|
||||
if (!IsValid()) {
|
||||
return {};
|
||||
}
|
||||
vk::SemaphoreGetFdInfoKHR info;
|
||||
info.semaphore = semaphore_->Get();
|
||||
info.handleType = vk::ExternalSemaphoreHandleTypeFlagBits::eSyncFd;
|
||||
auto [result, fd] =
|
||||
semaphore_->GetUniqueWrapper().getOwner().getSemaphoreFdKHR(info);
|
||||
if (result != vk::Result::eSuccess) {
|
||||
VALIDATION_LOG << "Could not export external fence FD: "
|
||||
<< vk::to_string(result);
|
||||
return {};
|
||||
}
|
||||
return fml::UniqueFD{fd};
|
||||
}
|
||||
|
||||
const vk::Semaphore& ExternalSemaphoreVK::GetHandle() const {
|
||||
return semaphore_->Get();
|
||||
}
|
||||
|
||||
const SharedHandleVK<vk::Semaphore>& ExternalSemaphoreVK::GetSharedHandle()
|
||||
const {
|
||||
return semaphore_;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
@ -2,44 +2,43 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_FENCE_VK_H_
|
||||
#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_FENCE_VK_H_
|
||||
#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_SEMAPHORE_VK_H_
|
||||
#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_SEMAPHORE_VK_H_
|
||||
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "impeller/renderer/backend/vulkan/shared_object_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/vk.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "vulkan/vulkan_handles.hpp"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief A Vulkan fence that can be exported as a platform specific file
|
||||
/// descriptor.
|
||||
/// @brief A Vulkan semaphore that can be exported as a platform specific
|
||||
/// file descriptor.
|
||||
///
|
||||
/// The fences are exported as sync file descriptors.
|
||||
/// The semaphore are exported as sync file descriptors.
|
||||
///
|
||||
/// @warning Only fences that have been signaled or have a single operation
|
||||
/// pending can be exported. Make sure to submit a fence signalling
|
||||
/// operation to a queue before attempted to obtain a file
|
||||
/// descriptor for the fence. See
|
||||
/// VUID-VkFenceGetFdInfoKHR-handleType-01454 for additional details
|
||||
/// on the implementation.
|
||||
/// @warning Only semaphore that have been signaled or have a single
|
||||
/// operation pending can be exported. Make sure to submit a fence
|
||||
/// signalling operation to a queue before attempted to obtain a
|
||||
/// file descriptor for the fence.
|
||||
///
|
||||
class ExternalFenceVK {
|
||||
class ExternalSemaphoreVK {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Create a new un-signaled fence that can be exported as a sync
|
||||
/// file descriptor.
|
||||
/// @brief Create a new un-signaled semaphore that can be exported as a
|
||||
/// sync file descriptor.
|
||||
///
|
||||
/// @param[in] context The device context.
|
||||
///
|
||||
explicit ExternalFenceVK(const std::shared_ptr<Context>& context);
|
||||
explicit ExternalSemaphoreVK(const std::shared_ptr<Context>& context);
|
||||
|
||||
~ExternalFenceVK();
|
||||
~ExternalSemaphoreVK();
|
||||
|
||||
ExternalFenceVK(const ExternalFenceVK&) = delete;
|
||||
ExternalSemaphoreVK(const ExternalSemaphoreVK&) = delete;
|
||||
|
||||
ExternalFenceVK& operator=(const ExternalFenceVK&) = delete;
|
||||
ExternalSemaphoreVK& operator=(const ExternalSemaphoreVK&) = delete;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief If a valid fence could be created.
|
||||
@ -49,16 +48,18 @@ class ExternalFenceVK {
|
||||
bool IsValid() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Create a new sync file descriptor for the underlying fence.
|
||||
/// The fence must already be signaled or have a signal operation
|
||||
/// pending in a queue. There are no checks for this in the
|
||||
/// implementation and only Vulkan validation will catch such a
|
||||
/// misuse and undefined behavior.
|
||||
/// @brief Create a new sync file descriptor for the underlying
|
||||
/// semaphore.
|
||||
///
|
||||
/// The semaphore must already be signaled or have a signal
|
||||
/// operation pending in a queue. There are no checks for this in
|
||||
/// the implementation and only Vulkan validation will catch such
|
||||
/// a misuse and undefined behavior.
|
||||
///
|
||||
/// @warning Implementations are also allowed to return invalid file
|
||||
/// descriptors in case a fence has already been signaled. So it
|
||||
/// is not necessary an error to obtain an invalid descriptor from
|
||||
/// this call. For APIs that are meant to consume such
|
||||
/// descriptors in case a semaphore has already been signaled. So
|
||||
/// it is not necessary an error to obtain an invalid descriptor
|
||||
/// from this call. For APIs that are meant to consume such
|
||||
/// descriptors, pass -1 as the file handle.
|
||||
///
|
||||
/// Since this call can return an invalid FD even in case of
|
||||
@ -70,14 +71,14 @@ class ExternalFenceVK {
|
||||
///
|
||||
fml::UniqueFD CreateFD() const;
|
||||
|
||||
const vk::Fence& GetHandle() const;
|
||||
const vk::Semaphore& GetHandle() const;
|
||||
|
||||
const SharedHandleVK<vk::Fence>& GetSharedHandle() const;
|
||||
const SharedHandleVK<vk::Semaphore>& GetSharedHandle() const;
|
||||
|
||||
private:
|
||||
SharedHandleVK<vk::Fence> fence_;
|
||||
SharedHandleVK<vk::Semaphore> semaphore_;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_FENCE_VK_H_
|
||||
#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_SEMAPHORE_VK_H_
|
Loading…
x
Reference in New Issue
Block a user