MayaFlux 0.4.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& staging = buffer->get_pipeline_context().push_constant_staging;
133 const size_t end = static_cast<size_t>(pc.offset) + pc.size;
134
135 if (staging.size() < end)
136 staging.resize(end);
137
138 if (pc.size == sizeof(float)) {
139 std::memcpy(staging.data() + pc.offset, &value, sizeof(float));
140 } else if (pc.size == sizeof(double)) {
141 auto promoted = static_cast<double>(value);
142 std::memcpy(staging.data() + pc.offset, &promoted, sizeof(double));
143 }
144
146 "FormaBindingsProcessor: PC write offset={} value={}", pc.offset, value);
147}
148
150 float value,
151 const DescriptorTarget& desc,
152 const std::shared_ptr<VKBuffer>& attached)
153{
154 upload_to_gpu(&value, sizeof(float), desc.gpu_buffer, nullptr);
155
156 auto& bindings_list = attached->get_pipeline_context().descriptor_buffer_bindings;
157
158 for (auto& entry : bindings_list) {
159 if (entry.set == desc.set_index && entry.binding == desc.binding_index) {
160 entry.buffer_info.buffer = desc.gpu_buffer->get_buffer();
161 entry.buffer_info.offset = 0;
162 entry.buffer_info.range = sizeof(float);
163 return;
164 }
165 }
166
167 bindings_list.push_back({
168 .set = desc.set_index,
169 .binding = desc.binding_index,
171 ? vk::DescriptorType::eUniformBuffer
172 : vk::DescriptorType::eStorageBuffer,
173 .buffer_info = vk::DescriptorBufferInfo {
174 desc.gpu_buffer->get_buffer(), 0, sizeof(float) },
175 });
176}
177
180{
184
185 auto buf = std::make_shared<VKBuffer>(
186 sizeof(float),
187 usage,
189
192
193 if (!svc) {
194 error<std::runtime_error>(
197 std::source_location::current(),
198 "FormaBindingsProcessor: no BufferService available");
199 }
200
201 svc->initialize_buffer(buf);
202 return buf;
203}
204
205} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_DEBUG(comp, ctx,...)
size_t b
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.
@ UNIFORM
Uniform buffer (host-visible)
@ COMPUTE
Storage buffer for compute shaders (device-local)
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)
Backend buffer management service interface.