Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "impeller/renderer/backend/vulkan/queue_vk.h"
#include "impeller/renderer/backend/vulkan/sampler_library_vk.h"
#include "impeller/renderer/backend/vulkan/shader_library_vk.h"
#include "impeller/renderer/backend/vulkan/shared_object_vk.h"
#include "impeller/renderer/capabilities.h"
#include "impeller/renderer/context.h"

Expand All @@ -31,6 +32,71 @@ class FenceWaiterVK;
class ResourceManagerVK;
class SurfaceContextVK;

/// @brief Ring buffer for one writer thread and one reader thread.
template <typename T>
class RingBuffer {
public:
RingBuffer(int32_t size) : read_(0), write_(0), buffer_(size) {}

std::optional<T> Read() {
int32_t current_read = read_.load();
if (current_read == write_.load()) {
return {};
} else {
int32_t next_read = (current_read + 1) % buffer_.size();
read_.store(next_read);
return buffer_[current_read];
}
}

bool Write(const T& value) {
int32_t current_write = write_.load();
int32_t next_write = (current_write + 1) % buffer_.size();
if (next_write == read_.load()) { // Buffer full
return false;
}
buffer_[current_write] = value;
write_.store(next_write);
return true;
}

private:
std::atomic<int32_t> read_;
std::atomic<int32_t> write_;
std::vector<T> buffer_;
};

template <typename T>
class RingBufferItem : public SharedObjectVK {
public:
RingBufferItem(std::weak_ptr<const ContextVK> context,
RingBuffer<T>* ring_buffer,
std::optional<T> value)
: context_(context), ring_buffer_(ring_buffer), value_(value) {}

virtual ~RingBufferItem() {
auto context = context_.lock();
if (value_ && context) {
bool did_write = ring_buffer_->Write(value_.value());
FML_CHECK(did_write);
}
}

std::optional<T>& GetValue() { return value_; }

private:
FML_DISALLOW_COPY_AND_ASSIGN(RingBufferItem<T>);

std::weak_ptr<const ContextVK> context_;
RingBuffer<T>* ring_buffer_;
std::optional<T> value_;
};

struct RenderPassFrameBufferPair {
SharedHandleVK<vk::RenderPass> render_pass;
SharedHandleVK<vk::Framebuffer> framebuffer;
};

class ContextVK final : public Context,
public BackendCast<ContextVK, Context>,
public std::enable_shared_from_this<ContextVK> {
Expand Down Expand Up @@ -135,6 +201,12 @@ class ContextVK final : public Context,

std::shared_ptr<ResourceManagerVK> GetResourceManager() const;

std::shared_ptr<RingBufferItem<RenderPassFrameBufferPair>>
GetRenderPassFrameBufferPair() const {
return std::make_shared<RingBufferItem<RenderPassFrameBufferPair>>(
shared_from_this(), &render_pass_pool_, render_pass_pool_.Read());
}

private:
struct DeviceHolderImpl : public DeviceHolder {
// |DeviceHolder|
Expand Down Expand Up @@ -162,6 +234,8 @@ class ContextVK final : public Context,
std::string device_name_;
std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
const uint64_t hash_;
mutable RingBuffer<RenderPassFrameBufferPair> render_pass_pool_ =
RingBuffer<RenderPassFrameBufferPair>(10);

bool is_valid_ = false;

Expand Down
111 changes: 88 additions & 23 deletions impeller/renderer/backend/vulkan/render_pass_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ static void SetTextureLayout(
return;
}
const auto& texture_vk = TextureVK::Cast(*texture);
auto current_layout = texture_vk.GetLayout();

if (attachment_desc.initialLayout == vk::ImageLayout::eGeneral) {
if (current_layout != vk::ImageLayout::ePresentSrcKHR &&
current_layout != vk::ImageLayout::eUndefined) {
BarrierVK barrier;
barrier.new_layout = vk::ImageLayout::eGeneral;
barrier.cmd_buffer = command_buffer->GetEncoder()->GetCommandBuffer();
Expand All @@ -97,9 +99,41 @@ static void SetTextureLayout(
texture_vk.SetLayoutWithoutEncoding(attachment_desc.finalLayout);
}

namespace {
void SetTextureLayouts(const RenderTarget& render_target,
const std::shared_ptr<CommandBufferVK>& command_buffer) {
for (const auto& [bind_point, color] : render_target.GetColorAttachments()) {
SetTextureLayout(color,
CreateAttachmentDescription(color, &Attachment::texture),
command_buffer, &Attachment::texture);
if (color.resolve_texture) {
SetTextureLayout(
color,
CreateAttachmentDescription(color, &Attachment::resolve_texture),
command_buffer, &Attachment::resolve_texture);
}
}

if (auto depth = render_target.GetDepthAttachment(); depth.has_value()) {
SetTextureLayout(
depth.value(),
CreateAttachmentDescription(depth.value(), &Attachment::texture),
command_buffer, &Attachment::texture);
}

if (auto stencil = render_target.GetStencilAttachment();
stencil.has_value()) {
SetTextureLayout(
stencil.value(),
CreateAttachmentDescription(stencil.value(), &Attachment::texture),
command_buffer, &Attachment::texture);
}
}
} // namespace

SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
const ContextVK& context,
const std::shared_ptr<CommandBufferVK>& command_buffer) const {
const ContextVK& context) const {
TRACE_EVENT0("impeller", "RenderPassVK::CreateVKRenderPass");
std::vector<vk::AttachmentDescription> attachments;

std::vector<vk::AttachmentReference> color_refs;
Expand All @@ -125,15 +159,11 @@ SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
vk::ImageLayout::eColorAttachmentOptimal};
attachments.emplace_back(
CreateAttachmentDescription(color, &Attachment::texture));
SetTextureLayout(color, attachments.back(), command_buffer,
&Attachment::texture);
if (color.resolve_texture) {
resolve_refs[bind_point] = vk::AttachmentReference{
static_cast<uint32_t>(attachments.size()), vk::ImageLayout::eGeneral};
attachments.emplace_back(
CreateAttachmentDescription(color, &Attachment::resolve_texture));
SetTextureLayout(color, attachments.back(), command_buffer,
&Attachment::resolve_texture);
}
}

Expand All @@ -143,8 +173,6 @@ SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
vk::ImageLayout::eDepthStencilAttachmentOptimal};
attachments.emplace_back(
CreateAttachmentDescription(depth.value(), &Attachment::texture));
SetTextureLayout(depth.value(), attachments.back(), command_buffer,
&Attachment::texture);
}

if (auto stencil = render_target_.GetStencilAttachment();
Expand All @@ -154,8 +182,6 @@ SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
vk::ImageLayout::eDepthStencilAttachmentOptimal};
attachments.emplace_back(
CreateAttachmentDescription(stencil.value(), &Attachment::texture));
SetTextureLayout(stencil.value(), attachments.back(), command_buffer,
&Attachment::texture);
}

vk::SubpassDescription subpass_desc;
Expand All @@ -176,6 +202,27 @@ SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
return {};
}
context.SetDebugName(pass.get(), debug_label_.c_str());

std::stringstream ss;
ss << debug_label_ << " " << pass.get() << " " << std::endl;
for (const vk::AttachmentDescription& desc : attachments) {
ss << " attachment"
<< ", initial: " << vk::to_string(desc.initialLayout)
<< ", final layout: " << vk::to_string(desc.finalLayout) << std::endl;
}

for (const vk::AttachmentReference& ref : color_refs) {
ss << " color ref: " << vk::to_string(ref.layout);
}

for (const vk::AttachmentReference& ref : resolve_refs) {
ss << ", resolve ref: " << vk::to_string(ref.layout);
}

ss << ", depth stencil ref: " << vk::to_string(depth_stencil_ref.layout);

FML_LOG(ERROR) << ss.str();

return MakeSharedVK(std::move(pass));
}

Expand Down Expand Up @@ -628,27 +675,45 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const {

const auto& target_size = render_target_.GetRenderTargetSize();

auto render_pass = CreateVKRenderPass(vk_context, command_buffer);
if (!render_pass) {
VALIDATION_LOG << "Could not create renderpass.";
return false;
}
std::shared_ptr<RingBufferItem<RenderPassFrameBufferPair>>
render_pass_frame_buffer_pair = vk_context.GetRenderPassFrameBufferPair();

auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass);
if (!framebuffer) {
VALIDATION_LOG << "Could not create framebuffer.";
return false;
if (!render_pass_frame_buffer_pair->GetValue()) {
auto render_pass = CreateVKRenderPass(vk_context);
if (!render_pass) {
VALIDATION_LOG << "Could not create renderpass.";
return false;
}

auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass);
if (!framebuffer) {
VALIDATION_LOG << "Could not create framebuffer.";
return false;
}

RenderPassFrameBufferPair pair = RenderPassFrameBufferPair{
.render_pass = render_pass,
.framebuffer = framebuffer,
};

render_pass_frame_buffer_pair->GetValue() = std::move(pair);
}
FML_LOG(ERROR) << render_target_.ToString() << " "
<< render_pass_frame_buffer_pair->GetValue()->render_pass;
SetTextureLayouts(render_target_, command_buffer);
FML_LOG(ERROR) << "end SetTextureLayouts";

if (!encoder->Track(framebuffer) || !encoder->Track(render_pass)) {
if (!encoder->Track(render_pass_frame_buffer_pair)) {
return false;
}

auto clear_values = GetVKClearValues(render_target_);

vk::RenderPassBeginInfo pass_info;
pass_info.renderPass = *render_pass;
pass_info.framebuffer = *framebuffer;
pass_info.renderPass =
*render_pass_frame_buffer_pair->GetValue()->render_pass;
pass_info.framebuffer =
*render_pass_frame_buffer_pair->GetValue()->framebuffer;
pass_info.renderArea.extent.width = static_cast<uint32_t>(target_size.width);
pass_info.renderArea.extent.height =
static_cast<uint32_t>(target_size.height);
Expand Down
3 changes: 1 addition & 2 deletions impeller/renderer/backend/vulkan/render_pass_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ class RenderPassVK final : public RenderPass {
bool OnEncodeCommands(const Context& context) const override;

SharedHandleVK<vk::RenderPass> CreateVKRenderPass(
const ContextVK& context,
const std::shared_ptr<CommandBufferVK>& command_buffer) const;
const ContextVK& context) const;

SharedHandleVK<vk::Framebuffer> CreateVKFramebuffer(
const ContextVK& context,
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/backend/vulkan/swapchain_impl_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ std::shared_ptr<Context> SwapchainImplVK::GetContext() const {

SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() {
auto context_strong = context_.lock();
FML_LOG(ERROR) << "SwapchainImplVK::AcquireNextDrawable";
if (!context_strong) {
return {};
}
Expand Down Expand Up @@ -506,6 +507,7 @@ bool SwapchainImplVK::Present(const std::shared_ptr<SwapchainImageVK>& image,
}
FML_UNREACHABLE();
});
FML_LOG(ERROR) << "SwapchainImplVK::Present";
return true;
}

Expand Down
7 changes: 7 additions & 0 deletions impeller/renderer/backend/vulkan/texture_source_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ vk::ImageLayout TextureSourceVK::GetLayout() const {

vk::ImageLayout TextureSourceVK::SetLayoutWithoutEncoding(
vk::ImageLayout layout) const {
FML_LOG(ERROR) << "SetLayoutWithoutEncoding " << GetImage() << " "
<< vk::to_string(layout);
WriterLock lock(layout_mutex_);
const auto old_layout = layout_;
layout_ = layout;
Expand All @@ -32,6 +34,11 @@ bool TextureSourceVK::SetLayout(const BarrierVK& barrier) const {
if (barrier.new_layout == old_layout) {
return true;
}
FML_LOG(ERROR) << "SetLayout " << GetImage() << " "
<< "src:" << vk::to_string(barrier.src_access) << " "
<< "dst:" << vk::to_string(barrier.dst_access) << " "
<< vk::to_string(old_layout) << " "
<< vk::to_string(barrier.new_layout);

vk::ImageMemoryBarrier image_barrier;
image_barrier.srcAccessMask = barrier.src_access;
Expand Down