MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FormaProcessor.cpp
Go to the documentation of this file.
1#include "FormaProcessor.hpp"
2
7
8namespace MayaFlux::Buffers {
9
10namespace {
11
13 {
14 switch (topology) {
20 default:
22 }
23 }
24
25}
26
34
35std::span<const uint8_t> FormaProcessor::whole_vertices(const std::vector<uint8_t>& bytes) const noexcept
36{
37 return { bytes.data(), bytes.size() - bytes.size() % m_stride };
38}
39
40void FormaProcessor::set_bytes(const std::vector<uint8_t>& bytes)
41{
42 if (m_default_slice == 0) {
44 } else {
46 }
47 m_changed = true;
48}
49
51 const std::vector<uint8_t>& bytes,
52 std::optional<Portal::Graphics::PrimitiveTopology> topology)
53{
54 m_changed = true;
55 return m_slices.add(whole_vertices(bytes), topology);
56}
57
58void FormaProcessor::update_slice(SliceId id, const std::vector<uint8_t>& bytes)
59{
60 m_slices.update(id, whole_vertices(bytes));
61 m_changed = true;
62}
63
65{
66 if (id == m_default_slice) {
68 }
69 m_slices.remove(id);
70 m_changed = true;
71}
72
74{
75 m_slices.set_visible(id, visible);
76 m_changed = true;
77}
78
84
90
91bool FormaProcessor::has_pending() const noexcept
92{
93 return m_changed;
94}
95
96void FormaProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
97{
98 auto vk = std::dynamic_pointer_cast<VKBuffer>(buffer);
99 if (!vk) {
100 error<std::invalid_argument>(
103 std::source_location::current(),
104 "FormaProcessor requires a VKBuffer");
105 }
106
107 m_staging = create_staging_buffer(vk->get_size_bytes());
108
109 switch (m_topology) {
111 vk->set_vertex_layout(Kakshya::VertexLayout::for_points());
112 break;
115 vk->set_vertex_layout(Kakshya::VertexLayout::for_lines());
116 break;
119 default:
120 vk->set_vertex_layout(Kakshya::VertexLayout::for_meshes());
121 break;
122 }
123}
124
125void FormaProcessor::on_detach(const std::shared_ptr<Buffer>& /*buffer*/)
126{
127 m_staging.reset();
129 m_default_slice = 0;
130 m_changed = false;
131 m_pending_runs.reset();
132}
133
134void FormaProcessor::set_texture(std::shared_ptr<Core::VKImage> image, std::string binding)
135{
136 m_pending_texture = PendingTexture { .image = std::move(image), .binding = std::move(binding) };
137 m_texture_dirty.test_and_set(std::memory_order_release);
138}
139
140void FormaProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
141{
142 if (m_texture_dirty.test(std::memory_order_acquire)) {
143 auto vk = std::dynamic_pointer_cast<VKBuffer>(buffer);
144 if (vk) {
145 if (auto rp = vk->get_render_processor()) {
146 if (m_pending_texture) {
147 rp->bind_texture(m_pending_texture->binding,
148 m_pending_texture->image);
149 }
150 m_pending_texture.reset();
151 m_texture_dirty.clear(std::memory_order_release);
152 }
153 }
154 }
155
156 if (!m_changed && !m_pending_runs)
157 return;
158
159 auto vk = std::dynamic_pointer_cast<VKBuffer>(buffer);
160 if (!vk)
161 return;
162
163 if (m_changed) {
164 m_changed = false;
166 if (auto runs = m_slices.take_runs()) {
167 m_pending_runs = std::move(runs);
168 }
169 }
170
171 if (m_pending_runs) {
172 apply_runs(vk);
173 }
174}
175
176void FormaProcessor::apply_runs(const std::shared_ptr<VKBuffer>& buffer)
177{
178 const auto total = m_slices.vertex_count();
179 const auto run_count = m_pending_runs->size();
181 const bool whole = run_count == 1 && first.vertex_offset == 0 && first.vertex_count == total;
182
183 if (auto layout = buffer->get_vertex_layout()) {
184 layout->vertex_count = run_count == 0 ? 0U : total;
185 buffer->set_vertex_layout(*layout);
186 }
187
188 auto render = buffer->get_render_processor();
189 if (!render) {
190 if (whole || run_count == 0) {
191 m_pending_runs.reset();
192 }
193 return;
194 }
195
196 if (run_count > 1) {
197 render->set_runs(std::move(*m_pending_runs));
198 render->set_vertex_range(0, 0);
199 } else {
200 if (run_count == 1 && first.topology != m_topology) {
201 render->set_runs({ first });
202 } else {
203 render->set_runs({});
204 }
205 if (run_count == 1 && !whole) {
206 render->set_vertex_range(first.vertex_offset, first.vertex_count);
207 } else {
208 render->set_vertex_range(0, 0);
209 }
210 }
211
212 m_pending_runs.reset();
213}
214
215} // namespace MayaFlux::Buffers
IO::ImageData image
Definition Decoder.cpp:47
std::shared_ptr< NetworkGeometryBuffer > buffer
uint32_t total
uint32_t run_count
PrimitiveTopology topology
Portal::Graphics::PrimitiveTopology m_topology
void apply_runs(const std::shared_ptr< VKBuffer > &buffer)
void remove_slice(SliceId id)
Remove a slice; later slices shift down.
void set_texture(std::shared_ptr< Core::VKImage > image, std::string binding)
Supply a texture to bind on the next graphics tick.
FormaProcessor(Portal::Graphics::PrimitiveTopology topology)
void set_slice_visible(SliceId id, bool visible)
Hide or show a slice without moving its data.
void set_bytes(const std::vector< uint8_t > &bytes)
Replace the default slice with new vertex bytes.
void bring_slice_to_front(SliceId id)
Draw a slice after every other.
std::shared_ptr< VKBuffer > m_staging
std::span< const uint8_t > whole_vertices(const std::vector< uint8_t > &bytes) const noexcept
std::optional< PendingTexture > m_pending_texture
void update_slice(SliceId id, const std::vector< uint8_t > &bytes)
Replace a slice's vertices; later slices shift if the size changes.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
void send_slice_to_back(SliceId id)
Draw a slice before every other.
bool has_pending() const noexcept
True when geometry or slice changes await the next tick.
std::optional< std::vector< Portal::Graphics::DrawRun > > m_pending_runs
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
SliceId add_slice(const std::vector< uint8_t > &bytes, std::optional< Portal::Graphics::PrimitiveTopology > topology=std::nullopt)
Append a slice, drawn after the existing ones.
void remove(SliceId id)
Remove a block; later blocks shift down.
Definition SliceSet.cpp:78
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.
Definition SliceSet.cpp:22
std::optional< std::vector< Portal::Graphics::DrawRun > > take_runs()
Runs for the visible blocks in draw order, if they changed.
Definition SliceSet.cpp:138
void bring_to_front(SliceId id)
Draw a block after every other.
Definition SliceSet.cpp:111
void send_to_back(SliceId id)
Draw a block before every other.
Definition SliceSet.cpp:122
void update(SliceId id, std::span< const uint8_t > bytes)
Replace a block's vertices.
Definition SliceSet.cpp:46
uint32_t vertex_count() const noexcept
Vertices in the mirror, hidden blocks included.
Definition SliceSet.cpp:133
void flush(const std::shared_ptr< VKBuffer > &target, std::shared_ptr< VKBuffer > &staging)
Upload what changed since the last flush.
Definition SliceSet.cpp:168
void set_visible(SliceId id, bool visible)
Hide or show a block without moving its data.
Definition SliceSet.cpp:100
Many vertex blocks laid out in one buffer, drawn as few runs.
Definition SliceSet.hpp:34
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
std::shared_ptr< VKBuffer > create_staging_buffer(size_t size)
Create staging buffer for transfers.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
PrimitiveTopology
Vertex assembly primitive topology.
uint32_t stride_bytes
Total bytes per vertex (stride in Vulkan terms) e.g., 3 floats (position) + 3 floats (normal) = 24 by...
static VertexLayout for_lines(uint32_t stride=60)
Factory: layout for LineVertex (position, color, thickness, uv, normal, tangent)
static VertexLayout for_meshes(uint32_t stride=60)
Factory: layout for MeshVertex (position, color, weight, uv, normal, tangent)
static VertexLayout for_points(uint32_t stride=60)
Factory: layout for PointVertex (position, color, size, uv, normal, tangent)
One contiguous span of vertices sharing a primitive topology.