22 const std::shared_ptr<Allocator>& allocator,
23 const std::shared_ptr<const IdleWaiter>& idle_waiter,
24 size_t minimum_uniform_alignment) {
25 return std::shared_ptr<HostBuffer>(
26 new HostBuffer(allocator, idle_waiter, minimum_uniform_alignment));
29 HostBuffer::HostBuffer(
const std::shared_ptr<Allocator>& allocator,
30 const std::shared_ptr<const IdleWaiter>& idle_waiter,
31 size_t minimum_uniform_alignment)
32 : allocator_(allocator),
33 idle_waiter_(idle_waiter),
34 minimum_uniform_alignment_(minimum_uniform_alignment) {
39 std::shared_ptr<DeviceBuffer> device_buffer = allocator->CreateBuffer(desc);
40 FML_CHECK(device_buffer) <<
"Failed to allocate device buffer.";
41 device_buffers_[i].push_back(device_buffer);
49 idle_waiter_->WaitIdle();
56 auto [range, device_buffer, raw_device_buffer] =
57 EmplaceInternal(buffer, length, align);
59 return BufferView(std::move(device_buffer), range);
60 }
else if (raw_device_buffer) {
68 auto [range, device_buffer, raw_device_buffer] =
69 EmplaceInternal(buffer, length);
71 return BufferView(std::move(device_buffer), range);
72 }
else if (raw_device_buffer) {
73 return BufferView(raw_device_buffer, range);
82 auto [range, device_buffer, raw_device_buffer] =
83 EmplaceInternal(length, align, cb);
85 return BufferView(std::move(device_buffer), range);
86 }
else if (raw_device_buffer) {
96 .current_buffer = current_buffer_,
97 .total_buffer_count = device_buffers_[frame_index_].size(),
101 bool HostBuffer::MaybeCreateNewBuffer() {
103 if (current_buffer_ >= device_buffers_[frame_index_].size()) {
107 std::shared_ptr<DeviceBuffer> buffer = allocator_->CreateBuffer(desc);
112 device_buffers_[frame_index_].push_back(std::move(buffer));
118 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
119 HostBuffer::EmplaceInternal(
size_t length,
121 const EmplaceProc& cb) {
129 DeviceBufferDescriptor desc;
132 std::shared_ptr<DeviceBuffer> device_buffer =
133 allocator_->CreateBuffer(desc);
134 if (!device_buffer) {
138 cb(device_buffer->OnGetContents());
139 device_buffer->Flush(Range{0, length});
141 return std::make_tuple(Range{0, length}, std::move(device_buffer),
nullptr);
145 if (align > 0 && offset_ % align) {
146 padding = align - (offset_ % align);
149 if (!MaybeCreateNewBuffer()) {
156 const std::shared_ptr<DeviceBuffer>& current_buffer = GetCurrentBuffer();
157 auto contents = current_buffer->OnGetContents();
158 cb(contents + offset_);
159 Range output_range(offset_, length);
160 current_buffer->Flush(output_range);
163 return std::make_tuple(output_range,
nullptr, current_buffer.get());
166 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
167 HostBuffer::EmplaceInternal(
const void* buffer,
size_t length) {
171 DeviceBufferDescriptor desc;
174 std::shared_ptr<DeviceBuffer> device_buffer =
175 allocator_->CreateBuffer(desc);
176 if (!device_buffer) {
180 if (!device_buffer->CopyHostBuffer(
static_cast<const uint8_t*
>(buffer),
185 return std::make_tuple(Range{0, length}, std::move(device_buffer),
nullptr);
188 auto old_length = GetLength();
190 if (!MaybeCreateNewBuffer()) {
194 old_length = GetLength();
196 const std::shared_ptr<DeviceBuffer>& current_buffer = GetCurrentBuffer();
197 auto contents = current_buffer->OnGetContents();
199 ::memmove(contents + old_length, buffer, length);
200 current_buffer->Flush(Range{old_length, length});
203 return std::make_tuple(Range{old_length, length},
nullptr,
204 current_buffer.get());
207 std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
208 HostBuffer::EmplaceInternal(
const void* buffer,
size_t length,
size_t align) {
209 if (align == 0 || (GetLength() % align) == 0) {
210 return EmplaceInternal(buffer, length);
214 auto padding = align - (GetLength() % align);
217 }
else if (!MaybeCreateNewBuffer()) {
222 return EmplaceInternal(buffer, length);
225 const std::shared_ptr<DeviceBuffer>& HostBuffer::GetCurrentBuffer()
const {
226 return device_buffers_[frame_index_][current_buffer_];
232 while (device_buffers_[frame_index_].size() > current_buffer_ + 1) {
233 device_buffers_[frame_index_].pop_back();
237 current_buffer_ = 0u;
242 return minimum_uniform_alignment_;
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.
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::function< void(uint8_t *buffer)> EmplaceProc
void Reset()
Resets the contents of the HostBuffer to nothing so it can be reused.
Vector2 padding
The halo padding in source space.
static constexpr const size_t kHostBufferArenaSize
Approximately the same size as the max frames in flight.
constexpr size_t kAllocatorBlockSize
Test only internal state.