Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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 <type_traits>
13#include <utility>
14#include <vector>
15
19
20namespace impeller {
21
22/// Approximately the same size as the max frames in flight.
23static const constexpr size_t kHostBufferArenaSize = 4u;
24
25/// The host buffer class manages one more 1024 Kb blocks of device buffer
26/// allocations.
27///
28/// These are reset per-frame.
29///
30/// The buffers of an arena entry are reused kHostBufferArenaSize resets
31/// after they were written. Nothing guarantees that few frames are in
32/// flight, so with a [GpuSubmissionTracker] the reuse is made safe. Entries
33/// whose GPU work has not completed by the time they come up for reuse are
34/// kept alive off to the side and replaced with fresh allocations.
36 public:
37 static std::shared_ptr<HostBuffer> Create(
38 const std::shared_ptr<Allocator>& allocator,
39 const std::shared_ptr<const IdleWaiter>& idle_waiter,
40 size_t minimum_uniform_alignment,
41 std::shared_ptr<const GpuSubmissionTracker> submission_tracker = nullptr);
42
44
45 //----------------------------------------------------------------------------
46 /// @brief Emplace uniform data onto the host buffer. Ensure that backend
47 /// specific uniform alignment requirements are respected.
48 ///
49 /// @param[in] uniform The uniform struct to emplace onto the buffer.
50 ///
51 /// @tparam UniformType The type of the uniform struct.
52 ///
53 /// @return The buffer view.
54 ///
55 template <class UniformType,
56 class = std::enable_if_t<std::is_standard_layout_v<UniformType>>>
57 [[nodiscard]] BufferView EmplaceUniform(const UniformType& uniform) {
58 const auto alignment =
59 std::max(alignof(UniformType), GetMinimumUniformAlignment());
60 return Emplace(reinterpret_cast<const void*>(&uniform), // buffer
61 sizeof(UniformType), // size
62 alignment // alignment
63 );
64 }
65
66 //----------------------------------------------------------------------------
67 /// @brief Emplace storage buffer data onto the host buffer. Ensure that
68 /// backend specific uniform alignment requirements are respected.
69 ///
70 /// @param[in] uniform The storage buffer to emplace onto the buffer.
71 ///
72 /// @tparam StorageBufferType The type of the shader storage buffer.
73 ///
74 /// @return The buffer view.
75 ///
76 template <
77 class StorageBufferType,
78 class = std::enable_if_t<std::is_standard_layout_v<StorageBufferType>>>
80 const StorageBufferType& buffer) {
81 const auto alignment =
82 std::max(alignof(StorageBufferType), GetMinimumUniformAlignment());
83 return Emplace(&buffer, // buffer
84 sizeof(StorageBufferType), // size
85 alignment // alignment
86 );
87 }
88
89 //----------------------------------------------------------------------------
90 /// @brief Emplace non-uniform data (like contiguous vertices) onto the
91 /// host buffer.
92 ///
93 /// @param[in] buffer The buffer data.
94 /// @param[in] alignment Minimum alignment of the data being emplaced.
95 ///
96 /// @tparam BufferType The type of the buffer data.
97 ///
98 /// @return The buffer view.
99 ///
100 template <class BufferType,
101 class = std::enable_if_t<std::is_standard_layout_v<BufferType>>>
102 [[nodiscard]] BufferView Emplace(const BufferType& buffer,
103 size_t alignment = 0) {
104 return Emplace(reinterpret_cast<const void*>(&buffer), // buffer
105 sizeof(BufferType), // size
106 std::max(alignment, alignof(BufferType)) // alignment
107 );
108 }
109
110 [[nodiscard]] BufferView Emplace(const void* buffer,
111 size_t length,
112 size_t align);
113
114 using EmplaceProc = std::function<void(uint8_t* buffer)>;
115
116 //----------------------------------------------------------------------------
117 /// @brief Emplaces undefined data onto the managed buffer and gives the
118 /// caller a chance to update it using the specified callback. The
119 /// buffer is guaranteed to have enough space for length bytes. It
120 /// is the responsibility of the caller to not exceed the bounds
121 /// of the buffer returned in the EmplaceProc.
122 ///
123 /// @param[in] cb A callback that will be passed a ptr to the
124 /// underlying host buffer.
125 ///
126 /// @return The buffer view.
127 ///
128 BufferView Emplace(size_t length, size_t align, const EmplaceProc& cb);
129
130 /// Retrieve the minimum uniform buffer alignment in bytes.
131 size_t GetMinimumUniformAlignment() const;
132
133 //----------------------------------------------------------------------------
134 /// @brief Resets the contents of the HostBuffer to nothing so it can be
135 /// reused.
136 void Reset();
137
138 /// Test only internal state.
144
145 /// @brief Retrieve internal buffer state for test expectations.
147
148 private:
149 [[nodiscard]] std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
150 EmplaceInternal(const void* buffer, size_t length);
151
152 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
153 EmplaceInternal(size_t length, size_t align, const EmplaceProc& cb);
154
155 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
156 EmplaceInternal(const void* buffer, size_t length, size_t align);
157
158 size_t GetLength() const { return offset_; }
159
160 /// Attempt to create a new internal buffer if the existing capacity is not
161 /// sufficient.
162 ///
163 /// A false return value indicates an unrecoverable allocation failure.
164 [[nodiscard]] bool MaybeCreateNewBuffer();
165
166 const std::shared_ptr<DeviceBuffer>& GetCurrentBuffer() const;
167
168 [[nodiscard]] BufferView Emplace(const void* buffer, size_t length);
169
170 explicit HostBuffer(
171 const std::shared_ptr<Allocator>& allocator,
172 const std::shared_ptr<const IdleWaiter>& idle_waiter,
173 size_t minimum_uniform_alignment,
174 std::shared_ptr<const GpuSubmissionTracker> submission_tracker);
175
176 HostBuffer(const HostBuffer&) = delete;
177
178 HostBuffer& operator=(const HostBuffer&) = delete;
179
180 std::shared_ptr<Allocator> allocator_;
181 std::shared_ptr<const IdleWaiter> idle_waiter_;
182 std::shared_ptr<const GpuSubmissionTracker> submission_tracker_;
183 std::array<std::vector<std::shared_ptr<DeviceBuffer>>, kHostBufferArenaSize>
184 device_buffers_;
185 // Per-entry id of the last GPU submission that may reference the entry's
186 // buffers.
187 std::array<uint64_t, kHostBufferArenaSize> entry_stamps_ = {};
188 // Buffers pulled out of reuse because the GPU had not completed with them,
189 // keyed by the submission id to outlive.
190 std::vector<std::pair<uint64_t, std::vector<std::shared_ptr<DeviceBuffer>>>>
191 retired_buffers_;
192 size_t current_buffer_ = 0u;
193 size_t offset_ = 0u;
194 size_t frame_index_ = 0u;
195 size_t minimum_uniform_alignment_ = 0u;
196};
197
198} // namespace impeller
199
200#endif // FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
size_t GetMinimumUniformAlignment() const
Retrieve the minimum uniform buffer alignment in bytes.
TestStateQuery GetStateForTest()
Retrieve internal buffer state for test expectations.
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition host_buffer.h:57
BufferView EmplaceStorageBuffer(const StorageBufferType &buffer)
Emplace storage buffer data onto the host buffer. Ensure that backend specific uniform alignment requ...
Definition host_buffer.h:79
std::function< void(uint8_t *buffer)> EmplaceProc
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator, const std::shared_ptr< const IdleWaiter > &idle_waiter, size_t minimum_uniform_alignment, std::shared_ptr< const GpuSubmissionTracker > submission_tracker=nullptr)
void Reset()
Resets the contents of the HostBuffer to nothing so it can be reused.
std::shared_ptr< ImpellerAllocator > allocator
size_t length
static const constexpr size_t kHostBufferArenaSize
Approximately the same size as the max frames in flight.
Definition host_buffer.h:23
Test only internal state.