| Flutter Impeller |

host_buffer.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_
6 #define FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_
7
8 #include <algorithm>
9 #include <array>
10 #include <functional>
11 #include <memory>
12 #include <string>
13 #include <type_traits>
14
15 #include "impeller/core/allocator.h"
16 #include "impeller/core/buffer_view.h"
17 #include "impeller/core/platform.h"
18
19 namespace impeller {
20
21 /// Approximately the same size as the max frames in flight.
22 static const constexpr size_t kHostBufferArenaSize = 4u;
23
24 /// The host buffer class manages one more 1024 Kb blocks of device buffer
25 /// allocations.
26 ///
27 /// These are reset per-frame.
28 class HostBuffer {
29 public:
30 static std::shared_ptr<HostBuffer> Create(
31 const std::shared_ptr<Allocator>& allocator,
32 const std::shared_ptr<const IdleWaiter>& idle_waiter);
33
34 ~HostBuffer();
35
36 //----------------------------------------------------------------------------
37 /// @brief Emplace uniform data onto the host buffer. Ensure that backend
38 /// specific uniform alignment requirements are respected.
39 ///
40 /// @param[in] uniform The uniform struct to emplace onto the buffer.
41 ///
42 /// @tparam UniformType The type of the uniform struct.
43 ///
44 /// @return The buffer view.
45 ///
46 template <class UniformType,
47 class = std::enable_if_t<std::is_standard_layout_v<UniformType>>>
48 [[nodiscard]] BufferView EmplaceUniform(const UniformType& uniform) {
49 const auto alignment =
50 std::max(alignof(UniformType), DefaultUniformAlignment());
51 return Emplace(reinterpret_cast<const void*>(&uniform), // buffer
52 sizeof(UniformType), // size
53 alignment // alignment
54 );
55 }
56
57 //----------------------------------------------------------------------------
58 /// @brief Emplace storage buffer data onto the host buffer. Ensure that
59 /// backend specific uniform alignment requirements are respected.
60 ///
61 /// @param[in] uniform The storage buffer to emplace onto the buffer.
62 ///
63 /// @tparam StorageBufferType The type of the shader storage buffer.
64 ///
65 /// @return The buffer view.
66 ///
67 template <
68 class StorageBufferType,
69 class = std::enable_if_t<std::is_standard_layout_v<StorageBufferType>>>
70 [[nodiscard]] BufferView EmplaceStorageBuffer(
71 const StorageBufferType& buffer) {
72 const auto alignment =
73 std::max(alignof(StorageBufferType), DefaultUniformAlignment());
74 return Emplace(&buffer, // buffer
75 sizeof(StorageBufferType), // size
76 alignment // alignment
77 );
78 }
79
80 //----------------------------------------------------------------------------
81 /// @brief Emplace non-uniform data (like contiguous vertices) onto the
82 /// host buffer.
83 ///
84 /// @param[in] buffer The buffer data.
85 /// @param[in] alignment Minimum alignment of the data being emplaced.
86 ///
87 /// @tparam BufferType The type of the buffer data.
88 ///
89 /// @return The buffer view.
90 ///
91 template <class BufferType,
92 class = std::enable_if_t<std::is_standard_layout_v<BufferType>>>
93 [[nodiscard]] BufferView Emplace(const BufferType& buffer,
94 size_t alignment = 0) {
95 return Emplace(reinterpret_cast<const void*>(&buffer), // buffer
96 sizeof(BufferType), // size
97 std::max(alignment, alignof(BufferType)) // alignment
98 );
99 }
100
101 [[nodiscard]] BufferView Emplace(const void* buffer,
102 size_t length,
103 size_t align);
104
105 using EmplaceProc = std::function<void(uint8_t* buffer)>;
106
107 //----------------------------------------------------------------------------
108 /// @brief Emplaces undefined data onto the managed buffer and gives the
109 /// caller a chance to update it using the specified callback. The
110 /// buffer is guaranteed to have enough space for length bytes. It
111 /// is the responsibility of the caller to not exceed the bounds
112 /// of the buffer returned in the EmplaceProc.
113 ///
114 /// @param[in] cb A callback that will be passed a ptr to the
115 /// underlying host buffer.
116 ///
117 /// @return The buffer view.
118 ///
119 BufferView Emplace(size_t length, size_t align, const EmplaceProc& cb);
120
121 //----------------------------------------------------------------------------
122 /// @brief Resets the contents of the HostBuffer to nothing so it can be
123 /// reused.
124 void Reset();
125
126 /// Test only internal state.
127 struct TestStateQuery {
128 size_t current_frame;
129 size_t current_buffer;
130 size_t total_buffer_count;
131 };
132
133 /// @brief Retrieve internal buffer state for test expectations.
134 TestStateQuery GetStateForTest();
135
136 private:
137 [[nodiscard]] std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
138 EmplaceInternal(const void* buffer, size_t length);
139
140 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
141 EmplaceInternal(size_t length, size_t align, const EmplaceProc& cb);
142
143 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
144 EmplaceInternal(const void* buffer, size_t length, size_t align);
145
146 size_t GetLength() const { return offset_; }
147
148 /// Attempt to create a new internal buffer if the existing capacity is not
149 /// sufficient.
150 ///
151 /// A false return value indicates an unrecoverable allocation failure.
152 [[nodiscard]] bool MaybeCreateNewBuffer();
153
154 const std::shared_ptr<DeviceBuffer>& GetCurrentBuffer() const;
155
156 [[nodiscard]] BufferView Emplace(const void* buffer, size_t length);
157
158 explicit HostBuffer(const std::shared_ptr<Allocator>& allocator,
159 const std::shared_ptr<const IdleWaiter>& idle_waiter);
160
161 HostBuffer(const HostBuffer&) = delete;
162
163 HostBuffer& operator=(const HostBuffer&) = delete;
164
165 std::shared_ptr<Allocator> allocator_;
166 std::shared_ptr<const IdleWaiter> idle_waiter_;
167 std::array<std::vector<std::shared_ptr<DeviceBuffer>>, kHostBufferArenaSize>
168 device_buffers_;
169 size_t current_buffer_ = 0u;
170 size_t offset_ = 0u;
171 size_t frame_index_ = 0u;
172 };
173
174 } // namespace impeller
175
176 #endif // FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_
impeller::HostBuffer::EmplaceProc
std::function< void(uint8_t *buffer)> EmplaceProc
Definition: host_buffer.h:105
impeller::HostBuffer::Emplace
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:93
impeller::DeviceBuffer
Definition: device_buffer.h:18
impeller::DefaultUniformAlignment
constexpr size_t DefaultUniformAlignment()
Definition: platform.h:14
impeller::HostBuffer::Create
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator, const std::shared_ptr< const IdleWaiter > &idle_waiter)
Definition: host_buffer.cc:21
impeller::HostBuffer
Definition: host_buffer.h:28
impeller::HostBuffer::TestStateQuery::total_buffer_count
size_t total_buffer_count
Definition: host_buffer.h:130
impeller::HostBuffer::TestStateQuery
Test only internal state.
Definition: host_buffer.h:127
impeller::HostBuffer::TestStateQuery::current_frame
size_t current_frame
Definition: host_buffer.h:128
impeller::HostBuffer::~HostBuffer
~HostBuffer()
Definition: host_buffer.cc:40
impeller::HostBuffer::TestStateQuery::current_buffer
size_t current_buffer
Definition: host_buffer.h:129
impeller::kHostBufferArenaSize
static const constexpr size_t kHostBufferArenaSize
Approximately the same size as the max frames in flight.
Definition: host_buffer.h:22
platform.h
allocator.h
impeller::BufferView
Definition: buffer_view.h:19
buffer_view.h
impeller::HostBuffer::Reset
void Reset()
Resets the contents of the HostBuffer to nothing so it can be reused.
Definition: host_buffer.cc:224
impeller::HostBuffer::GetStateForTest
TestStateQuery GetStateForTest()
Retrieve internal buffer state for test expectations.
Definition: host_buffer.cc:88
impeller::HostBuffer::EmplaceUniform
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition: host_buffer.h:48
impeller::HostBuffer::EmplaceStorageBuffer
BufferView EmplaceStorageBuffer(const StorageBufferType &buffer)
Emplace storage buffer data onto the host buffer. Ensure that backend specific uniform alignment requ...
Definition: host_buffer.h:70
impeller
Definition: allocation.cc:12