[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_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.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/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_semaphore_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.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.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_image_vk.h + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc + ../../../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_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.cc
|
||||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_texture_pool_vk.h
|
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_semaphore_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.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.cc
|
||||||
FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h
|
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
|
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_swapchain_vk.h",
|
||||||
"swapchain/ahb/ahb_texture_pool_vk.cc",
|
"swapchain/ahb/ahb_texture_pool_vk.cc",
|
||||||
"swapchain/ahb/ahb_texture_pool_vk.h",
|
"swapchain/ahb/ahb_texture_pool_vk.h",
|
||||||
"swapchain/ahb/external_fence_vk.cc",
|
"swapchain/ahb/external_semaphore_vk.cc",
|
||||||
"swapchain/ahb/external_fence_vk.h",
|
"swapchain/ahb/external_semaphore_vk.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,24 +4,16 @@
|
|||||||
|
|
||||||
#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.h"
|
#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/base/validation.h"
|
||||||
#include "impeller/renderer/backend/vulkan/command_buffer_vk.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/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/renderer/backend/vulkan/swapchain/surface_vk.h"
|
||||||
#include "impeller/toolkit/android/surface_transaction.h"
|
#include "impeller/toolkit/android/surface_transaction.h"
|
||||||
#include "impeller/toolkit/android/surface_transaction_stats.h"
|
#include "impeller/toolkit/android/surface_transaction_stats.h"
|
||||||
|
|
||||||
namespace impeller {
|
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(
|
static TextureDescriptor ToSwapchainTextureDescriptor(
|
||||||
const android::HardwareBufferDescriptor& ahb_desc) {
|
const android::HardwareBufferDescriptor& ahb_desc) {
|
||||||
TextureDescriptor desc;
|
TextureDescriptor desc;
|
||||||
@ -36,6 +28,41 @@ static TextureDescriptor ToSwapchainTextureDescriptor(
|
|||||||
return desc;
|
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(
|
std::shared_ptr<AHBSwapchainImplVK> AHBSwapchainImplVK::Create(
|
||||||
const std::weak_ptr<Context>& context,
|
const std::weak_ptr<Context>& context,
|
||||||
std::weak_ptr<android::SurfaceControl> surface_control,
|
std::weak_ptr<android::SurfaceControl> surface_control,
|
||||||
@ -54,8 +81,7 @@ AHBSwapchainImplVK::AHBSwapchainImplVK(
|
|||||||
const ISize& size,
|
const ISize& size,
|
||||||
bool enable_msaa,
|
bool enable_msaa,
|
||||||
size_t swapchain_image_count)
|
size_t swapchain_image_count)
|
||||||
: surface_control_(std::move(surface_control)),
|
: surface_control_(std::move(surface_control)) {
|
||||||
pending_presents_(std::make_shared<fml::Semaphore>(kMaxPendingPresents)) {
|
|
||||||
desc_ = android::HardwareBufferDescriptor::MakeForSwapchainImage(size);
|
desc_ = android::HardwareBufferDescriptor::MakeForSwapchainImage(size);
|
||||||
pool_ =
|
pool_ =
|
||||||
std::make_shared<AHBTexturePoolVK>(context, desc_, swapchain_image_count);
|
std::make_shared<AHBTexturePoolVK>(context, desc_, swapchain_image_count);
|
||||||
@ -65,6 +91,15 @@ AHBSwapchainImplVK::AHBSwapchainImplVK(
|
|||||||
transients_ = std::make_shared<SwapchainTransientsVK>(
|
transients_ = std::make_shared<SwapchainTransientsVK>(
|
||||||
context, ToSwapchainTextureDescriptor(desc_), enable_msaa);
|
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();
|
auto control = surface_control_.lock();
|
||||||
is_valid_ = control && control->IsValid();
|
is_valid_ = control && control->IsValid();
|
||||||
}
|
}
|
||||||
@ -85,17 +120,17 @@ const android::HardwareBufferDescriptor& AHBSwapchainImplVK::GetDescriptor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
||||||
{
|
auto context = transients_->GetContext().lock();
|
||||||
TRACE_EVENT0("impeller", "CompositorPendingWait");
|
if (!context) {
|
||||||
if (!pending_presents_->Wait()) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
frame_index_ = (frame_index_ + 1) % kMaxPendingPresents;
|
frame_index_ = (frame_index_ + 1) % kMaxPendingPresents;
|
||||||
AutoSemaSignaler auto_sema_signaler =
|
|
||||||
std::make_shared<fml::ScopedCleanupClosure>(
|
if (!frame_data_[frame_index_]->WaitForFence(
|
||||||
[sema = pending_presents_]() { sema->Signal(); });
|
ContextVK::Cast(*context).GetDevice())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_valid_) {
|
if (!is_valid_) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -110,14 +145,12 @@ std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
|||||||
|
|
||||||
// Import the render ready semaphore that will block onscreen rendering until
|
// Import the render ready semaphore that will block onscreen rendering until
|
||||||
// it is ready.
|
// it is ready.
|
||||||
if (!SubmitWaitForRenderReady(pool_entry.render_ready_fence,
|
if (!ImportRenderReady(pool_entry.render_ready_fence, pool_entry.texture)) {
|
||||||
pool_entry.texture)) {
|
|
||||||
VALIDATION_LOG << "Could wait on render ready fence.";
|
VALIDATION_LOG << "Could wait on render ready fence.";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IMPELLER_DEBUG
|
#if IMPELLER_DEBUG
|
||||||
auto context = transients_->GetContext().lock();
|
|
||||||
if (context) {
|
if (context) {
|
||||||
ContextVK::Cast(*context).GetGPUTracer()->MarkFrameStart();
|
ContextVK::Cast(*context).GetGPUTracer()->MarkFrameStart();
|
||||||
}
|
}
|
||||||
@ -125,14 +158,13 @@ std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
|||||||
|
|
||||||
auto surface = SurfaceVK::WrapSwapchainImage(
|
auto surface = SurfaceVK::WrapSwapchainImage(
|
||||||
transients_, pool_entry.texture,
|
transients_, pool_entry.texture,
|
||||||
[signaler = auto_sema_signaler, weak = weak_from_this(),
|
[weak = weak_from_this(), texture = pool_entry.texture]() {
|
||||||
texture = pool_entry.texture]() {
|
|
||||||
auto thiz = weak.lock();
|
auto thiz = weak.lock();
|
||||||
if (!thiz) {
|
if (!thiz) {
|
||||||
VALIDATION_LOG << "Swapchain died before image could be presented.";
|
VALIDATION_LOG << "Swapchain died before image could be presented.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return thiz->Present(signaler, texture);
|
return thiz->Present(texture);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
@ -143,7 +175,6 @@ std::unique_ptr<Surface> AHBSwapchainImplVK::AcquireNextDrawable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AHBSwapchainImplVK::Present(
|
bool AHBSwapchainImplVK::Present(
|
||||||
const AutoSemaSignaler& signaler,
|
|
||||||
const std::shared_ptr<AHBTextureSourceVK>& texture) {
|
const std::shared_ptr<AHBTextureSourceVK>& texture) {
|
||||||
auto control = surface_control_.lock();
|
auto control = surface_control_.lock();
|
||||||
if (!control || !control->IsValid()) {
|
if (!control || !control->IsValid()) {
|
||||||
@ -163,9 +194,9 @@ bool AHBSwapchainImplVK::Present(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fence = SubmitSignalForPresentReady(texture);
|
auto present_ready = SubmitSignalForPresentReady(texture);
|
||||||
|
|
||||||
if (!fence) {
|
if (!present_ready) {
|
||||||
VALIDATION_LOG << "Could not submit completion signal.";
|
VALIDATION_LOG << "Could not submit completion signal.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -173,67 +204,70 @@ bool AHBSwapchainImplVK::Present(
|
|||||||
android::SurfaceTransaction transaction;
|
android::SurfaceTransaction transaction;
|
||||||
if (!transaction.SetContents(control.get(), //
|
if (!transaction.SetContents(control.get(), //
|
||||||
texture->GetBackingStore(), //
|
texture->GetBackingStore(), //
|
||||||
fence->CreateFD() //
|
present_ready->CreateFD() //
|
||||||
)) {
|
)) {
|
||||||
VALIDATION_LOG << "Could not set swapchain image contents on the surface "
|
VALIDATION_LOG << "Could not set swapchain image contents on the surface "
|
||||||
"control.";
|
"control.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return transaction.Apply([signaler, texture, weak = weak_from_this()](
|
return transaction.Apply(
|
||||||
ASurfaceTransactionStats* stats) {
|
[texture, weak = weak_from_this()](ASurfaceTransactionStats* stats) {
|
||||||
auto thiz = weak.lock();
|
auto thiz = weak.lock();
|
||||||
if (!thiz) {
|
if (!thiz) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
thiz->OnTextureUpdatedOnSurfaceControl(signaler, texture, stats);
|
thiz->OnTextureUpdatedOnSurfaceControl(texture, stats);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AHBSwapchainImplVK::AddFinalCommandBuffer(
|
void AHBSwapchainImplVK::AddFinalCommandBuffer(
|
||||||
std::shared_ptr<CommandBuffer> cmd_buffer) {
|
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(
|
AHBSwapchainImplVK::SubmitSignalForPresentReady(
|
||||||
const std::shared_ptr<AHBTextureSourceVK>& texture) const {
|
const std::shared_ptr<AHBTextureSourceVK>& texture) const {
|
||||||
auto context = transients_->GetContext().lock();
|
auto context = transients_->GetContext().lock();
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return nullptr;
|
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;
|
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) {
|
if (!command_buffer) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
CommandBufferVK& command_buffer_vk = CommandBufferVK::Cast(*command_buffer);
|
CommandBufferVK& command_buffer_vk = CommandBufferVK::Cast(*command_buffer);
|
||||||
const auto command_encoder_vk = command_buffer_vk.GetCommandBuffer();
|
const auto command_encoder_vk = command_buffer_vk.GetCommandBuffer();
|
||||||
command_buffer_vk.Track(fence->GetSharedHandle());
|
|
||||||
|
|
||||||
if (!command_buffer_vk.EndCommandBuffer()) {
|
if (!command_buffer_vk.EndCommandBuffer()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
sync->present_ready = present_ready;
|
||||||
|
|
||||||
vk::SubmitInfo submit_info;
|
vk::SubmitInfo submit_info;
|
||||||
vk::PipelineStageFlags wait_stage =
|
vk::PipelineStageFlags wait_stage =
|
||||||
vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||||
if (frame_data_[frame_index_].semaphore) {
|
if (sync->render_ready) {
|
||||||
submit_info.setPWaitSemaphores(&frame_data_[frame_index_].semaphore.get());
|
submit_info.setPWaitSemaphores(&sync->render_ready.get());
|
||||||
submit_info.setWaitSemaphoreCount(1);
|
submit_info.setWaitSemaphoreCount(1);
|
||||||
submit_info.setWaitDstStageMask(wait_stage);
|
submit_info.setWaitDstStageMask(wait_stage);
|
||||||
}
|
}
|
||||||
submit_info.setCommandBuffers(command_encoder_vk);
|
submit_info.setCommandBuffers(command_encoder_vk);
|
||||||
|
submit_info.setPSignalSemaphores(&sync->present_ready->GetHandle());
|
||||||
|
submit_info.setSignalSemaphoreCount(1);
|
||||||
|
|
||||||
auto result = ContextVK::Cast(*context).GetGraphicsQueue()->Submit(
|
auto result = ContextVK::Cast(*context).GetGraphicsQueue()->Submit(
|
||||||
submit_info, fence->GetHandle());
|
submit_info, *sync->acquire);
|
||||||
if (result != vk::Result::eSuccess) {
|
if (result != vk::Result::eSuccess) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return fence;
|
return present_ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
||||||
@ -251,7 +285,6 @@ vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
|||||||
const auto& device = context_vk.GetDevice();
|
const auto& device = context_vk.GetDevice();
|
||||||
|
|
||||||
auto signal_wait = device.createSemaphoreUnique({});
|
auto signal_wait = device.createSemaphoreUnique({});
|
||||||
|
|
||||||
if (signal_wait.result != vk::Result::eSuccess) {
|
if (signal_wait.result != vk::Result::eSuccess) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -282,33 +315,32 @@ vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
|
|||||||
return std::move(signal_wait.value);
|
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<fml::UniqueFD>& render_ready_fence,
|
||||||
const std::shared_ptr<AHBTextureSourceVK>& texture) {
|
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();
|
auto context = transients_->GetContext().lock();
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return false;
|
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);
|
auto semaphore = CreateRenderReadySemaphore(render_ready_fence);
|
||||||
if (!semaphore) {
|
if (!semaphore) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// This semaphore will be later used to block the onscreen render pass
|
// This semaphore will be later used to block the onscreen render pass
|
||||||
// from starting until the system is done reading the onscreen.
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AHBSwapchainImplVK::OnTextureUpdatedOnSurfaceControl(
|
void AHBSwapchainImplVK::OnTextureUpdatedOnSurfaceControl(
|
||||||
const AutoSemaSignaler& signaler,
|
|
||||||
std::shared_ptr<AHBTextureSourceVK> texture,
|
std::shared_ptr<AHBTextureSourceVK> texture,
|
||||||
ASurfaceTransactionStats* stats) {
|
ASurfaceTransactionStats* stats) {
|
||||||
auto control = surface_control_.lock();
|
auto control = surface_control_.lock();
|
||||||
|
@ -8,11 +8,10 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "flutter/fml/closure.h"
|
#include "flutter/fml/closure.h"
|
||||||
#include "flutter/fml/synchronization/semaphore.h"
|
|
||||||
#include "impeller/base/thread.h"
|
#include "impeller/base/thread.h"
|
||||||
#include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.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/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/backend/vulkan/swapchain/swapchain_transients_vk.h"
|
||||||
#include "impeller/renderer/surface.h"
|
#include "impeller/renderer/surface.h"
|
||||||
#include "impeller/toolkit/android/hardware_buffer.h"
|
#include "impeller/toolkit/android/hardware_buffer.h"
|
||||||
@ -21,6 +20,24 @@
|
|||||||
|
|
||||||
namespace impeller {
|
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
|
/// @brief The implementation of a swapchain at a specific size. Resizes to
|
||||||
/// the surface will cause the instance of the swapchain impl at
|
/// the surface will cause the instance of the swapchain impl at
|
||||||
@ -99,19 +116,14 @@ class AHBSwapchainImplVK final
|
|||||||
android::HardwareBufferDescriptor desc_;
|
android::HardwareBufferDescriptor desc_;
|
||||||
std::shared_ptr<AHBTexturePoolVK> pool_;
|
std::shared_ptr<AHBTexturePoolVK> pool_;
|
||||||
std::shared_ptr<SwapchainTransientsVK> transients_;
|
std::shared_ptr<SwapchainTransientsVK> transients_;
|
||||||
|
|
||||||
// In C++20, this mutex can be replaced by the shared pointer specialization
|
// In C++20, this mutex can be replaced by the shared pointer specialization
|
||||||
// of std::atomic.
|
// of std::atomic.
|
||||||
Mutex currently_displayed_texture_mutex_;
|
Mutex currently_displayed_texture_mutex_;
|
||||||
std::shared_ptr<AHBTextureSourceVK> currently_displayed_texture_
|
std::shared_ptr<AHBTextureSourceVK> currently_displayed_texture_
|
||||||
IPLR_GUARDED_BY(currently_displayed_texture_mutex_);
|
IPLR_GUARDED_BY(currently_displayed_texture_mutex_);
|
||||||
std::shared_ptr<fml::Semaphore> pending_presents_;
|
|
||||||
|
|
||||||
struct FrameData {
|
std::vector<std::unique_ptr<AHBFrameSynchronizerVK>> frame_data_;
|
||||||
std::shared_ptr<CommandBuffer> command_buffer;
|
|
||||||
vk::UniqueSemaphore semaphore;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<FrameData, 3> frame_data_;
|
|
||||||
size_t frame_index_ = 0;
|
size_t frame_index_ = 0;
|
||||||
bool is_valid_ = false;
|
bool is_valid_ = false;
|
||||||
|
|
||||||
@ -122,21 +134,19 @@ class AHBSwapchainImplVK final
|
|||||||
bool enable_msaa,
|
bool enable_msaa,
|
||||||
size_t swapchain_image_count);
|
size_t swapchain_image_count);
|
||||||
|
|
||||||
bool Present(const AutoSemaSignaler& signaler,
|
bool Present(const std::shared_ptr<AHBTextureSourceVK>& texture);
|
||||||
const std::shared_ptr<AHBTextureSourceVK>& texture);
|
|
||||||
|
|
||||||
vk::UniqueSemaphore CreateRenderReadySemaphore(
|
vk::UniqueSemaphore CreateRenderReadySemaphore(
|
||||||
const std::shared_ptr<fml::UniqueFD>& fd) const;
|
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<fml::UniqueFD>& render_ready_fence,
|
||||||
const std::shared_ptr<AHBTextureSourceVK>& texture);
|
const std::shared_ptr<AHBTextureSourceVK>& texture);
|
||||||
|
|
||||||
std::shared_ptr<ExternalFenceVK> SubmitSignalForPresentReady(
|
std::shared_ptr<ExternalSemaphoreVK> SubmitSignalForPresentReady(
|
||||||
const std::shared_ptr<AHBTextureSourceVK>& texture) const;
|
const std::shared_ptr<AHBTextureSourceVK>& texture) const;
|
||||||
|
|
||||||
void OnTextureUpdatedOnSurfaceControl(
|
void OnTextureUpdatedOnSurfaceControl(
|
||||||
const AutoSemaSignaler& signaler,
|
|
||||||
std::shared_ptr<AHBTextureSourceVK> texture,
|
std::shared_ptr<AHBTextureSourceVK> texture,
|
||||||
ASurfaceTransactionStats* stats);
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef 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_FENCE_VK_H_
|
#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_EXTERNAL_SEMAPHORE_VK_H_
|
||||||
|
|
||||||
#include "flutter/fml/unique_fd.h"
|
#include "flutter/fml/unique_fd.h"
|
||||||
#include "impeller/renderer/backend/vulkan/shared_object_vk.h"
|
#include "impeller/renderer/backend/vulkan/shared_object_vk.h"
|
||||||
#include "impeller/renderer/backend/vulkan/vk.h"
|
#include "impeller/renderer/backend/vulkan/vk.h"
|
||||||
#include "impeller/renderer/context.h"
|
#include "impeller/renderer/context.h"
|
||||||
|
#include "vulkan/vulkan_handles.hpp"
|
||||||
|
|
||||||
namespace impeller {
|
namespace impeller {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/// @brief A Vulkan fence that can be exported as a platform specific file
|
/// @brief A Vulkan semaphore that can be exported as a platform specific
|
||||||
/// descriptor.
|
/// 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
|
/// @warning Only semaphore that have been signaled or have a single
|
||||||
/// pending can be exported. Make sure to submit a fence signalling
|
/// operation pending can be exported. Make sure to submit a fence
|
||||||
/// operation to a queue before attempted to obtain a file
|
/// signalling operation to a queue before attempted to obtain a
|
||||||
/// descriptor for the fence. See
|
/// file descriptor for the fence.
|
||||||
/// VUID-VkFenceGetFdInfoKHR-handleType-01454 for additional details
|
|
||||||
/// on the implementation.
|
|
||||||
///
|
///
|
||||||
class ExternalFenceVK {
|
class ExternalSemaphoreVK {
|
||||||
public:
|
public:
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
/// @brief Create a new un-signaled fence that can be exported as a sync
|
/// @brief Create a new un-signaled semaphore that can be exported as a
|
||||||
/// file descriptor.
|
/// sync file descriptor.
|
||||||
///
|
///
|
||||||
/// @param[in] context The device context.
|
/// @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.
|
/// @brief If a valid fence could be created.
|
||||||
@ -49,16 +48,18 @@ class ExternalFenceVK {
|
|||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
/// @brief Create a new sync file descriptor for the underlying fence.
|
/// @brief Create a new sync file descriptor for the underlying
|
||||||
/// The fence must already be signaled or have a signal operation
|
/// semaphore.
|
||||||
/// pending in a queue. There are no checks for this in the
|
///
|
||||||
/// implementation and only Vulkan validation will catch such a
|
/// The semaphore must already be signaled or have a signal
|
||||||
/// misuse and undefined behavior.
|
/// 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
|
/// @warning Implementations are also allowed to return invalid file
|
||||||
/// descriptors in case a fence has already been signaled. So it
|
/// descriptors in case a semaphore has already been signaled. So
|
||||||
/// is not necessary an error to obtain an invalid descriptor from
|
/// it is not necessary an error to obtain an invalid descriptor
|
||||||
/// this call. For APIs that are meant to consume such
|
/// from this call. For APIs that are meant to consume such
|
||||||
/// descriptors, pass -1 as the file handle.
|
/// descriptors, pass -1 as the file handle.
|
||||||
///
|
///
|
||||||
/// Since this call can return an invalid FD even in case of
|
/// Since this call can return an invalid FD even in case of
|
||||||
@ -70,14 +71,14 @@ class ExternalFenceVK {
|
|||||||
///
|
///
|
||||||
fml::UniqueFD CreateFD() const;
|
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:
|
private:
|
||||||
SharedHandleVK<vk::Fence> fence_;
|
SharedHandleVK<vk::Semaphore> semaphore_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace impeller
|
} // 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