MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FormaBindingsProcessor.cpp
Go to the documentation of this file.
2
8
9namespace MayaFlux::Buffers {
10
12 : ShaderProcessor(shader_path)
13{
14}
15
20
21// =============================================================================
22// Raw reader overloads
23// =============================================================================
24
26 const std::string& name,
27 std::function<float()> reader,
28 uint32_t offset,
29 size_t size)
30{
31 auto& b = m_bindings[name];
33 b.reader = std::move(reader);
34 b.pc = PushConstantTarget { .offset = offset, .size = size };
35 b.desc.reset();
36}
37
39 const std::string& name,
40 std::function<float()> reader,
41 const std::string& descriptor_name,
42 uint32_t binding_index,
43 uint32_t set,
45{
46 if (!reader) {
48 "FormaBindingsProcessor::bind_descriptor: null reader for '{}'", name);
49 return;
50 }
51
52 auto& b = m_bindings[name];
54 b.reader = std::move(reader);
55 b.pc.reset();
56
57 auto gpu_buf = make_descriptor_buffer(role);
58
59 b.desc = DescriptorTarget {
60 .descriptor_name = descriptor_name,
61 .set_index = set,
62 .binding_index = binding_index,
63 .role = role,
64 .gpu_buffer = gpu_buf,
65 .buffer_size = sizeof(float),
66 };
67
68 bind_buffer(descriptor_name, gpu_buf);
70}
71
72// =============================================================================
73// Introspection
74// =============================================================================
75
76bool FormaBindingsProcessor::has_binding(const std::string& name) const
77{
78 return m_bindings.contains(name);
79}
80
81std::vector<std::string> FormaBindingsProcessor::get_binding_names() const
82{
83 std::vector<std::string> names;
84 names.reserve(m_bindings.size());
85 for (const auto& [k, _] : m_bindings) {
86 names.push_back(k);
87 }
88 return names;
89}
90
91bool FormaBindingsProcessor::unbind(const std::string& name)
92{
93 return m_bindings.erase(name) > 0;
94}
95
96// =============================================================================
97// ShaderProcessor hook
98// =============================================================================
99
100void FormaBindingsProcessor::execute_shader(const std::shared_ptr<VKBuffer>& buffer)
101{
102 for (const auto& [name, b] : m_bindings) {
103 if (!b.reader) {
105 "FormaBindingsProcessor: binding '{}' has no reader", name);
106 continue;
107 }
108
109 const float value = b.reader();
110 switch (b.kind) {
112 if (b.pc)
113 flush_push_constant(value, *b.pc, buffer);
114 break;
116 if (b.desc)
117 flush_descriptor(value, *b.desc, buffer);
118 break;
119 }
120 }
121}
122
123// =============================================================================
124// Private
125// =============================================================================
126
128 float value,
129 const PushConstantTarget& pc,
130 const std::shared_ptr<VKBuffer>& buffer)
131{
132 auto& entries = buffer->get_pipeline_context().push_constant_bindings;
133
134 auto it = std::ranges::find_if(entries, [&](const auto& e) {
135 return e.offset == pc.offset;
136 });
137
138 if (it == entries.end()) {
140 .offset = pc.offset,
141 .data = std::vector<uint8_t>(pc.size) });
142 it = std::prev(entries.end());
143 }
144
145 if (pc.size == sizeof(float)) {
146 std::memcpy(it->data.data(), &value, sizeof(float));
147 } else if (pc.size == sizeof(double)) {
148 auto promoted = static_cast<double>(value);
149 std::memcpy(it->data.data(), &promoted, sizeof(double));
150 }
151
153 "FormaBindingsProcessor: PC write offset={} value={}", pc.offset, value);
154}
155
157 float value,
158 const DescriptorTarget& desc,
159 const std::shared_ptr<VKBuffer>& attached)
160{
161 upload_to_gpu(&value, sizeof(float), desc.gpu_buffer, nullptr);
162
163 auto& bindings_list = attached->get_pipeline_context().descriptor_buffer_bindings;
164
165 for (auto& entry : bindings_list) {
166 if (entry.set == desc.set_index && entry.binding == desc.binding_index) {
167 entry.buffer_info.buffer = desc.gpu_buffer->get_buffer();
168 entry.buffer_info.offset = 0;
169 entry.buffer_info.range = sizeof(float);
170 return;
171 }
172 }
173
174 bindings_list.push_back({
175 .set = desc.set_index,
176 .binding = desc.binding_index,
178 ? vk::DescriptorType::eUniformBuffer
179 : vk::DescriptorType::eStorageBuffer,
180 .buffer_info = vk::DescriptorBufferInfo {
181 desc.gpu_buffer->get_buffer(), 0, sizeof(float) },
182 });
183}
184
187{
189 ? VKBuffer::Usage::UNIFORM
190 : VKBuffer::Usage::COMPUTE;
191
192 auto buf = std::make_shared<VKBuffer>(
193 sizeof(float),
194 usage,
196
199
200 if (!svc) {
201 error<std::runtime_error>(
204 std::source_location::current(),
205 "FormaBindingsProcessor: no BufferService available");
206 }
207
208 svc->initialize_buffer(buf);
209 return buf;
210}
211
212} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_DEBUG(comp, ctx,...)
size_t b
float value
float offset
float k
void flush_descriptor(float value, const DescriptorTarget &desc, const std::shared_ptr< VKBuffer > &attached)
void bind_descriptor(const std::string &name, std::function< float()> reader, const std::string &descriptor_name, uint32_t binding_index, uint32_t set, Portal::Graphics::DescriptorRole role=Portal::Graphics::DescriptorRole::UNIFORM)
Bind a type-erased reader to a descriptor binding.
static std::shared_ptr< VKBuffer > make_descriptor_buffer(Portal::Graphics::DescriptorRole role)
bool unbind(const std::string &name)
Remove a binding by name.
bool has_binding(const std::string &name) const
Returns true if a binding with name exists.
void flush_push_constant(float value, const PushConstantTarget &pc, const std::shared_ptr< VKBuffer > &buffer)
void execute_shader(const std::shared_ptr< VKBuffer > &buffer) override
std::vector< std::string > get_binding_names() const
Returns all registered binding names.
FormaBindingsProcessor(const std::string &shader_path)
std::unordered_map< std::string, Binding > m_bindings
void bind_push_constant(const std::string &name, std::function< float()> reader, uint32_t offset, size_t size=sizeof(float))
Bind a type-erased reader to a push constant slot.
void bind_buffer(const std::string &descriptor_name, const std::shared_ptr< VKBuffer > &buffer)
Bind a VKBuffer to a named shader descriptor.
Abstract base class for shader-based buffer processing.
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
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.
@ UNKNOWN
Unknown or undefined modality.
DescriptorRole
Semantic descriptor type — maps to Vulkan descriptor types internally.
@ UNIFORM
Small, read-only, frequently updated (scalars, param structs)
BufferUsageHint
Semantic usage hint for buffer allocation and memory properties.
Self-describing push constant fragment staged on a VKBuffer.
Backend buffer management service interface.