[Impeller] protect onscreen cmd buffer with render ready semaphore. (#161140)
Ensures that the onscreen command buffer is blocked via the render ready semaphore, instead of just the layout transition. I can confirm this fixes the rendering artifacts on the Samsung a50 - which I suspect are the same as the issues these other devices are having. Essentially, without the semaphore protecting the onscreen pass we can end up writing to the color attachment while it is still being read. * https://github.com/flutter/flutter/issues/160522 * https://github.com/flutter/flutter/issues/160370
This commit is contained in:
parent
a9b3f6c042
commit
ffc7ced2a0
@ -50,14 +50,14 @@ bool AiksPlayground::OpenPlaygroundHere(
|
||||
|
||||
return Playground::OpenPlaygroundHere(
|
||||
[&renderer, &callback](RenderTarget& render_target) -> bool {
|
||||
return RenderToOnscreen(
|
||||
return RenderToTarget(
|
||||
renderer.GetContentContext(), //
|
||||
render_target, //
|
||||
callback(), //
|
||||
SkIRect::MakeWH(render_target.GetRenderTargetSize().width,
|
||||
render_target.GetRenderTargetSize().height), //
|
||||
/*reset_host_buffer=*/true //
|
||||
);
|
||||
/*reset_host_buffer=*/true, //
|
||||
/*is_onscreen=*/false);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "impeller/geometry/color.h"
|
||||
#include "impeller/geometry/constants.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
#include "impeller/renderer/command_buffer.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@ -162,9 +163,11 @@ static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
|
||||
|
||||
Canvas::Canvas(ContentContext& renderer,
|
||||
const RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool requires_readback)
|
||||
: renderer_(renderer),
|
||||
render_target_(render_target),
|
||||
is_onscreen_(is_onscreen),
|
||||
requires_readback_(requires_readback),
|
||||
clip_coverage_stack_(EntityPassClipStack(
|
||||
Rect::MakeSize(render_target.GetRenderTargetSize()))) {
|
||||
@ -174,10 +177,12 @@ Canvas::Canvas(ContentContext& renderer,
|
||||
|
||||
Canvas::Canvas(ContentContext& renderer,
|
||||
const RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool requires_readback,
|
||||
Rect cull_rect)
|
||||
: renderer_(renderer),
|
||||
render_target_(render_target),
|
||||
is_onscreen_(is_onscreen),
|
||||
requires_readback_(requires_readback),
|
||||
clip_coverage_stack_(EntityPassClipStack(
|
||||
Rect::MakeSize(render_target.GetRenderTargetSize()))) {
|
||||
@ -187,10 +192,12 @@ Canvas::Canvas(ContentContext& renderer,
|
||||
|
||||
Canvas::Canvas(ContentContext& renderer,
|
||||
const RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool requires_readback,
|
||||
IRect cull_rect)
|
||||
: renderer_(renderer),
|
||||
render_target_(render_target),
|
||||
is_onscreen_(is_onscreen),
|
||||
requires_readback_(requires_readback),
|
||||
clip_coverage_stack_(EntityPassClipStack(
|
||||
Rect::MakeSize(render_target.GetRenderTargetSize()))) {
|
||||
@ -1658,7 +1665,7 @@ std::shared_ptr<Texture> Canvas::FlipBackdrop(Point global_pass_position,
|
||||
return input_texture;
|
||||
}
|
||||
|
||||
bool Canvas::BlitToOnscreen() {
|
||||
bool Canvas::BlitToOnscreen(bool is_onscreen) {
|
||||
auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
|
||||
command_buffer->SetLabel("EntityPass Root Command Buffer");
|
||||
auto offscreen_target = render_passes_.back()
|
||||
@ -1675,10 +1682,6 @@ bool Canvas::BlitToOnscreen() {
|
||||
VALIDATION_LOG << "Failed to encode root pass blit command.";
|
||||
return false;
|
||||
}
|
||||
if (!renderer_.GetContext()->EnqueueCommandBuffer(
|
||||
std::move(command_buffer))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto render_pass = command_buffer->CreateRenderPass(render_target_);
|
||||
render_pass->SetLabel("EntityPass Root Render Pass");
|
||||
@ -1704,25 +1707,28 @@ bool Canvas::BlitToOnscreen() {
|
||||
VALIDATION_LOG << "Failed to encode root pass command buffer.";
|
||||
return false;
|
||||
}
|
||||
if (!renderer_.GetContext()->EnqueueCommandBuffer(
|
||||
std::move(command_buffer))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_onscreen) {
|
||||
return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
|
||||
} else {
|
||||
return renderer_.GetContext()->EnqueueCommandBuffer(
|
||||
std::move(command_buffer));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Canvas::EndReplay() {
|
||||
FML_DCHECK(render_passes_.size() == 1u);
|
||||
render_passes_.back().inline_pass_context->GetRenderPass();
|
||||
render_passes_.back().inline_pass_context->EndPass();
|
||||
render_passes_.back().inline_pass_context->EndPass(
|
||||
/*is_onscreen=*/!requires_readback_ && is_onscreen_);
|
||||
backdrop_data_.clear();
|
||||
|
||||
// If requires_readback_ was true, then we rendered to an offscreen texture
|
||||
// instead of to the onscreen provided in the render target. Now we need to
|
||||
// draw or blit the offscreen back to the onscreen.
|
||||
if (requires_readback_) {
|
||||
BlitToOnscreen();
|
||||
BlitToOnscreen(/*is_onscreen_=*/is_onscreen_);
|
||||
}
|
||||
|
||||
if (!renderer_.GetContext()->FlushCommandBuffers()) {
|
||||
|
@ -123,15 +123,18 @@ class Canvas {
|
||||
|
||||
Canvas(ContentContext& renderer,
|
||||
const RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool requires_readback);
|
||||
|
||||
explicit Canvas(ContentContext& renderer,
|
||||
const RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool requires_readback,
|
||||
Rect cull_rect);
|
||||
|
||||
explicit Canvas(ContentContext& renderer,
|
||||
const RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool requires_readback,
|
||||
IRect cull_rect);
|
||||
|
||||
@ -251,6 +254,7 @@ class Canvas {
|
||||
private:
|
||||
ContentContext& renderer_;
|
||||
RenderTarget render_target_;
|
||||
const bool is_onscreen_;
|
||||
bool requires_readback_;
|
||||
EntityPassClipStack clip_coverage_stack_;
|
||||
|
||||
@ -318,7 +322,7 @@ class Canvas {
|
||||
bool should_remove_texture = false,
|
||||
bool should_use_onscreen = false);
|
||||
|
||||
bool BlitToOnscreen();
|
||||
bool BlitToOnscreen(bool is_onscreen = false);
|
||||
|
||||
size_t GetClipHeight() const;
|
||||
|
||||
|
@ -56,10 +56,12 @@ std::unique_ptr<Canvas> CreateTestCanvas(
|
||||
render_target.SetColorAttachment(color0, 0);
|
||||
|
||||
if (cull_rect.has_value()) {
|
||||
return std::make_unique<Canvas>(context, render_target, requires_readback,
|
||||
cull_rect.value());
|
||||
return std::make_unique<Canvas>(
|
||||
context, render_target, /*is_onscreen=*/false,
|
||||
/*requires_readback=*/requires_readback, cull_rect.value());
|
||||
}
|
||||
return std::make_unique<Canvas>(context, render_target, requires_readback);
|
||||
return std::make_unique<Canvas>(context, render_target, /*is_onscreen=*/false,
|
||||
/*requires_readback=*/requires_readback);
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, TransformMultipliesCorrectly) {
|
||||
|
@ -947,11 +947,13 @@ static bool RequiresReadbackForBlends(
|
||||
|
||||
CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer,
|
||||
RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool has_root_backdrop_filter,
|
||||
flutter::DlBlendMode max_root_blend_mode,
|
||||
IRect cull_rect)
|
||||
: canvas_(renderer,
|
||||
render_target,
|
||||
is_onscreen,
|
||||
has_root_backdrop_filter ||
|
||||
RequiresReadbackForBlends(renderer, max_root_blend_mode),
|
||||
cull_rect),
|
||||
@ -1270,6 +1272,7 @@ std::shared_ptr<Texture> DisplayListToTexture(
|
||||
impeller::CanvasDlDispatcher impeller_dispatcher(
|
||||
context.GetContentContext(), //
|
||||
target, //
|
||||
/*is_onscreen=*/false, //
|
||||
display_list->root_has_backdrop_filter(), //
|
||||
display_list->max_root_blend_mode(), //
|
||||
impeller::IRect::MakeSize(size) //
|
||||
@ -1288,11 +1291,12 @@ std::shared_ptr<Texture> DisplayListToTexture(
|
||||
return target.GetRenderTargetTexture();
|
||||
}
|
||||
|
||||
bool RenderToOnscreen(ContentContext& context,
|
||||
bool RenderToTarget(ContentContext& context,
|
||||
RenderTarget render_target,
|
||||
const sk_sp<flutter::DisplayList>& display_list,
|
||||
SkIRect cull_rect,
|
||||
bool reset_host_buffer) {
|
||||
bool reset_host_buffer,
|
||||
bool is_onscreen) {
|
||||
Rect ip_cull_rect = Rect::MakeLTRB(cull_rect.left(), cull_rect.top(),
|
||||
cull_rect.right(), cull_rect.bottom());
|
||||
FirstPassDispatcher collector(context, impeller::Matrix(), ip_cull_rect);
|
||||
@ -1301,6 +1305,7 @@ bool RenderToOnscreen(ContentContext& context,
|
||||
impeller::CanvasDlDispatcher impeller_dispatcher(
|
||||
context, //
|
||||
render_target, //
|
||||
/*is_onscreen=*/is_onscreen, //
|
||||
display_list->root_has_backdrop_filter(), //
|
||||
display_list->max_root_blend_mode(), //
|
||||
IRect::RoundOut(ip_cull_rect) //
|
||||
|
@ -254,6 +254,7 @@ class CanvasDlDispatcher : public DlDispatcherBase {
|
||||
public:
|
||||
CanvasDlDispatcher(ContentContext& renderer,
|
||||
RenderTarget& render_target,
|
||||
bool is_onscreen,
|
||||
bool has_root_backdrop_filter,
|
||||
flutter::DlBlendMode max_root_blend_mode,
|
||||
IRect cull_rect);
|
||||
@ -390,11 +391,15 @@ std::shared_ptr<Texture> DisplayListToTexture(
|
||||
bool reset_host_buffer = true,
|
||||
bool generate_mips = false);
|
||||
|
||||
/// Render the provided display list to the render target.
|
||||
bool RenderToOnscreen(ContentContext& context, RenderTarget render_target,
|
||||
/// @brief Render the provided display list to the render target.
|
||||
///
|
||||
/// If [is_onscreen] is true, then the onscreen command buffer will be
|
||||
/// submitted via Context::SubmitOnscreen.
|
||||
bool RenderToTarget(ContentContext& context, RenderTarget render_target,
|
||||
const sk_sp<flutter::DisplayList>& display_list,
|
||||
SkIRect cull_rect,
|
||||
bool reset_host_buffer);
|
||||
bool reset_host_buffer,
|
||||
bool is_onscreen = true);
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
|
@ -45,13 +45,14 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) {
|
||||
wireframe = !wireframe;
|
||||
context.GetContentContext().SetWireframe(wireframe);
|
||||
}
|
||||
return RenderToOnscreen(
|
||||
return RenderToTarget(
|
||||
context.GetContentContext(), //
|
||||
render_target, //
|
||||
callback(), //
|
||||
SkIRect::MakeWH(render_target.GetRenderTargetSize().width,
|
||||
render_target.GetRenderTargetSize().height), //
|
||||
/*reset_host_buffer=*/true //
|
||||
/*reset_host_buffer=*/true, //
|
||||
/*is_onscreen=*/false //
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ std::shared_ptr<Texture> InlinePassContext::GetTexture() {
|
||||
return pass_target_.GetRenderTarget().GetRenderTargetTexture();
|
||||
}
|
||||
|
||||
bool InlinePassContext::EndPass() {
|
||||
bool InlinePassContext::EndPass(bool is_onscreen) {
|
||||
if (!IsActive()) {
|
||||
return true;
|
||||
}
|
||||
@ -63,8 +63,12 @@ bool InlinePassContext::EndPass() {
|
||||
}
|
||||
|
||||
pass_ = nullptr;
|
||||
if (is_onscreen) {
|
||||
return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer_));
|
||||
} else {
|
||||
return renderer_.GetContext()->EnqueueCommandBuffer(
|
||||
std::move(command_buffer_));
|
||||
}
|
||||
}
|
||||
|
||||
EntityPassTarget& InlinePassContext::GetPassTarget() const {
|
||||
|
@ -27,7 +27,7 @@ class InlinePassContext {
|
||||
|
||||
std::shared_ptr<Texture> GetTexture();
|
||||
|
||||
bool EndPass();
|
||||
bool EndPass(bool is_onscreen = false);
|
||||
|
||||
EntityPassTarget& GetPassTarget() const;
|
||||
|
||||
|
@ -657,6 +657,10 @@ bool ContextVK::EnqueueCommandBuffer(
|
||||
}
|
||||
|
||||
bool ContextVK::FlushCommandBuffers() {
|
||||
if (pending_command_buffers_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (should_batch_cmd_buffers_) {
|
||||
bool result = GetCommandQueue()->Submit(pending_command_buffers_).ok();
|
||||
pending_command_buffers_.clear();
|
||||
@ -733,4 +737,8 @@ RuntimeStageBackend ContextVK::GetRuntimeStageBackend() const {
|
||||
return RuntimeStageBackend::kVulkan;
|
||||
}
|
||||
|
||||
bool ContextVK::SubmitOnscreen(std::shared_ptr<CommandBuffer> cmd_buffer) {
|
||||
return EnqueueCommandBuffer(std::move(cmd_buffer));
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
@ -131,6 +131,10 @@ class ContextVK final : public Context,
|
||||
// |Context|
|
||||
const std::shared_ptr<const Capabilities>& GetCapabilities() const override;
|
||||
|
||||
// |Context|
|
||||
virtual bool SubmitOnscreen(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) override;
|
||||
|
||||
const std::shared_ptr<YUVConversionLibraryVK>& GetYUVConversionLibrary()
|
||||
const;
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "impeller/core/formats.h"
|
||||
#include "impeller/renderer/backend/vulkan/formats_vk.h"
|
||||
#include "vulkan/vulkan_enums.hpp"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "impeller/core/formats.h"
|
||||
#include "impeller/core/texture.h"
|
||||
#include "impeller/core/vertex_buffer.h"
|
||||
#include "impeller/renderer/backend/vulkan/barrier_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
|
||||
@ -82,14 +81,16 @@ SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
|
||||
const std::shared_ptr<CommandBufferVK>& command_buffer) const {
|
||||
RenderPassBuilderVK builder;
|
||||
|
||||
render_target_.IterateAllColorAttachments(
|
||||
[&](size_t bind_point, const ColorAttachment& attachment) -> bool {
|
||||
render_target_.IterateAllColorAttachments([&](size_t bind_point,
|
||||
const ColorAttachment&
|
||||
attachment) -> bool {
|
||||
builder.SetColorAttachment(
|
||||
bind_point, //
|
||||
attachment.texture->GetTextureDescriptor().format, //
|
||||
attachment.texture->GetTextureDescriptor().sample_count, //
|
||||
attachment.load_action, //
|
||||
attachment.store_action //
|
||||
attachment.store_action, //
|
||||
/*current_layout=*/TextureVK::Cast(*attachment.texture).GetLayout() //
|
||||
);
|
||||
return true;
|
||||
});
|
||||
@ -179,6 +180,8 @@ RenderPassVK::RenderPassVK(const std::shared_ptr<const Context>& context,
|
||||
if (resolve_image_vk_) {
|
||||
TextureVK::Cast(*resolve_image_vk_).SetCachedFramebuffer(framebuffer);
|
||||
TextureVK::Cast(*resolve_image_vk_).SetCachedRenderPass(render_pass_);
|
||||
TextureVK::Cast(*resolve_image_vk_)
|
||||
.SetLayoutWithoutEncoding(vk::ImageLayout::eGeneral);
|
||||
}
|
||||
|
||||
std::array<vk::ClearValue, kMaxAttachments> clears;
|
||||
|
@ -129,6 +129,12 @@ bool SurfaceContextVK::FlushCommandBuffers() {
|
||||
return parent_->FlushCommandBuffers();
|
||||
}
|
||||
|
||||
bool SurfaceContextVK::SubmitOnscreen(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) {
|
||||
swapchain_->AddFinalCommandBuffer(std::move(cmd_buffer));
|
||||
return true;
|
||||
}
|
||||
|
||||
RuntimeStageBackend SurfaceContextVK::GetRuntimeStageBackend() const {
|
||||
return parent_->GetRuntimeStageBackend();
|
||||
}
|
||||
|
@ -73,6 +73,9 @@ class SurfaceContextVK : public Context,
|
||||
// |Context|
|
||||
RuntimeStageBackend GetRuntimeStageBackend() const override;
|
||||
|
||||
// |Context|
|
||||
bool SubmitOnscreen(std::shared_ptr<CommandBuffer> cmd_buffer) override;
|
||||
|
||||
// |Context|
|
||||
void Shutdown() override;
|
||||
|
||||
|
@ -192,6 +192,12 @@ bool AHBSwapchainImplVK::Present(
|
||||
});
|
||||
}
|
||||
|
||||
void AHBSwapchainImplVK::AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) {
|
||||
FML_DCHECK(!pending_cmd_buffer_);
|
||||
pending_cmd_buffer_ = std::move(cmd_buffer);
|
||||
}
|
||||
|
||||
std::shared_ptr<ExternalFenceVK>
|
||||
AHBSwapchainImplVK::SubmitSignalForPresentReady(
|
||||
const std::shared_ptr<AHBTextureSourceVK>& texture) const {
|
||||
@ -204,7 +210,7 @@ AHBSwapchainImplVK::SubmitSignalForPresentReady(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto command_buffer = context->CreateCommandBuffer();
|
||||
auto command_buffer = pending_cmd_buffer_;
|
||||
if (!command_buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ class AHBSwapchainImplVK final
|
||||
///
|
||||
std::unique_ptr<Surface> AcquireNextDrawable();
|
||||
|
||||
void AddFinalCommandBuffer(std::shared_ptr<CommandBuffer> cmd_buffer);
|
||||
|
||||
private:
|
||||
using AutoSemaSignaler = std::shared_ptr<fml::ScopedCleanupClosure>;
|
||||
|
||||
@ -102,6 +104,7 @@ class AHBSwapchainImplVK final
|
||||
std::shared_ptr<AHBTextureSourceVK> currently_displayed_texture_
|
||||
IPLR_GUARDED_BY(currently_displayed_texture_mutex_);
|
||||
std::shared_ptr<fml::Semaphore> pending_presents_;
|
||||
std::shared_ptr<CommandBuffer> pending_cmd_buffer_;
|
||||
bool is_valid_ = false;
|
||||
|
||||
explicit AHBSwapchainImplVK(
|
||||
|
@ -66,6 +66,12 @@ vk::Format AHBSwapchainVK::GetSurfaceFormat() const {
|
||||
: vk::Format::eUndefined;
|
||||
}
|
||||
|
||||
// |SwapchainVK|
|
||||
void AHBSwapchainVK::AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) const {
|
||||
return impl_->AddFinalCommandBuffer(cmd_buffer);
|
||||
}
|
||||
|
||||
// |SwapchainVK|
|
||||
void AHBSwapchainVK::UpdateSurfaceSize(const ISize& size) {
|
||||
if (impl_ && impl_->GetSize() == size) {
|
||||
|
@ -46,6 +46,10 @@ class AHBSwapchainVK final : public SwapchainVK {
|
||||
// |SwapchainVK|
|
||||
void UpdateSurfaceSize(const ISize& size) override;
|
||||
|
||||
// |SwapchainVK|
|
||||
void AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) const override;
|
||||
|
||||
private:
|
||||
friend class SwapchainVK;
|
||||
|
||||
|
@ -13,11 +13,12 @@
|
||||
#include "impeller/renderer/backend/vulkan/gpu_tracer_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/surface_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/texture_vk.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
static constexpr size_t kMaxFramesInFlight = 3u;
|
||||
static constexpr size_t kMaxFramesInFlight = 2u;
|
||||
|
||||
struct KHRFrameSynchronizerVK {
|
||||
vk::UniqueFence acquire;
|
||||
@ -25,6 +26,8 @@ struct KHRFrameSynchronizerVK {
|
||||
vk::UniqueSemaphore present_ready;
|
||||
std::shared_ptr<CommandBuffer> final_cmd_buffer;
|
||||
bool is_valid = false;
|
||||
// Whether the renderer attached an onscreen command buffer to render to.
|
||||
bool has_onscreen = false;
|
||||
|
||||
explicit KHRFrameSynchronizerVK(const vk::Device& device) {
|
||||
auto acquire_res = device.createFenceUnique(
|
||||
@ -378,6 +381,13 @@ KHRSwapchainImplVK::AcquireResult KHRSwapchainImplVK::AcquireNextDrawable() {
|
||||
)};
|
||||
}
|
||||
|
||||
void KHRSwapchainImplVK::AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) {
|
||||
const auto& sync = synchronizers_[current_frame_];
|
||||
sync->final_cmd_buffer = std::move(cmd_buffer);
|
||||
sync->has_onscreen = true;
|
||||
}
|
||||
|
||||
bool KHRSwapchainImplVK::Present(
|
||||
const std::shared_ptr<KHRSwapchainImageVK>& image,
|
||||
uint32_t index) {
|
||||
@ -393,7 +403,10 @@ bool KHRSwapchainImplVK::Present(
|
||||
//----------------------------------------------------------------------------
|
||||
/// Transition the image to color-attachment-optimal.
|
||||
///
|
||||
if (!sync->has_onscreen) {
|
||||
sync->final_cmd_buffer = context.CreateCommandBuffer();
|
||||
}
|
||||
sync->has_onscreen = false;
|
||||
if (!sync->final_cmd_buffer) {
|
||||
return false;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
#include "impeller/geometry/size.h"
|
||||
#include "impeller/renderer/backend/vulkan/swapchain/swapchain_transients_vk.h"
|
||||
@ -63,6 +62,8 @@ class KHRSwapchainImplVK final
|
||||
|
||||
const ISize& GetSize() const;
|
||||
|
||||
void AddFinalCommandBuffer(std::shared_ptr<CommandBuffer> cmd_buffer);
|
||||
|
||||
private:
|
||||
std::weak_ptr<Context> context_;
|
||||
vk::UniqueSurfaceKHR surface_;
|
||||
|
@ -39,6 +39,11 @@ void KHRSwapchainVK::UpdateSurfaceSize(const ISize& size) {
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
void KHRSwapchainVK::AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) const {
|
||||
impl_->AddFinalCommandBuffer(std::move(cmd_buffer));
|
||||
}
|
||||
|
||||
std::unique_ptr<Surface> KHRSwapchainVK::AcquireNextDrawable() {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
|
@ -37,6 +37,10 @@ class KHRSwapchainVK final : public SwapchainVK {
|
||||
// |SwapchainVK|
|
||||
void UpdateSurfaceSize(const ISize& size) override;
|
||||
|
||||
// |SwapchainVK|
|
||||
void AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) const override;
|
||||
|
||||
private:
|
||||
friend class SwapchainVK;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "flutter/fml/build_config.h"
|
||||
#include "impeller/geometry/size.h"
|
||||
#include "impeller/renderer/backend/vulkan/vk.h"
|
||||
#include "impeller/renderer/command_buffer.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/renderer/surface.h"
|
||||
|
||||
@ -52,6 +53,9 @@ class SwapchainVK {
|
||||
|
||||
virtual vk::Format GetSurfaceFormat() const = 0;
|
||||
|
||||
virtual void AddFinalCommandBuffer(
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer) const = 0;
|
||||
|
||||
/// @brief Mark the current swapchain configuration as dirty, forcing it to be
|
||||
/// recreated on the next frame.
|
||||
virtual void UpdateSurfaceSize(const ISize& size) = 0;
|
||||
|
@ -37,4 +37,8 @@ bool Context::AddTrackingFence(const std::shared_ptr<Texture>& texture) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Context::SubmitOnscreen(std::shared_ptr<CommandBuffer> cmd_buffer) {
|
||||
return EnqueueCommandBuffer(std::move(cmd_buffer));
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
@ -242,6 +242,9 @@ class Context {
|
||||
/// correct shader types.
|
||||
virtual RuntimeStageBackend GetRuntimeStageBackend() const = 0;
|
||||
|
||||
/// @brief Submit the command buffer that renders to the onscreen surface.
|
||||
virtual bool SubmitOnscreen(std::shared_ptr<CommandBuffer> cmd_buffer);
|
||||
|
||||
protected:
|
||||
Context();
|
||||
|
||||
|
@ -62,7 +62,7 @@ bool Surface::DrawDisplayList(const DisplayList& dl) const {
|
||||
auto skia_cull_rect =
|
||||
SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight());
|
||||
|
||||
auto result = RenderToOnscreen(content_context, render_target, display_list,
|
||||
auto result = RenderToTarget(content_context, render_target, display_list,
|
||||
skia_cull_rect, /*reset_host_buffer=*/true);
|
||||
context_->GetContext()->ResetThreadLocalState();
|
||||
return result;
|
||||
|
@ -116,7 +116,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGLImpeller::AcquireFrame(
|
||||
|
||||
auto cull_rect = render_target.GetRenderTargetSize();
|
||||
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.width, cull_rect.height);
|
||||
return impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||
return impeller::RenderToTarget(aiks_context->GetContentContext(), //
|
||||
render_target, //
|
||||
display_list, //
|
||||
sk_cull_rect, //
|
||||
|
@ -169,7 +169,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLa
|
||||
surface->SetFrameBoundary(surface_frame.submit_info().frame_boundary);
|
||||
|
||||
const bool reset_host_buffer = surface_frame.submit_info().frame_boundary;
|
||||
auto render_result = impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||
auto render_result = impeller::RenderToTarget(aiks_context->GetContentContext(), //
|
||||
surface->GetRenderTarget(), //
|
||||
display_list, //
|
||||
sk_cull_rect, //
|
||||
@ -283,7 +283,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTextur
|
||||
|
||||
impeller::IRect cull_rect = surface->coverage();
|
||||
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight());
|
||||
auto render_result = impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||
auto render_result = impeller::RenderToTarget(aiks_context->GetContentContext(), //
|
||||
surface->GetRenderTarget(), //
|
||||
display_list, //
|
||||
sk_cull_rect, //
|
||||
|
@ -115,7 +115,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
|
||||
}
|
||||
|
||||
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.width, cull_rect.height);
|
||||
return impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||
return impeller::RenderToTarget(aiks_context->GetContentContext(), //
|
||||
render_target, //
|
||||
display_list, //
|
||||
sk_cull_rect, //
|
||||
@ -212,7 +212,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
|
||||
}
|
||||
|
||||
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.width, cull_rect.height);
|
||||
return impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||
return impeller::RenderToTarget(aiks_context->GetContentContext(), //
|
||||
render_target, //
|
||||
display_list, //
|
||||
sk_cull_rect, //
|
||||
|
@ -133,11 +133,12 @@ bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target,
|
||||
SkIRect sk_cull_rect =
|
||||
SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight());
|
||||
|
||||
return impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||
return impeller::RenderToTarget(aiks_context->GetContentContext(), //
|
||||
*impeller_target, //
|
||||
display_list, //
|
||||
sk_cull_rect, //
|
||||
/*reset_host_buffer=*/true //
|
||||
/*reset_host_buffer=*/true, //
|
||||
/*is_onscreen=*/false //
|
||||
);
|
||||
}
|
||||
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||
|
Loading…
x
Reference in New Issue
Block a user