MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NodeTextureProcessor.cpp
Go to the documentation of this file.
2
7
10
12
13namespace MayaFlux::Buffers {
14
20
22 const std::string& name,
23 const std::shared_ptr<Nodes::GpuSync::TextureNode>& node,
24 const std::shared_ptr<Core::VKImage>& texture)
25{
26 if (!node) {
27 error<std::invalid_argument>(
30 std::source_location::current(),
31 "Cannot bind null texture node '{}'", name);
32 }
33
34 if (!texture) {
35 error<std::invalid_argument>(
38 std::source_location::current(),
39 "Cannot bind texture node '{}' to null VKImage", name);
40 }
41
42 size_t texture_size = static_cast<size_t>(node->get_width())
43 * static_cast<size_t>(node->get_height())
44 * 4
45 * sizeof(float);
46
48 .node = node,
49 .gpu_texture = texture
50 };
51
53 "Bound texture node '{}' ({}x{}, {} bytes)",
54 name, node->get_width(), node->get_height(), texture_size);
55}
56
57void NodeTextureProcessor::unbind_texture_node(const std::string& name)
58{
59 if (m_bindings.erase(name) == 0) {
61 "Attempted to unbind non-existent texture node '{}'", name);
62 } else {
64 "Unbound texture node '{}'", name);
65 }
66}
67
68std::vector<std::string> NodeTextureProcessor::get_binding_names() const
69{
70 std::vector<std::string> names;
71 names.reserve(m_bindings.size());
72 for (const auto& [name, _] : m_bindings) {
73 names.push_back(name);
74 }
75 return names;
76}
77
78std::optional<NodeTextureProcessor::TextureBinding>
79NodeTextureProcessor::get_binding(const std::string& name) const
80{
81 auto it = m_bindings.find(name);
82 if (it != m_bindings.end()) {
83 return it->second;
84 }
85 return std::nullopt;
86}
87
88void NodeTextureProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
89{
90 if (m_bindings.empty()) {
91 return;
92 }
93
94 auto staging_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
95 if (!staging_buffer) {
97 "NodeTextureProcessor requires VKBuffer for staging");
98 return;
99 }
100
102
103 for (auto& [name, binding] : m_bindings) {
104 if (!binding.node->needs_gpu_update()) {
106 "Texture '{}' unchanged, skipping upload", name);
107 continue;
108 }
109
110 auto pixels = binding.node->get_pixel_buffer();
111
112 if (pixels.empty()) {
114 "Texture node '{}' has empty pixel buffer, skipping upload", name);
115 continue;
116 }
117
118 loom.upload_data(
119 binding.gpu_texture,
120 pixels.data(),
121 pixels.size_bytes());
122
123 binding.node->clear_gpu_update_flag();
124
126 "Uploaded texture '{}' ({} bytes)", name, pixels.size_bytes());
127 }
128}
129
130void NodeTextureProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
131{
132 m_attached_buffer = std::dynamic_pointer_cast<NodeTextureBuffer>(buffer);
133 if (!m_attached_buffer) {
134 return;
135 }
136
137 if (!m_buffer_service) {
140 }
141
142 if (!m_buffer_service) {
143 error<std::runtime_error>(
146 std::source_location::current(),
147 "TextureProcessor requires a valid buffer service");
148 }
149
150 if (!m_attached_buffer->is_initialized()) {
151 try {
153 } catch (const std::exception& e) {
154 error_rethrow(
157 std::source_location::current(),
158 "Failed to initialize texture buffer: {}", e.what());
159 }
160 }
161
163}
164
166{
167 if (!m_attached_buffer || m_attached_buffer->m_vertex_bytes.empty()) {
169 "NodeTextureProcessor: no attached buffer or empty vertex data");
170 return;
171 }
172
174 m_attached_buffer->m_vertex_bytes.data(),
175 m_attached_buffer->m_vertex_bytes.size(),
177
179
180 for (auto& [name, binding] : m_bindings) {
181 auto pixels = binding.node->get_pixel_buffer();
182 if (!pixels.empty()) {
183 loom.upload_data(binding.gpu_texture, pixels.data(), pixels.size_bytes());
184 }
185 }
186
188 "NodeTextureProcessor: uploaded {} bytes of vertex geometry",
189 m_attached_buffer->m_vertex_bytes.size());
190}
191
192void NodeTextureProcessor::on_detach(const std::shared_ptr<Buffer>& /*buffer*/)
193{
194 m_attached_buffer.reset();
195}
196
197} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_TRACE(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::shared_ptr< NodeTextureBuffer > m_attached_buffer
void bind_texture_node(const std::string &name, const std::shared_ptr< Nodes::GpuSync::TextureNode > &node, const std::shared_ptr< Core::VKImage > &texture)
Bind a TextureNode to a GPU texture.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
std::unordered_map< std::string, TextureBinding > m_bindings
void processing_function(const std::shared_ptr< Buffer > &buffer) override
Process all texture uploads.
void unbind_texture_node(const std::string &name)
Remove a texture binding.
std::vector< std::string > get_binding_names() const
Get all binding names.
std::optional< TextureBinding > get_binding(const std::string &name) const
Get a specific binding.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
Registry::Service::BufferService * m_buffer_service
Definition VKBuffer.hpp:489
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
@ 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.
MAYAFLUX_API TextureLoom & get_texture_manager()
Get the global texture manager instance.
std::shared_ptr< Nodes::GpuSync::TextureNode > node
Represents a TextureNode → GPU texture binding.
std::function< void(const std::shared_ptr< void > &)> initialize_buffer
Initialize a buffer object.
Backend buffer management service interface.