MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
SliceSet.hpp
Go to the documentation of this file.
1#pragma once
2
5
6namespace MayaFlux::Buffers {
7
8/**
9 * @class SliceSet
10 * @brief Many vertex blocks laid out in one buffer, drawn as few runs.
11 *
12 * Holds a CPU mirror of the whole batch that shares offsets with the GPU
13 * buffer. Blocks are identified by id, placed contiguously in the order they
14 * were added, and share one stride. Each carries a topology, defaulting to the
15 * set's, so a render processor that triangulates can draw mixed spans as one
16 * batch; one that does not needs every slice to match its own topology. Draw
17 * order is independent
18 * of memory order: bring_to_front, send_to_back and set_visible only change
19 * the run list, never move vertex data. Runs adjacent in both memory and draw
20 * order and of the same topology are coalesced, so an in-order visible batch
21 * is a single run. Strip and fan topologies are never coalesced, since joining
22 * their runs would fabricate a primitive across the seam.
23 *
24 * Same-size updates write into the mirror and mark one dirty range. Adding
25 * appends. Resizing or removing a block shifts the blocks after it, which are
26 * then uploaded as one range.
27 *
28 * Apply runs with RenderProcessor::set_runs and pair them with
29 * set_vertex_range: a single run is not honoured by the multi-run draw, which
30 * otherwise draws the buffer's whole vertex count.
31 *
32 * Not thread safe.
33 */
34class MAYAFLUX_API SliceSet {
35public:
36 using SliceId = uint32_t;
37
38 /**
39 * @param stride_bytes Bytes per vertex; every block must be a whole multiple.
40 * @param topology Topology of a block added without one.
41 */
43
44 /**
45 * @brief Append a block at the end of memory and draw order.
46 * @param bytes Whole vertices.
47 * @param topology Topology of this block; the set's default when omitted.
48 * @return Id of the block, or 0 if @p bytes is not a whole number of vertices.
49 */
50 SliceId add(std::span<const uint8_t> bytes,
51 std::optional<Portal::Graphics::PrimitiveTopology> topology = std::nullopt);
52
53 /**
54 * @brief Replace a block's vertices.
55 *
56 * Same size writes in place. A different size shifts every later block.
57 */
58 void update(SliceId id, std::span<const uint8_t> bytes);
59
60 /** @brief Remove a block; later blocks shift down. */
61 void remove(SliceId id);
62
63 /** @brief Hide or show a block without moving its data. */
64 void set_visible(SliceId id, bool visible);
65
66 /** @brief Draw a block after every other. */
67 void bring_to_front(SliceId id);
68
69 /** @brief Draw a block before every other. */
70 void send_to_back(SliceId id);
71
72 /** @brief Vertices in the mirror, hidden blocks included. */
73 [[nodiscard]] uint32_t vertex_count() const noexcept;
74
75 /** @brief Bytes in the mirror. */
76 [[nodiscard]] size_t size_bytes() const noexcept { return m_mirror.size(); }
77
78 /** @brief Number of live blocks. */
79 [[nodiscard]] size_t size() const noexcept { return m_slices.size(); }
80
81 /** @brief True when @p id names a live block. */
82 [[nodiscard]] bool contains(SliceId id) const noexcept { return m_slices.contains(id); }
83
84 /**
85 * @brief Runs for the visible blocks in draw order, if they changed.
86 * @return The new run list once after each change, then nullopt.
87 */
88 [[nodiscard]] std::optional<std::vector<Portal::Graphics::DrawRun>> take_runs();
89
90 /**
91 * @brief Upload what changed since the last flush.
92 * @param target Destination buffer, grown here when the mirror outgrew it.
93 * @param staging Staging buffer for device-local targets, grown as needed.
94 *
95 * Growing discards the target's contents, so a grow uploads the whole mirror.
96 */
97 void flush(const std::shared_ptr<VKBuffer>& target, std::shared_ptr<VKBuffer>& staging);
98
99private:
100 struct Slice {
101 size_t byte_offset {};
102 size_t byte_size {};
104 bool visible { true };
105 };
106
107 void repack_from(size_t memory_index);
108 void mark_dirty(size_t start, size_t end);
109
110 uint32_t m_stride;
112 SliceId m_next_id { 1 };
113
114 std::unordered_map<SliceId, Slice> m_slices;
115 std::vector<SliceId> m_memory_order;
116 std::vector<SliceId> m_draw_order;
117 std::vector<uint8_t> m_mirror;
118 std::vector<std::pair<size_t, size_t>> m_dirty;
119 bool m_runs_changed { true };
120 bool m_all_dirty { false };
121};
122
123} // namespace MayaFlux::Buffers
PrimitiveTopology topology
std::unordered_map< SliceId, Slice > m_slices
Definition SliceSet.hpp:114
std::vector< SliceId > m_draw_order
Definition SliceSet.hpp:116
std::vector< SliceId > m_memory_order
Definition SliceSet.hpp:115
std::vector< uint8_t > m_mirror
Definition SliceSet.hpp:117
Portal::Graphics::PrimitiveTopology m_topology
Definition SliceSet.hpp:111
std::vector< std::pair< size_t, size_t > > m_dirty
Definition SliceSet.hpp:118
size_t size() const noexcept
Number of live blocks.
Definition SliceSet.hpp:79
bool contains(SliceId id) const noexcept
True when id names a live block.
Definition SliceSet.hpp:82
Many vertex blocks laid out in one buffer, drawn as few runs.
Definition SliceSet.hpp:34
PrimitiveTopology
Vertex assembly primitive topology.