11 const std::string& name,
12 const std::shared_ptr<Nodes::GpuSync::TextureNode>& node,
13 const std::shared_ptr<VKBuffer>& texture)
16 error<std::invalid_argument>(
19 std::source_location::current(),
20 "Cannot bind null texture node '{}'", name);
24 error<std::invalid_argument>(
27 std::source_location::current(),
28 "Cannot bind texture node '{}' to null texture buffer", name);
31 size_t texture_size =
static_cast<size_t>(node->get_width()) *
static_cast<size_t>(node->get_height()) * 4 *
sizeof(
float);
33 if (texture->get_size_bytes() < texture_size) {
34 error<std::invalid_argument>(
37 std::source_location::current(),
38 "Texture buffer for '{}' is too small: {} bytes required, {} available",
39 name, texture_size, texture->get_size_bytes());
42 std::shared_ptr<VKBuffer> staging =
nullptr;
43 if (!texture->is_host_visible()) {
47 "Created staging buffer for device-local texture '{}' ({} bytes)",
51 "No staging needed for host-visible texture '{}'", name);
56 .gpu_texture = texture,
57 .staging_buffer = staging
61 "Bound texture node '{}' ({}x{}, {} bytes)",
62 name, node->get_width(), node->get_height(), texture_size);
69 "Attempted to unbind non-existent texture node '{}'", name);
72 "Unbound texture node '{}'", name);
78 std::vector<std::string> names;
81 names.push_back(name);
92 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
95 "TextureBindingsProcessor requires VKBuffer, got different buffer type");
99 bool attached_is_host_visible = vk_buffer->is_host_visible();
102 if (!binding.node->needs_gpu_update()) {
104 "Texture '{}' unchanged, skipping upload", name);
108 auto pixels = binding.node->get_pixel_buffer();
110 if (pixels.empty()) {
112 "Texture node '{}' has empty pixel buffer, skipping upload", name);
120 binding.staging_buffer);
122 binding.node->clear_gpu_update_flag();
126 auto& first_binding =
m_bindings.begin()->second;
128 bool attached_is_target =
false;
129 for (
const auto& [name, binding] :
m_bindings) {
130 if (binding.gpu_texture == vk_buffer) {
131 attached_is_target =
true;
136 if (!attached_is_target) {
137 auto pixels = first_binding.node->get_pixel_buffer();
139 if (!pixels.empty()) {
140 std::shared_ptr<VKBuffer> staging = attached_is_host_visible ? nullptr : first_binding.staging_buffer;
#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,...)
void bind_texture_node(const std::string &name, const std::shared_ptr< Nodes::GpuSync::TextureNode > &node, const std::shared_ptr< VKBuffer > &texture)
Bind a texture node to a GPU texture buffer.
void unbind_texture_node(const std::string &name)
Remove a texture binding.
std::vector< std::string > get_binding_names() const
Get all binding names.
void processing_function(std::shared_ptr< Buffer > buffer) override
The core processing function that must be implemented by derived classes.
std::unordered_map< std::string, TextureBinding > m_bindings
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::shared_ptr< Nodes::GpuSync::TextureNode > node