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