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 
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 = 3u;
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 
33  // |Buffer|
34  virtual ~HostBuffer();
35 
36  void SetLabel(std::string label);
37 
38  //----------------------------------------------------------------------------
39  /// @brief Emplace uniform data onto the host buffer. Ensure that backend
40  /// specific uniform alignment requirements are respected.
41  ///
42  /// @param[in] uniform The uniform struct to emplace onto the buffer.
43  ///
44  /// @tparam UniformType The type of the uniform struct.
45  ///
46  /// @return The buffer view.
47  ///
48  template <class UniformType,
49  class = std::enable_if_t<std::is_standard_layout_v<UniformType>>>
50  [[nodiscard]] BufferView EmplaceUniform(const UniformType& uniform) {
51  const auto alignment =
52  std::max(alignof(UniformType), DefaultUniformAlignment());
53  return Emplace(reinterpret_cast<const void*>(&uniform), // buffer
54  sizeof(UniformType), // size
55  alignment // alignment
56  );
57  }
58 
59  //----------------------------------------------------------------------------
60  /// @brief Emplace storage buffer data onto the host buffer. Ensure that
61  /// backend specific uniform alignment requirements are respected.
62  ///
63  /// @param[in] uniform The storage buffer to emplace onto the buffer.
64  ///
65  /// @tparam StorageBufferType The type of the shader storage buffer.
66  ///
67  /// @return The buffer view.
68  ///
69  template <
70  class StorageBufferType,
71  class = std::enable_if_t<std::is_standard_layout_v<StorageBufferType>>>
73  const StorageBufferType& buffer) {
74  const auto alignment =
75  std::max(alignof(StorageBufferType), DefaultUniformAlignment());
76  return Emplace(&buffer, // buffer
77  sizeof(StorageBufferType), // size
78  alignment // alignment
79  );
80  }
81 
82  //----------------------------------------------------------------------------
83  /// @brief Emplace non-uniform data (like contiguous vertices) onto the
84  /// host buffer.
85  ///
86  /// @param[in] buffer The buffer data.
87  ///
88  /// @tparam BufferType The type of the buffer data.
89  ///
90  /// @return The buffer view.
91  ///
92  template <class BufferType,
93  class = std::enable_if_t<std::is_standard_layout_v<BufferType>>>
94  [[nodiscard]] BufferView Emplace(const BufferType& buffer) {
95  return Emplace(reinterpret_cast<const void*>(&buffer), // buffer
96  sizeof(BufferType), // size
97  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 {
131  };
132 
133  /// @brief Retrieve internal buffer state for test expectations.
135 
136  private:
137  [[nodiscard]] std::tuple<Range, std::shared_ptr<DeviceBuffer>>
138  EmplaceInternal(const void* buffer, size_t length);
139 
140  std::tuple<Range, std::shared_ptr<DeviceBuffer>>
141  EmplaceInternal(size_t length, size_t align, const EmplaceProc& cb);
142 
143  std::tuple<Range, std::shared_ptr<DeviceBuffer>>
144  EmplaceInternal(const void* buffer, size_t length, size_t align);
145 
146  size_t GetLength() const { return offset_; }
147 
148  void MaybeCreateNewBuffer();
149 
150  std::shared_ptr<DeviceBuffer>& GetCurrentBuffer() {
151  return device_buffers_[frame_index_][current_buffer_];
152  }
153 
154  [[nodiscard]] BufferView Emplace(const void* buffer, size_t length);
155 
156  explicit HostBuffer(const std::shared_ptr<Allocator>& allocator);
157 
158  HostBuffer(const HostBuffer&) = delete;
159 
160  HostBuffer& operator=(const HostBuffer&) = delete;
161 
162  std::shared_ptr<Allocator> allocator_;
163  std::array<std::vector<std::shared_ptr<DeviceBuffer>>, kHostBufferArenaSize>
164  device_buffers_;
165  size_t current_buffer_ = 0u;
166  size_t offset_ = 0u;
167  size_t frame_index_ = 0u;
168  std::string label_;
169 };
170 
171 } // namespace impeller
172 
173 #endif // FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_
impeller::HostBuffer::EmplaceProc
std::function< void(uint8_t *buffer)> EmplaceProc
Definition: host_buffer.h:105
impeller::DefaultUniformAlignment
constexpr size_t DefaultUniformAlignment()
Definition: platform.h:15
impeller::HostBuffer
Definition: host_buffer.h:28
impeller::HostBuffer::Emplace
BufferView Emplace(const BufferType &buffer)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:94
impeller::HostBuffer::Create
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator)
Definition: host_buffer.cc:20
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
virtual ~HostBuffer()
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:15
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:189
impeller::HostBuffer::GetStateForTest
TestStateQuery GetStateForTest()
Retrieve internal buffer state for test expectations.
Definition: host_buffer.cc:69
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:50
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:72
impeller::HostBuffer::SetLabel
void SetLabel(std::string label)
Definition: host_buffer.cc:37
impeller
Definition: aiks_blur_unittests.cc:20