MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataWriteProcessor.cpp
Go to the documentation of this file.
2
4#include "StagingUtils.hpp"
5
7
13
15
17
18namespace MayaFlux::Buffers {
19
24
26{
27 m_data_pending.clear();
28 m_data_pending.push_back(std::move(variant));
29 m_data_dirty.test_and_set(std::memory_order_release);
30}
31
32void DataWriteProcessor::set_data(std::vector<Kakshya::DataVariant> variants)
33{
34 m_data_pending = std::move(variants);
35 m_data_dirty.test_and_set(std::memory_order_release);
36}
37
38void DataWriteProcessor::set_vertices(const void* data, size_t byte_count)
39{
40 const auto* src = static_cast<const uint8_t*>(data);
41 m_data_pending = { Kakshya::DataVariant { std::vector<uint8_t>(src, src + byte_count) } };
42 m_data_dirty.test_and_set(std::memory_order_release);
43}
44
45void DataWriteProcessor::set_texture(std::shared_ptr<Core::VKImage> image, std::string binding)
46{
47 m_pending_texture = PendingTexture { .image = std::move(image), .binding = std::move(binding) };
48 m_texture_dirty.test_and_set(std::memory_order_release);
49}
50
52{
53 m_pixel_pending = std::move(variant);
54 m_pixel_dirty.test_and_set(std::memory_order_release);
55}
56
58 uint32_t width,
59 uint32_t height,
61 std::string binding)
62{
64 m_tex_height = height;
65 m_tex_format = format;
66 m_tex_binding = std::move(binding);
67}
68
70{
71 return m_data_dirty.test(std::memory_order_acquire);
72}
73
78
79void DataWriteProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
80{
81 auto vk = std::dynamic_pointer_cast<VKBuffer>(buffer);
82 if (!vk) {
83 error<std::invalid_argument>(
86 std::source_location::current(),
87 "DataWriteProcessor requires a VKBuffer");
88 }
89
90 m_modality = vk->get_modality();
91 m_topology = vk->get_render_config().topology;
92
93 if (!vk->is_host_visible()) {
94 m_staging = create_staging_buffer(vk->get_size_bytes());
95 }
96
99 vk->set_vertex_layout(Kakshya::VertexLayout::for_raw());
100 } else {
101 switch (m_topology) {
104 vk->set_vertex_layout(Kakshya::VertexLayout::for_lines());
105 break;
108 vk->set_vertex_layout(Kakshya::VertexLayout::for_meshes());
109 break;
110 default:
111 vk->set_vertex_layout(Kakshya::VertexLayout::for_points());
112 break;
113 }
114 }
115 }
116
118 "DataWriteProcessor attached (modality: {}, staging: {})",
120 m_staging ? "yes" : "no");
121}
122
123void DataWriteProcessor::on_detach(const std::shared_ptr<Buffer>& /*buffer*/)
124{
125 m_staging.reset();
126 m_pending_texture.reset();
127 m_data_pending.clear();
128 m_active.clear();
129
130 m_pixel_pending = {};
131 m_pixel_active = {};
133
135}
136
137void DataWriteProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
138{
139 auto vk = std::dynamic_pointer_cast<VKBuffer>(buffer);
140 if (!vk) {
142 "DataWriteProcessor attached to non-VKBuffer");
143 return;
144 }
145
146 if (m_texture_dirty.test(std::memory_order_acquire)) {
147 m_texture_dirty.clear(std::memory_order_release);
148 if (m_pending_texture) {
149 if (auto rp = vk->get_render_processor()) {
150 rp->bind_texture(m_pending_texture->binding, m_pending_texture->image);
151 }
152 m_pending_texture.reset();
153 }
154 }
155
156 if (m_pixel_dirty.test(std::memory_order_acquire)) {
157 m_pixel_dirty.clear(std::memory_order_release);
160 }
161
162 if (m_gpu_texture) {
163 if (auto rp = vk->get_render_processor()) {
165 rp->bind_texture(m_tex_binding, m_gpu_texture);
167 }
168 }
169 }
170
171 if (!m_data_dirty.test(std::memory_order_acquire)) {
172 return;
173 }
174
175 m_data_dirty.clear(std::memory_order_release);
176 std::swap(m_active, m_data_pending);
177
178 if (m_active.empty()) {
179 return;
180 }
181
183
184 for (size_t i = 1; i < m_active.size(); ++i) {
185 if (i == 1 && m_tex_width > 0 && is_vertex_modality(m_modality)) {
186 upload_texture(vk, m_active[i]);
187 } else {
189 }
190 }
191}
192
193void DataWriteProcessor::upload_primary(const std::shared_ptr<VKBuffer>& vk, std::vector<Kakshya::DataVariant>& slots)
194{
196 upload_vertex(vk, slots);
197 } else if (is_texture_modality(m_modality)) {
198 upload_texture(vk, slots[0]);
199 } else {
200 upload_raw(vk, slots[0]);
201 }
202}
203
204void DataWriteProcessor::upload_secondary(const std::shared_ptr<VKBuffer>& vk, Kakshya::DataVariant& slot)
205{
206 auto bytes = Kakshya::convert_variant<uint8_t>(slot);
207 ensure_capacity(vk, bytes.size_bytes());
208 upload_to_gpu(bytes.data(), bytes.size_bytes(), vk, m_staging);
209}
210
211void DataWriteProcessor::upload_vertex(const std::shared_ptr<VKBuffer>& vk, std::vector<Kakshya::DataVariant>& slots)
212{
213 std::optional<Kakshya::VertexAccess> access;
214
215 switch (m_topology) {
218 access = Kakshya::as_line_vertex_access(slots);
219 break;
222 access = Kakshya::as_mesh_vertex_access(slots);
223 break;
224 default:
225 access = Kakshya::as_point_vertex_access(slots);
226 break;
227 }
228
229 if (!access) {
231 "DataWriteProcessor: vertex access failed for modality {}",
233 return;
234 }
235
236 ensure_capacity(vk, access->byte_count);
237 upload_to_gpu(access->data_ptr, access->byte_count, vk, m_staging);
238 vk->set_vertex_layout(access->layout);
239}
240
241void DataWriteProcessor::upload_texture(const std::shared_ptr<VKBuffer>& vk, Kakshya::DataVariant& slot)
242{
243 auto access = Kakshya::as_texture_access(slot);
244 if (!access) {
246 "DataWriteProcessor: as_texture_access failed for modality {}",
248 return;
249 }
250
251 m_last_texture_format = access->format;
252
253 if (m_tex_width == 0 || m_tex_height == 0) {
255 "DataWriteProcessor: setup_pixel_target() not called before texture upload");
256 return;
257 }
258
260
261 if (!m_gpu_texture) {
262 m_gpu_texture = loom.create_2d(m_tex_width, m_tex_height, m_tex_format, nullptr, 1);
263 if (!m_gpu_texture) {
265 "DataWriteProcessor: failed to create GPU texture {}x{}",
267 return;
268 }
270 if (auto rp = vk->get_render_processor()) {
271 rp->bind_texture(m_tex_binding, m_gpu_texture);
272 }
273 }
274
275 loom.upload_data(m_gpu_texture, access->data_ptr, access->byte_count, m_image_staging);
276}
277
278void DataWriteProcessor::upload_raw(const std::shared_ptr<VKBuffer>& vk, Kakshya::DataVariant& slot)
279{
280 Kakshya::DataAccess accessor(slot, {}, m_modality);
281 auto [ptr, bytes, fmt] = accessor.gpu_buffer();
282
283 ensure_capacity(vk, bytes);
284 upload_to_gpu(ptr, bytes, vk, m_staging);
285}
286
287void DataWriteProcessor::ensure_capacity(const std::shared_ptr<VKBuffer>& vk, size_t required)
288{
289 if (required <= vk->get_size_bytes()) {
290 return;
291 }
292
293 vk->resize(static_cast<size_t>(static_cast<float>(required) * 1.5F), false);
294
295 if (m_staging) {
296 m_staging = create_staging_buffer(vk->get_size_bytes());
297 }
298}
299
315
330
331} // namespace MayaFlux::Buffers
#define MF_RT_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
IO::ImageData image
Definition Decoder.cpp:57
uint32_t width
Definition Decoder.cpp:59
const uint8_t * ptr
void upload_secondary(const std::shared_ptr< VKBuffer > &vk, Kakshya::DataVariant &slot)
std::vector< Kakshya::DataVariant > m_data_pending
void set_pixel_data(Kakshya::DataVariant variant)
Supply pixel data for the co-resident texture on the next cycle.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
static bool is_vertex_modality(Kakshya::DataModality m) noexcept
Portal::Graphics::ImageFormat m_tex_format
void set_vertices(const void *data, size_t byte_count)
Supply pre-packed interleaved vertex bytes for the next cycle.
void upload_texture(const std::shared_ptr< VKBuffer > &vk, Kakshya::DataVariant &slot)
void ensure_capacity(const std::shared_ptr< VKBuffer > &vk, size_t required)
Portal::Graphics::PrimitiveTopology m_topology
void set_data(Kakshya::DataVariant variant)
Supply a single data value for the next cycle (slot 0).
std::shared_ptr< Core::VKImage > m_gpu_texture
void upload_raw(const std::shared_ptr< VKBuffer > &vk, Kakshya::DataVariant &slot)
std::optional< PendingTexture > m_pending_texture
void upload_vertex(const std::shared_ptr< VKBuffer > &vk, std::vector< Kakshya::DataVariant > &slots)
void setup_pixel_target(uint32_t width, uint32_t height, Portal::Graphics::ImageFormat format, std::string binding="texSampler")
Configure the pixel upload path for texture modalities.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
std::vector< Kakshya::DataVariant > m_active
void upload_primary(const std::shared_ptr< VKBuffer > &vk, std::vector< Kakshya::DataVariant > &slots)
void set_texture(std::shared_ptr< Core::VKImage > image, std::string binding)
Supply a texture to bind on the next graphics tick.
Kakshya::GpuDataFormat last_texture_format() const noexcept
Returns the GpuDataFormat resolved on the last texture upload.
bool has_pending() const noexcept
Returns true if a snapshot has been set and not yet consumed.
std::shared_ptr< VKBuffer > m_image_staging
static bool is_texture_modality(Kakshya::DataModality m) noexcept
auto gpu_buffer() const
Get raw buffer info for GPU upload.
Type-erased accessor for NDData with semantic view construction.
std::shared_ptr< VKBuffer > create_image_staging_buffer(size_t size)
Allocate a persistent host-visible staging buffer sized for repeated streaming uploads to an image of...
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
std::shared_ptr< VKBuffer > create_staging_buffer(size_t size)
Create staging buffer for transfers.
void upload_to_gpu(const void *data, size_t size, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging)
Upload raw data to GPU buffer (auto-detects host-visible vs device-local)
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
std::optional< VertexAccess > as_line_vertex_access(std::span< const DataVariant > channels, const VertexAccessConfig &config)
Assemble line-vertex-compatible bytes from one or more data channels.
std::optional< VertexAccess > as_point_vertex_access(std::span< const DataVariant > channels, const VertexAccessConfig &config)
Assemble point-vertex-compatible bytes from one or more data channels.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:76
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:81
@ SPECTRAL_2D
2D spectral data (time + frequency)
@ UNKNOWN
Unknown or undefined modality.
@ VERTICES_3D
3D vertex data (positions, normals, etc.)
@ VIDEO_GRAYSCALE
3D video (time + 2D grayscale)
@ VIDEO_COLOR
4D video (time + 2D + color)
@ IMAGE_COLOR
2D RGB/RGBA image
@ IMAGE_2D
2D image (grayscale or single channel)
GpuDataFormat
GPU data formats with explicit precision levels.
Definition NDData.hpp:11
std::string_view modality_to_string(DataModality modality)
Convert DataModality enum to string representation.
Definition NDData.cpp:83
std::optional< VertexAccess > as_mesh_vertex_access(std::span< const DataVariant > channels, const VertexAccessConfig &config)
Assemble mesh-vertex-compatible bytes from one or more data channels.
std::optional< TextureAccess > as_texture_access(const DataVariant &variant)
Extract a TextureAccess from a DataVariant.
MAYAFLUX_API TextureLoom & get_texture_manager()
Get the global texture manager instance.
ImageFormat
User-friendly image format enum.
static VertexLayout for_raw(uint32_t stride=60)
Factory: layout for raw vertex data with common attributes.
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)