1717#include " impeller/renderer/backend/vulkan/queue_vk.h"
1818#include " impeller/renderer/backend/vulkan/sampler_library_vk.h"
1919#include " impeller/renderer/backend/vulkan/shader_library_vk.h"
20+ #include " impeller/renderer/backend/vulkan/shared_object_vk.h"
2021#include " impeller/renderer/capabilities.h"
2122#include " impeller/renderer/context.h"
2223
@@ -31,6 +32,71 @@ class FenceWaiterVK;
3132class ResourceManagerVK ;
3233class SurfaceContextVK ;
3334
35+ // / @brief Ring buffer for one writer thread and one reader thread.
36+ template <typename T>
37+ class RingBuffer {
38+ public:
39+ RingBuffer (int32_t size) : read_(0 ), write_(0 ), buffer_(size) {}
40+
41+ std::optional<T> Read () {
42+ int32_t current_read = read_.load ();
43+ if (current_read == write_.load ()) {
44+ return {};
45+ } else {
46+ int32_t next_read = (current_read + 1 ) % buffer_.size ();
47+ read_.store (next_read);
48+ return buffer_[current_read];
49+ }
50+ }
51+
52+ bool Write (const T& value) {
53+ int32_t current_write = write_.load ();
54+ int32_t next_write = (current_write + 1 ) % buffer_.size ();
55+ if (next_write == read_.load ()) { // Buffer full
56+ return false ;
57+ }
58+ buffer_[current_write] = value;
59+ write_.store (next_write);
60+ return true ;
61+ }
62+
63+ private:
64+ std::atomic<int32_t > read_;
65+ std::atomic<int32_t > write_;
66+ std::vector<T> buffer_;
67+ };
68+
69+ template <typename T>
70+ class RingBufferItem : public SharedObjectVK {
71+ public:
72+ RingBufferItem (std::weak_ptr<const ContextVK> context,
73+ RingBuffer<T>* ring_buffer,
74+ std::optional<T> value)
75+ : context_(context), ring_buffer_(ring_buffer), value_(value) {}
76+
77+ virtual ~RingBufferItem () {
78+ auto context = context_.lock ();
79+ if (value_ && context) {
80+ bool did_write = ring_buffer_->Write (value_.value ());
81+ FML_CHECK (did_write);
82+ }
83+ }
84+
85+ std::optional<T>& GetValue () { return value_; }
86+
87+ private:
88+ FML_DISALLOW_COPY_AND_ASSIGN (RingBufferItem<T>);
89+
90+ std::weak_ptr<const ContextVK> context_;
91+ RingBuffer<T>* ring_buffer_;
92+ std::optional<T> value_;
93+ };
94+
95+ struct RenderPassFrameBufferPair {
96+ SharedHandleVK<vk::RenderPass> render_pass;
97+ SharedHandleVK<vk::Framebuffer> framebuffer;
98+ };
99+
34100class ContextVK final : public Context,
35101 public BackendCast<ContextVK, Context>,
36102 public std::enable_shared_from_this<ContextVK> {
@@ -135,6 +201,12 @@ class ContextVK final : public Context,
135201
136202 std::shared_ptr<ResourceManagerVK> GetResourceManager () const ;
137203
204+ std::shared_ptr<RingBufferItem<RenderPassFrameBufferPair>>
205+ GetRenderPassFrameBufferPair () const {
206+ return std::make_shared<RingBufferItem<RenderPassFrameBufferPair>>(
207+ shared_from_this (), &render_pass_pool_, render_pass_pool_.Read ());
208+ }
209+
138210 private:
139211 struct DeviceHolderImpl : public DeviceHolder {
140212 // |DeviceHolder|
@@ -162,6 +234,8 @@ class ContextVK final : public Context,
162234 std::string device_name_;
163235 std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
164236 const uint64_t hash_;
237+ mutable RingBuffer<RenderPassFrameBufferPair> render_pass_pool_ =
238+ RingBuffer<RenderPassFrameBufferPair>(10 );
165239
166240 bool is_valid_ = false ;
167241
0 commit comments