MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureProcessor.cpp
Go to the documentation of this file.
2
5#include "TextureBuffer.hpp"
6
9
12
14
16
17namespace MayaFlux::Buffers {
18
24
26
27void TextureProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
28{
29 if (!m_buffer_service) {
32 }
33
34 if (!m_buffer_service) {
35 error<std::runtime_error>(
38 std::source_location::current(),
39 "TextureProcessor requires a valid buffer service");
40 }
41
42 auto tex_buffer = std::dynamic_pointer_cast<TextureBuffer>(buffer);
43 if (!tex_buffer) {
44 return;
45 }
46
47 m_texture_buffer = tex_buffer;
48
49 if (!tex_buffer->is_initialized()) {
50 try {
52 } catch (const std::exception& e) {
53 error_rethrow(
56 std::source_location::current(),
57 "Failed to initialize texture buffer: {}", e.what());
58 }
59 }
60
62
63 if (auto rp = tex_buffer->get_render_processor()) {
64 rp->bind_texture(
65 tex_buffer->get_render_config().default_texture_binding,
66 tex_buffer->get_texture());
67 }
68
70 "TextureProcessor attached to {}x{} TextureBuffer",
71 tex_buffer->get_width(), tex_buffer->get_height());
72}
73
74void TextureProcessor::on_detach(const std::shared_ptr<Buffer>& /*buffer*/)
75{
76 m_texture_buffer.reset();
77 m_stream_staging.reset();
78}
79
80void TextureProcessor::processing_function(const std::shared_ptr<Buffer>& /*buffer*/)
81{
82 if (!m_texture_buffer) {
83 return;
84 }
85
87
89}
90
91// =========================================================================
92// Initialization
93// =========================================================================
94
96{
97 if (!m_texture_buffer) {
98 return;
99 }
100
101 if (!m_texture_buffer->has_texture()) {
102 m_texture_buffer->m_gpu_texture = create_gpu_texture();
103 }
104
106
108
109 m_texture_buffer->m_texture_dirty = false;
110 m_texture_buffer->m_geometry_dirty = false;
111
113 "TextureProcessor: GPU resources initialized");
114}
115
117{
118 if (!m_texture_buffer || m_texture_buffer->m_vertex_bytes.empty()) {
119 return;
120 }
121
122 try {
124 m_texture_buffer->m_vertex_bytes.data(),
125 m_texture_buffer->m_vertex_bytes.size(),
127
129 "TextureProcessor: uploaded {} bytes of geometry data",
130 m_texture_buffer->m_vertex_bytes.size());
131 } catch (const std::exception& e) {
133 "Failed to upload initial geometry: {}", e.what());
134 }
135}
136
138{
139 if (!m_texture_buffer || !m_texture_buffer->has_texture()) {
140 return;
141 }
142
143 const auto& pixel_data = m_texture_buffer->m_pixel_data;
144 if (pixel_data.empty()) {
146 "TextureProcessor: no pixel data to upload (uninitialized texture)");
147 return;
148 }
149
151 loom.upload_data(
152 m_texture_buffer->get_texture(),
153 pixel_data.data(),
154 pixel_data.size());
155
157 "TextureProcessor: uploaded {} bytes of pixel data", pixel_data.size());
158}
159
160// =========================================================================
161// Per-Frame Updates
162// =========================================================================
163
165{
166 if (!m_texture_buffer || !m_texture_buffer->m_geometry_dirty) {
167 return;
168 }
169
170 m_texture_buffer->generate_quad_with_transform();
171
172 try {
174 m_texture_buffer->m_vertex_bytes.data(),
175 m_texture_buffer->m_vertex_bytes.size(),
177
178 m_texture_buffer->m_geometry_dirty = false;
179
181 "TextureProcessor: geometry updated and uploaded");
182 } catch (const std::exception& e) {
184 "Failed to update geometry: {}", e.what());
185 }
186}
187
189{
190 if (!m_texture_buffer || !m_texture_buffer->m_texture_dirty) {
191 return;
192 }
193
195 auto variant = get_variant_source();
196 if (!variant) {
197 m_texture_buffer->m_texture_dirty = false;
198 return;
199 }
200
201 if (!m_texture_buffer->has_texture()) {
202 m_texture_buffer->m_gpu_texture = create_gpu_texture();
203 }
204
206
209 m_texture_buffer->get_texture()->get_size_bytes());
210 }
211
212 auto access = Kakshya::as_texture_access(*variant);
213 if (!access) {
214 m_texture_buffer->m_texture_dirty = false;
215 return;
216 }
217
219 loom.upload_data(
220 m_texture_buffer->get_texture(),
221 access->data_ptr,
222 access->byte_count,
224 } else {
225 loom.upload_data(
226 m_texture_buffer->get_texture(),
227 access->data_ptr,
228 access->byte_count);
229 }
230
231 m_texture_buffer->m_texture_dirty = false;
232
234 "TextureProcessor: external variant data updated ({} bytes)", access->byte_count);
235 return;
236 }
237
238 if (!m_texture_buffer->has_texture()) {
239 m_texture_buffer->m_gpu_texture = create_gpu_texture();
240
241 if (auto rp = m_texture_buffer->get_render_processor()) {
242 rp->bind_texture(
243 m_texture_buffer->get_render_config().default_texture_binding,
244 m_texture_buffer->get_texture());
245 }
246 }
247
248 const auto& pixel_data = m_texture_buffer->m_pixel_data;
249 if (pixel_data.empty()) {
250 return;
251 }
252
254
257 m_texture_buffer->get_texture()->get_size_bytes());
258 }
259
261 loom.upload_data(
262 m_texture_buffer->get_texture(),
263 pixel_data.data(),
264 pixel_data.size(),
266 } else {
267 loom.upload_data(
268 m_texture_buffer->get_texture(),
269 pixel_data.data(),
270 pixel_data.size());
271 }
272
273 m_texture_buffer->m_texture_dirty = false;
274
276 "TextureProcessor: pixel data updated ({} bytes)", pixel_data.size());
277}
278
279// =========================================================================
280// GPU Resource Creation
281// =========================================================================
282
283std::shared_ptr<Core::VKImage> TextureProcessor::create_gpu_texture()
284{
285 if (!m_texture_buffer) {
286 return nullptr;
287 }
288
290
291 auto texture = loom.create_2d(
292 m_texture_buffer->get_width(),
293 m_texture_buffer->get_height(),
294 m_texture_buffer->get_format(),
295 nullptr,
296 1);
297
298 if (!texture) {
299 error<std::runtime_error>(
302 std::source_location::current(),
303 "Failed to create GPU texture via TextureLoom");
304 }
305
307 "TextureProcessor: created GPU VKImage {}x{}",
308 m_texture_buffer->get_width(), m_texture_buffer->get_height());
309
310 return texture;
311}
312
313void TextureProcessor::generate_quad_vertices(std::vector<uint8_t>& out_bytes)
314{
315 // Helper for future enhancements (actual transform application)
316 // For now, this is called by TextureBuffer::generate_quad_with_transform()
317 // Future: apply m_position, m_scale, m_rotation here
318}
319
320} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::shared_ptr< Core::VKImage > create_gpu_texture()
Create VKImage for texture storage.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
void update_geometry_if_dirty()
Regenerate quad vertices if transform changed, upload if needed.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
void initialize_gpu_resources()
Initialize all GPU resources:
void update_pixels_if_dirty()
Re-upload pixels to GPU if they changed.
virtual std::optional< Kakshya::DataVariant > get_variant_source()
void upload_initial_pixels()
Upload initial pixel data to GPU texture.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void generate_quad_vertices(std::vector< uint8_t > &out_bytes)
Generate quad vertices respecting current transform Handles both default quad and custom vertices.
std::shared_ptr< TextureBuffer > m_texture_buffer
std::shared_ptr< Buffers::VKBuffer > m_stream_staging
Persistent host-visible staging buffer for streaming pixel uploads.
void upload_initial_geometry()
Upload initial quad geometry based on default or custom vertices.
Registry::Service::BufferService * m_buffer_service
Definition VKBuffer.hpp:651
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
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.
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< 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.
std::function< void(const std::shared_ptr< void > &)> initialize_buffer
Initialize a buffer object.
Backend buffer management service interface.