10 : m_stride(stride_bytes)
14 error<std::invalid_argument>(
17 std::source_location::current(),
18 "SliceSet: stride must be nonzero");
23 std::span<const uint8_t> bytes,
24 std::optional<Portal::Graphics::PrimitiveTopology>
topology)
28 "SliceSet::add: {} bytes is not a whole number of {} byte vertices",
51 "SliceSet::update: unknown slice {} or {} bytes is not a whole number of {} byte vertices",
56 auto& slice = it->second;
58 if (bytes.size() == slice.byte_size) {
60 std::memcpy(
m_mirror.data() + slice.byte_offset, bytes.data(), bytes.size());
61 mark_dirty(slice.byte_offset, slice.byte_offset + bytes.size());
66 const auto first =
m_mirror.begin() +
static_cast<std::ptrdiff_t
>(slice.byte_offset);
67 m_mirror.erase(first, first +
static_cast<std::ptrdiff_t
>(slice.byte_size));
68 m_mirror.insert(
m_mirror.begin() +
static_cast<std::ptrdiff_t
>(slice.byte_offset),
69 bytes.begin(), bytes.end());
70 slice.byte_size = bytes.size();
85 const Slice slice = it->second;
86 const auto first =
m_mirror.begin() +
static_cast<std::ptrdiff_t
>(slice.byte_offset);
87 m_mirror.erase(first, first +
static_cast<std::ptrdiff_t
>(slice.byte_size));
103 if (it ==
m_slices.end() || it->second.visible == visible) {
107 it->second.visible = visible;
145 std::vector<Portal::Graphics::DrawRun> runs;
147 const auto& slice =
m_slices.at(
id);
148 if (!slice.visible || slice.byte_size == 0) {
152 const auto offset =
static_cast<uint32_t
>(slice.byte_offset /
m_stride);
153 const auto count =
static_cast<uint32_t
>(slice.byte_size /
m_stride);
155 if (is_concatenable_topology(slice.topology) && !runs.empty()
156 && runs.back().topology == slice.topology
157 && runs.back().vertex_offset + runs.back().vertex_count ==
offset) {
158 runs.back().vertex_count +=
count;
162 runs.push_back({ .topology = slice.topology, .vertex_offset =
offset, .vertex_count =
count });
168void SliceSet::flush(
const std::shared_ptr<VKBuffer>& target, std::shared_ptr<VKBuffer>& staging)
171 error<std::invalid_argument>(
174 std::source_location::current(),
175 "SliceSet::flush: target buffer is null");
178 const size_t capacity_before = target->get_size_bytes();
180 if (target->get_size_bytes() != capacity_before) {
190 for (
auto& [start, end] :
m_dirty) {
191 end = std::min(end,
m_mirror.size());
201 if (memory_index > 0) {
203 offset = previous.byte_offset + previous.byte_size;
208 slice.byte_offset =
offset;
209 offset += slice.byte_size;
216 m_dirty.emplace_back(start, end);
#define MF_ERROR(comp, ctx,...)
std::optional< glm::vec3 > position
PrimitiveTopology topology
void remove(SliceId id)
Remove a block; later blocks shift down.
void mark_dirty(size_t start, size_t end)
std::unordered_map< SliceId, Slice > m_slices
std::vector< SliceId > m_draw_order
std::vector< SliceId > m_memory_order
SliceId add(std::span< const uint8_t > bytes, std::optional< Portal::Graphics::PrimitiveTopology > topology=std::nullopt)
Append a block at the end of memory and draw order.
std::optional< std::vector< Portal::Graphics::DrawRun > > take_runs()
Runs for the visible blocks in draw order, if they changed.
SliceSet(uint32_t stride_bytes, Portal::Graphics::PrimitiveTopology topology)
void repack_from(size_t memory_index)
std::vector< uint8_t > m_mirror
void bring_to_front(SliceId id)
Draw a block after every other.
void send_to_back(SliceId id)
Draw a block before every other.
Portal::Graphics::PrimitiveTopology m_topology
void update(SliceId id, std::span< const uint8_t > bytes)
Replace a block's vertices.
std::vector< std::pair< size_t, size_t > > m_dirty
uint32_t vertex_count() const noexcept
Vertices in the mirror, hidden blocks included.
void flush(const std::shared_ptr< VKBuffer > &target, std::shared_ptr< VKBuffer > &staging)
Upload what changed since the last flush.
void set_visible(SliceId id, bool visible)
Hide or show a block without moving its data.
void upload_intervals(const void *base, std::span< const std::pair< size_t, size_t > > intervals, const std::shared_ptr< VKBuffer > &target, std::shared_ptr< VKBuffer > &staging)
Upload several byte ranges of one source to the same offsets in target.
void ensure_gpu_capacity(const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging, size_t required, float growth_factor)
Grow a GPU buffer (and its paired staging buffer) to fit required bytes.
@ BufferManagement
Buffer Management (Buffers::BufferManager, creating buffers)
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
PrimitiveTopology
Vertex assembly primitive topology.