44
55#include " impeller/core/host_buffer.h"
66
7- #include < algorithm>
87#include < cstring>
9-
10- #include " flutter/fml/logging.h"
8+ #include < tuple>
119
1210#include " impeller/core/allocator.h"
1311#include " impeller/core/buffer_view.h"
1412#include " impeller/core/device_buffer.h"
13+ #include " impeller/core/device_buffer_descriptor.h"
14+ #include " impeller/core/formats.h"
1515
1616namespace impeller {
1717
18- std::shared_ptr<HostBuffer> HostBuffer::Create () {
19- return std::shared_ptr<HostBuffer>(new HostBuffer ());
18+ constexpr size_t kAllocatorBlockSize = 1024000 ; // 1024 Kb.
19+
20+ std::shared_ptr<HostBuffer> HostBuffer::Create (
21+ const std::shared_ptr<Allocator>& allocator) {
22+ return std::shared_ptr<HostBuffer>(new HostBuffer (allocator));
2023}
2124
22- HostBuffer::HostBuffer () = default ;
25+ HostBuffer::HostBuffer (const std::shared_ptr<Allocator>& allocator) {
26+ state_->allocator = allocator;
27+ DeviceBufferDescriptor desc;
28+ desc.size = kAllocatorBlockSize ;
29+ desc.storage_mode = StorageMode::kHostVisible ;
30+ for (auto i = 0u ; i < kHostBufferArenaSize ; i++) {
31+ state_->device_buffers [i].push_back (allocator->CreateBuffer (desc));
32+ }
33+ }
2334
2435HostBuffer::~HostBuffer () = default ;
2536
@@ -30,104 +41,143 @@ void HostBuffer::SetLabel(std::string label) {
3041BufferView HostBuffer::Emplace (const void * buffer,
3142 size_t length,
3243 size_t align) {
33- auto [device_buffer , range] = state_->Emplace (buffer, length, align);
44+ auto [data , range, device_buffer ] = state_->Emplace (buffer, length, align);
3445 if (!device_buffer) {
3546 return {};
3647 }
37- return BufferView{state_, device_buffer , range};
48+ return BufferView{std::move (device_buffer), data , range};
3849}
3950
4051BufferView HostBuffer::Emplace (const void * buffer, size_t length) {
41- auto [device_buffer , range] = state_->Emplace (buffer, length);
52+ auto [data , range, device_buffer ] = state_->Emplace (buffer, length);
4253 if (!device_buffer) {
4354 return {};
4455 }
45- return BufferView{state_, device_buffer , range};
56+ return BufferView{std::move (device_buffer), data , range};
4657}
4758
4859BufferView HostBuffer::Emplace (size_t length,
4960 size_t align,
5061 const EmplaceProc& cb) {
51- auto [buffer , range] = state_->Emplace (length, align, cb);
52- if (!buffer ) {
62+ auto [data , range, device_buffer ] = state_->Emplace (length, align, cb);
63+ if (!device_buffer ) {
5364 return {};
5465 }
55- return BufferView{state_, buffer , range};
66+ return BufferView{std::move (device_buffer), data , range};
5667}
5768
58- std::shared_ptr<const DeviceBuffer> HostBuffer::GetDeviceBuffer (
59- Allocator& allocator) const {
60- return state_->GetDeviceBuffer (allocator);
69+ HostBuffer::TestStateQuery HostBuffer::GetStateForTest () {
70+ return HostBuffer::TestStateQuery{
71+ .current_frame = state_->frame_index ,
72+ .current_buffer = state_->current_buffer ,
73+ .total_buffer_count = state_->device_buffers [state_->frame_index ].size (),
74+ };
6175}
6276
6377void HostBuffer::Reset () {
6478 state_->Reset ();
6579}
6680
67- size_t HostBuffer::GetSize () const {
68- return state_->GetReservedLength ();
69- }
70-
71- size_t HostBuffer::GetLength () const {
72- return state_->GetLength ();
81+ void HostBuffer::HostBufferState::MaybeCreateNewBuffer (size_t required_size) {
82+ current_buffer++;
83+ if (current_buffer >= device_buffers[frame_index].size ()) {
84+ FML_DCHECK (required_size <= kAllocatorBlockSize );
85+ DeviceBufferDescriptor desc;
86+ desc.size = kAllocatorBlockSize ;
87+ desc.storage_mode = StorageMode::kHostVisible ;
88+ device_buffers[frame_index].push_back (allocator->CreateBuffer (desc));
89+ }
90+ offset = 0 ;
7391}
7492
75- std::pair <uint8_t *, Range> HostBuffer::HostBufferState::Emplace (
76- size_t length,
77- size_t align,
78- const EmplaceProc& cb) {
93+ std::tuple <uint8_t *, Range, std::shared_ptr<DeviceBuffer>>
94+ HostBuffer::HostBufferState::Emplace ( size_t length,
95+ size_t align,
96+ const EmplaceProc& cb) {
7997 if (!cb) {
8098 return {};
8199 }
100+
101+ // If the requested allocation is bigger than the block size, create a one-off
102+ // device buffer and write to that.
103+ if (length > kAllocatorBlockSize ) {
104+ DeviceBufferDescriptor desc;
105+ desc.size = length;
106+ desc.storage_mode = StorageMode::kHostVisible ;
107+ auto device_buffer = allocator->CreateBuffer (desc);
108+ if (!device_buffer) {
109+ return {};
110+ }
111+ if (cb) {
112+ cb (device_buffer->OnGetContents ());
113+ device_buffer->Flush (Range{0 , length});
114+ }
115+ return std::make_tuple (device_buffer->OnGetContents (), Range{0 , length},
116+ device_buffer);
117+ }
118+
82119 auto old_length = GetLength ();
83- if (! Truncate ( old_length + length) ) {
84- return {} ;
120+ if (old_length + length > kAllocatorBlockSize ) {
121+ MaybeCreateNewBuffer (length) ;
85122 }
86- generation++;
87- cb (GetBuffer () + old_length);
123+ old_length = GetLength ();
124+
125+ cb (GetCurrentBuffer ()->OnGetContents () + old_length);
126+ GetCurrentBuffer ()->Flush (Range{old_length, length});
88127
89- return std::make_pair (GetBuffer (), Range{old_length, length});
128+ offset += length;
129+ return std::make_tuple (GetCurrentBuffer ()->OnGetContents (),
130+ Range{old_length, length}, GetCurrentBuffer ());
90131}
91132
92- std::shared_ptr<const DeviceBuffer>
93- HostBuffer::HostBufferState::GetDeviceBuffer (Allocator& allocator) const {
94- if (generation == device_buffer_generation) {
95- return device_buffer;
96- }
97- auto new_buffer = allocator.CreateBufferWithCopy (GetBuffer (), GetLength ());
98- if (!new_buffer) {
99- return nullptr ;
133+ std::tuple<uint8_t *, Range, std::shared_ptr<DeviceBuffer>>
134+ HostBuffer::HostBufferState::Emplace (const void * buffer, size_t length) {
135+ // If the requested allocation is bigger than the block size, create a one-off
136+ // device buffer and write to that.
137+ if (length > kAllocatorBlockSize ) {
138+ DeviceBufferDescriptor desc;
139+ desc.size = length;
140+ desc.storage_mode = StorageMode::kHostVisible ;
141+ auto device_buffer = allocator->CreateBuffer (desc);
142+ if (!device_buffer) {
143+ return {};
144+ }
145+ if (buffer) {
146+ if (!device_buffer->CopyHostBuffer (static_cast <const uint8_t *>(buffer),
147+ Range{0 , length})) {
148+ return {};
149+ }
150+ }
151+ return std::make_tuple (device_buffer->OnGetContents (), Range{0 , length},
152+ device_buffer);
100153 }
101- new_buffer->SetLabel (label);
102- device_buffer_generation = generation;
103- device_buffer = std::move (new_buffer);
104- return device_buffer;
105- }
106154
107- std::pair<uint8_t *, Range> HostBuffer::HostBufferState::Emplace (
108- const void * buffer,
109- size_t length) {
110155 auto old_length = GetLength ();
111- if (! Truncate ( old_length + length) ) {
112- return {} ;
156+ if (old_length + length > kAllocatorBlockSize ) {
157+ MaybeCreateNewBuffer (length) ;
113158 }
114- generation++;
159+ old_length = GetLength ();
160+
115161 if (buffer) {
116- ::memmove (GetBuffer() + old_length, buffer, length);
162+ ::memmove (GetCurrentBuffer()->OnGetContents() + old_length, buffer, length);
163+ GetCurrentBuffer ()->Flush (Range{old_length, length});
117164 }
118- return std::make_pair (GetBuffer (), Range{old_length, length});
165+ offset += length;
166+ return std::make_tuple (GetCurrentBuffer ()->OnGetContents (),
167+ Range{old_length, length}, GetCurrentBuffer ());
119168}
120169
121- std::pair <uint8_t *, Range> HostBuffer::HostBufferState::Emplace (
122- const void * buffer,
123- size_t length,
124- size_t align) {
170+ std::tuple <uint8_t *, Range, std::shared_ptr<DeviceBuffer>>
171+ HostBuffer::HostBufferState::Emplace ( const void * buffer,
172+ size_t length,
173+ size_t align) {
125174 if (align == 0 || (GetLength () % align) == 0 ) {
126175 return Emplace (buffer, length);
127176 }
128177
129178 {
130- auto [buffer, range] = Emplace (nullptr , align - (GetLength () % align));
179+ auto [buffer, range, device_buffer] =
180+ Emplace (nullptr , align - (GetLength () % align));
131181 if (!buffer) {
132182 return {};
133183 }
@@ -137,10 +187,15 @@ std::pair<uint8_t*, Range> HostBuffer::HostBufferState::Emplace(
137187}
138188
139189void HostBuffer::HostBufferState::Reset () {
140- generation += 1 ;
141- device_buffer = nullptr ;
142- bool did_truncate = Truncate (0 );
143- FML_CHECK (did_truncate);
190+ // When resetting the host buffer state at the end of the frame, check if
191+ // there are any unused buffers and remove them.
192+ while (device_buffers[frame_index].size () > current_buffer + 1 ) {
193+ device_buffers[frame_index].pop_back ();
194+ }
195+
196+ offset = 0u ;
197+ current_buffer = 0u ;
198+ frame_index = (frame_index + 1 ) % kHostBufferArenaSize ;
144199}
145200
146201} // namespace impeller
0 commit comments