stage/columns/device_heap.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | #include "chrono_batch_render/stage/columns/device_heap.h" | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <utility> | ||
| 6 | |||
| 7 | #include <fmt/format.h> | ||
| 8 | |||
| 9 | #include "chrono_batch_render/device/kernels/shared.h" | ||
| 10 | |||
| 11 | namespace chrono::batch_render { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | |||
| 15 | constexpr uint64_t kFirstChunk = uint64_t(1) << 20; | ||
| 16 | constexpr uint64_t kLargestChunk = uint64_t(64) << 20; | ||
| 17 | |||
| 18 | } | ||
| 19 | |||
| 20 | 523 | DeviceHeap::DeviceHeap(device::Device& device, std::string label) | |
| 21 | 523 | : m_device(device), m_label(std::move(label)), m_nextChunk(kFirstChunk) {} | |
| 22 | |||
| 23 | 1 | uint64_t DeviceHeap::Bytes() const { | |
| 24 | 1 | uint64_t bytes = 0; | |
| 25 | 1 | for (const Chunk& chunk : m_chunks) { | |
| 26 | ✗ | bytes += chunk.buffer->Bytes(); | |
| 27 | } | ||
| 28 | 1 | return bytes; | |
| 29 | } | ||
| 30 | |||
| 31 | 38030 | HeapBlock DeviceHeap::Allocate(uint64_t bytes, uint64_t alignment) { | |
| 32 | 38030 | if (bytes == 0) { | |
| 33 | 1 | return {}; | |
| 34 | } | ||
| 35 | 38029 | bytes = RoundUp(bytes, alignment); | |
| 36 | 38029 | std::vector<HeapBlock>& free = m_free[bytes]; | |
| 37 | 38029 | const auto aligned = std::ranges::find_if( | |
| 38 | 144 | free, [&](const HeapBlock& block) { return block.offset % alignment == 0; }); | |
| 39 | 38029 | if (aligned != free.end()) { | |
| 40 | 143 | const HeapBlock block = *aligned; | |
| 41 | 143 | free.erase(aligned); | |
| 42 | 143 | return block; | |
| 43 | } | ||
| 44 | 75250 | const auto fits = [&](const Chunk& chunk) { | |
| 45 | 37364 | return RoundUp(chunk.used, alignment) + bytes <= chunk.buffer->Bytes(); | |
| 46 | 37886 | }; | |
| 47 | 37886 | if (m_chunks.empty() || !fits(m_chunks.back())) { | |
| 48 | 524 | const uint64_t chunkBytes = std::max(m_nextChunk, bytes); | |
| 49 | 524 | m_nextChunk = std::min(m_nextChunk * 2, kLargestChunk); | |
| 50 | 524 | m_chunks.push_back( | |
| 51 | 524 | {m_device.CreateBuffer( | |
| 52 | {.bytes = chunkBytes, | ||
| 53 | .usage = device::BufferUsage::Interop | device::BufferUsage::AccelBuildInput, | ||
| 54 | 1048 | .label = fmt::format("{} chunk {}", m_label, m_chunks.size())}), | |
| 55 | 0}); | ||
| 56 | } | ||
| 57 | 37886 | Chunk& chunk = m_chunks.back(); | |
| 58 | 37886 | const uint64_t offset = RoundUp(chunk.used, alignment); | |
| 59 | 37886 | chunk.used = offset + bytes; | |
| 60 | 37886 | return {chunk.buffer.Get(), offset, bytes}; | |
| 61 | 1048 | } | |
| 62 | |||
| 63 | 345 | void DeviceHeap::Free(const HeapBlock& block) { | |
| 64 | 345 | if (block) { | |
| 65 | 345 | m_free[block.bytes].push_back(block); | |
| 66 | } | ||
| 67 | 345 | } | |
| 68 | |||
| 69 | } | ||
| 70 |