22 const std::shared_ptr<Allocator>& allocator) {
23 return std::shared_ptr<HostBuffer>(
new HostBuffer(allocator));
26 HostBuffer::HostBuffer(
const std::shared_ptr<Allocator>& allocator)
27 : allocator_(allocator) {
32 std::shared_ptr<DeviceBuffer> device_buffer = allocator->CreateBuffer(desc);
33 FML_CHECK(device_buffer) <<
"Failed to allocate device buffer.";
34 device_buffers_[i].push_back(device_buffer);
41 label_ = std::move(label);
47 auto [range, device_buffer] = EmplaceInternal(buffer, length, align);
51 return BufferView{std::move(device_buffer), range};
55 auto [range, device_buffer] = EmplaceInternal(buffer, length);
59 return BufferView{std::move(device_buffer), range};
65 auto [range, device_buffer] = EmplaceInternal(length, align, cb);
69 return BufferView{std::move(device_buffer), range};
75 .current_buffer = current_buffer_,
76 .total_buffer_count = device_buffers_[frame_index_].size(),
80 bool HostBuffer::MaybeCreateNewBuffer() {
82 if (current_buffer_ >= device_buffers_[frame_index_].size()) {
86 std::shared_ptr<DeviceBuffer> buffer = allocator_->CreateBuffer(desc);
91 device_buffers_[frame_index_].push_back(std::move(buffer));
97 std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
100 const EmplaceProc& cb) {
108 DeviceBufferDescriptor desc;
111 std::shared_ptr<DeviceBuffer> device_buffer =
112 allocator_->CreateBuffer(desc);
113 if (!device_buffer) {
117 cb(device_buffer->OnGetContents());
118 device_buffer->Flush(Range{0, length});
120 return std::make_tuple(Range{0, length}, std::move(device_buffer));
124 if (align > 0 && offset_ % align) {
125 padding = align - (offset_ % align);
128 if (!MaybeCreateNewBuffer()) {
135 const std::shared_ptr<DeviceBuffer>& current_buffer = GetCurrentBuffer();
136 auto contents = current_buffer->OnGetContents();
137 cb(contents + offset_);
138 Range output_range(offset_, length);
139 current_buffer->Flush(output_range);
142 return std::make_tuple(output_range, current_buffer);
145 std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
151 DeviceBufferDescriptor desc;
154 std::shared_ptr<DeviceBuffer> device_buffer =
155 allocator_->CreateBuffer(desc);
156 if (!device_buffer) {
160 if (!device_buffer->CopyHostBuffer(
static_cast<const uint8_t*
>(buffer),
165 return std::make_tuple(Range{0, length}, std::move(device_buffer));
168 auto old_length = GetLength();
170 if (!MaybeCreateNewBuffer()) {
174 old_length = GetLength();
176 const std::shared_ptr<DeviceBuffer>& current_buffer = GetCurrentBuffer();
177 auto contents = current_buffer->OnGetContents();
179 ::memmove(contents + old_length, buffer, length);
180 current_buffer->Flush(Range{old_length, length});
183 return std::make_tuple(Range{old_length, length}, current_buffer);
186 std::tuple<Range, std::shared_ptr<DeviceBuffer>>
187 HostBuffer::EmplaceInternal(
const void* buffer,
size_t length,
size_t align) {
188 if (align == 0 || (GetLength() % align) == 0) {
189 return EmplaceInternal(buffer, length);
193 auto padding = align - (GetLength() % align);
196 }
else if (!MaybeCreateNewBuffer()) {
201 return EmplaceInternal(buffer, length);
204 const std::shared_ptr<DeviceBuffer>& HostBuffer::GetCurrentBuffer()
const {
205 return device_buffers_[frame_index_][current_buffer_];
211 while (device_buffers_[frame_index_].size() > current_buffer_ + 1) {
212 device_buffers_[frame_index_].pop_back();
216 current_buffer_ = 0u;