MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GpuDispatchCore.cpp
Go to the documentation of this file.
1#include "GpuDispatchCore.hpp"
2
4
5namespace MayaFlux::Yantra {
6
8 : m_gpu_config(std::move(config))
9{
11}
12
13//==============================================================================
14// Public interface
15//==============================================================================
16
17void GpuDispatchCore::set_push_constants(const void* data, size_t bytes)
18{
19 m_push_constants.resize(bytes);
20 std::memcpy(m_push_constants.data(), data, bytes);
21}
22
23void GpuDispatchCore::set_output_size(size_t index, size_t byte_size)
24{
25 if (index >= m_output_size_overrides.size())
26 m_output_size_overrides.resize(index + 1, 0);
27 m_output_size_overrides[index] = byte_size;
28}
29
37
42
43std::shared_ptr<Core::VKImage> GpuDispatchCore::get_output_image(size_t binding_index) const
44{
45 if (binding_index >= m_image_bindings.size())
46 return nullptr;
47 return m_image_bindings[binding_index].image;
48}
49
54
55//==============================================================================
56// Protected staging helpers
57//==============================================================================
58
59void GpuDispatchCore::stage_passthrough(size_t binding_index, const void* data, size_t byte_size)
60{
61 if (binding_index >= m_passthrough_bytes.size())
62 m_passthrough_bytes.resize(binding_index + 1);
63 auto& slot = m_passthrough_bytes[binding_index];
64 slot.resize(byte_size);
65 std::memcpy(slot.data(), data, byte_size);
66}
67
68void GpuDispatchCore::stage_image_at(size_t binding_index,
69 std::shared_ptr<Core::VKImage> image,
71 vk::Sampler sampler)
72{
73 if (binding_index >= m_image_bindings.size())
74 m_image_bindings.resize(binding_index + 1);
75 m_image_bindings[binding_index] = {
76 .image = std::move(image),
77 .sampler = (kind == GpuBufferBinding::ElementType::IMAGE_SAMPLED) ? sampler : nullptr,
78 .kind = kind,
79 };
80}
81
82void GpuDispatchCore::stage_native_bytes(size_t binding_index, const void* data, size_t byte_size)
83{
84 if (binding_index >= m_native_staging_bytes.size())
85 m_native_staging_bytes.resize(binding_index + 1);
86
87 m_native_staging_bytes.resize(byte_size);
88 std::memcpy(m_native_staging_bytes.data(), data, byte_size);
89}
90
91//==============================================================================
92// Virtual override points
93//==============================================================================
94
95std::vector<GpuBufferBinding> GpuDispatchCore::declare_buffer_bindings() const
96{
97 return {
98 { .set = 0, .binding = 0, .direction = GpuBufferBinding::Direction::INPUT, .element_type = GpuBufferBinding::ElementType::FLOAT32 },
99 { .set = 0, .binding = 1, .direction = GpuBufferBinding::Direction::OUTPUT, .element_type = GpuBufferBinding::ElementType::FLOAT32 },
100 };
101}
102
104 const std::vector<std::vector<double>>&,
105 const DataStructureInfo&)
106{
107}
108
110 const std::vector<std::vector<double>>& channels,
111 const DataStructureInfo& structure_info)
112{
113 const auto& key = dispatch_key();
114
115 flatten_channels_to_staging(channels, structure_info);
116 const size_t float_byte_size = m_staging_floats.size() * sizeof(float);
117
118 const size_t fallback_bytes = float_byte_size > 0
119 ? float_byte_size
120 : Kakshya::ContainerDataStructure::get_total_elements(structure_info.dimensions) * sizeof(float);
121
122 std::vector<GpuResourceManager::ImageBind> image_binds;
123
124 for (auto b : m_bindings) {
125 const size_t idx = b.binding;
126
127 if (idx < m_binding_data.size() && !m_binding_data[idx].empty()) {
129 m_resources.upload_raw(key, idx, m_binding_data[idx].data(), m_binding_data[idx].size());
130 continue;
131 }
132
133 if (b.direction == GpuBufferBinding::Direction::OUTPUT) {
134 const auto et = b.element_type;
137 } else {
138 const size_t sz = (idx < m_output_size_overrides.size() && m_output_size_overrides[idx] > 0)
140 : fallback_bytes;
141 m_resources.ensure_buffer(key, idx, sz);
142 if (idx < m_output_size_overrides.size() && m_output_size_overrides[idx] > 0) {
143 std::vector<uint8_t> zeros(sz, 0);
144 m_resources.upload_raw(key, idx, zeros.data(), sz);
145 }
146 continue;
147 }
148 }
149
150 switch (b.element_type) {
152 if (idx < m_passthrough_bytes.size() && !m_passthrough_bytes[idx].empty()) {
154 m_resources.upload_raw(key, idx, m_passthrough_bytes[idx].data(),
156 }
157 break;
158
160 if (idx >= m_image_bindings.size() || !m_image_bindings[idx].image)
161 continue;
162 auto& img = m_image_bindings[idx].image;
163 if (img->get_current_layout() != vk::ImageLayout::eGeneral) {
164 m_resources.transition_image(img, img->get_current_layout(),
165 vk::ImageLayout::eGeneral);
166 }
167 image_binds.push_back({ .index = idx, .image = img, .sampler = nullptr, .spec = b });
168 } break;
169
171 if (idx >= m_image_bindings.size() || !m_image_bindings[idx].image)
172 continue;
173 auto& img = m_image_bindings[idx].image;
174 auto sampler = m_image_bindings[idx].sampler;
175 if (img->get_current_layout() != vk::ImageLayout::eShaderReadOnlyOptimal) {
176 m_resources.transition_image(img, img->get_current_layout(),
177 vk::ImageLayout::eShaderReadOnlyOptimal);
178 }
179 image_binds.push_back({ .index = idx, .image = img, .sampler = sampler, .spec = b });
180 } break;
181
184 if (!channels.empty()) {
185 const size_t raw_bytes = channels[0].size()
187 ? sizeof(uint32_t)
188 : sizeof(int32_t));
189 m_resources.ensure_buffer(key, idx, raw_bytes);
190 m_resources.upload_raw(key, idx,
191 reinterpret_cast<const uint8_t*>(channels[0].data()),
192 raw_bytes);
193 }
194 break;
195
197 default:
198 if (!m_native_staging_bytes.empty()) {
201 } else {
202 m_resources.ensure_buffer(key, idx, float_byte_size);
203 m_resources.upload(key, idx, m_staging_floats.data(), float_byte_size);
204 }
205 break;
206 }
207 }
208
209 if (!image_binds.empty())
210 m_resources.bind_images_batch(key, image_binds);
211}
212
214 size_t total_elements, const DataStructureInfo& structure_info) const
215{
216 uint64_t sz_x = 0, sz_y = 0, sz_z = 0;
217 for (const auto& dim : structure_info.dimensions) {
218 switch (dim.role) {
220 sz_x = dim.size;
221 break;
223 sz_y = dim.size;
224 break;
226 sz_z = dim.size;
227 break;
228 default:
229 break;
230 }
231 }
232
233 const auto& ws = m_gpu_config.workgroup_size;
234 if (sz_x > 0) {
235 return {
236 static_cast<uint32_t>((sz_x + ws[0] - 1) / ws[0]),
237 sz_y > 0 ? static_cast<uint32_t>((sz_y + ws[1] - 1) / ws[1]) : 1U,
238 sz_z > 0 ? static_cast<uint32_t>((sz_z + ws[2] - 1) / ws[2]) : 1U,
239 };
240 }
241
242 return { static_cast<uint32_t>((total_elements + ws[0] - 1) / ws[0]), 1U, 1U };
243}
244
245//==============================================================================
246// Dispatch
247//==============================================================================
248
250 const std::vector<std::vector<double>>& channels,
251 const DataStructureInfo& structure_info)
252{
253 on_before_gpu_dispatch(channels, structure_info);
254 prepare_gpu_inputs(channels, structure_info);
255
257
258 const size_t effective = m_staging_floats.empty()
260 : m_staging_floats.size();
261 const auto groups = calculate_dispatch_size(effective, structure_info);
262
264 dispatch_key(), groups, m_bindings,
265 m_push_constants.empty() ? nullptr : m_push_constants.data(),
266 m_push_constants.size());
267
268 GpuChannelResult result;
269 result.primary = readback_primary(effective);
270 readback_aux(result);
271 return result;
272}
273
275 const std::vector<std::vector<double>>& channels,
276 const DataStructureInfo& structure_info,
277 const ExecutionContext& ctx)
278{
279 on_before_gpu_dispatch(channels, structure_info);
280 prepare_gpu_inputs(channels, structure_info);
281
283
284 const size_t effective = m_staging_floats.empty()
286 : m_staging_floats.size();
287 const auto groups = calculate_dispatch_size(effective, structure_info);
288
290 dispatch_key(), groups, m_bindings,
292
293 GpuChannelResult result;
294 result.primary = readback_primary(effective);
295 readback_aux(result);
296 return result;
297}
298
300 const std::vector<std::vector<double>>& channels,
301 const DataStructureInfo& structure_info,
302 const ExecutionContext& ctx)
303{
304 on_before_gpu_dispatch(channels, structure_info);
305 prepare_gpu_inputs(channels, structure_info);
306
308 if (!ensure_gpu_ready()) {
309 error<std::runtime_error>(Journal::Component::Yantra,
311 std::source_location::current(),
312 "GpuDispatchCore: dispatch_core_chained_indirect GPU initialisation failed");
313 }
314
316
317 const size_t effective = m_staging_floats.empty()
319 : m_staging_floats.size();
320 const auto groups = calculate_dispatch_size(effective, structure_info);
321
322 const auto indirect_it = std::ranges::find_if(m_bindings, [](const auto& b) {
324 });
325 if (indirect_it == m_bindings.end()) {
326 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::Runtime,
327 std::source_location::current(),
328 "GpuDispatchCore: dispatch_core_chained_indirect requires a binding with usage_hint INDIRECT");
329 }
330
332 dispatch_key(), indirect_it->set, indirect_it->binding, groups, m_bindings,
334
335 GpuChannelResult result;
336 result.primary = readback_primary(effective);
337 readback_aux(result);
338 return result;
339}
340
342 const std::vector<std::vector<double>>& channels,
343 const DataStructureInfo& structure_info)
344{
345 on_before_gpu_dispatch(channels, structure_info);
346 prepare_gpu_inputs(channels, structure_info);
347
349
350 const size_t effective = m_staging_floats.empty()
352 : m_staging_floats.size();
353 const auto groups = calculate_dispatch_size(effective, structure_info);
354
356
358 dispatch_key(), groups, m_bindings,
359 m_push_constants.empty() ? nullptr : m_push_constants.data(),
360 m_push_constants.size());
361}
362
363void GpuDispatchCore::dispatch_core_dependency(const std::vector<DependencyStage>& stages)
364{
365 const auto plan = prepare_dependency(stages);
366 m_resources.dispatch_sequence(plan.keys, plan.groups, plan.push_constants, plan.hazards, plan.indirect);
367}
368
370{
371 const auto plan = prepare_dependency(stages);
372 return m_resources.dispatch_sequence_async(plan.keys, plan.groups, plan.push_constants, plan.hazards, plan.indirect);
373}
374
376{
377 const GpuComputeConfig original_config = m_gpu_config;
378 const auto original_bindings = m_bindings;
379 const auto original_image_bindings = m_image_bindings;
380 const auto original_binding_data = m_binding_data;
381 const auto original_passthrough_bytes = m_passthrough_bytes;
382 const auto original_push_constants = m_push_constants;
383
384 DependencyPlan plan;
385 auto& keys = plan.keys;
386 auto& groups_per_key = plan.groups;
387 auto& pc_per_key = plan.push_constants;
388 auto& hazards_per_key = plan.hazards;
389 auto& indirect_per_key = plan.indirect;
390
391 keys.reserve(stages.size());
392 groups_per_key.reserve(stages.size());
393 pc_per_key.reserve(stages.size());
394 hazards_per_key.reserve(stages.size());
395 indirect_per_key.reserve(stages.size());
396
397 for (const auto& stage : stages) {
398 m_gpu_config = stage.config;
401 m_image_bindings.clear();
402 m_binding_data.clear();
403 m_passthrough_bytes.clear();
404 m_push_constants.clear();
405
406 stage.stage_fn(*this);
407
408 if (!ensure_gpu_ready()) {
409 error<std::runtime_error>(Journal::Component::Yantra,
411 std::source_location::current(),
412 "GpuDispatchCore: dispatch_core_dependency failed to initialise key '{}'",
413 stage.config.shader_path);
414 }
415
416 prepare_gpu_inputs({}, {});
417
419
420 keys.push_back(dispatch_key());
421 groups_per_key.push_back(stage.explicit_groups ? *stage.explicit_groups : calculate_dispatch_size(largest_binding_data_element_count(), {}));
422 pc_per_key.push_back(m_push_constants);
423 hazards_per_key.push_back(stage.hazard_fn ? stage.hazard_fn(*this) : std::vector<Portal::Graphics::HazardResource> {});
424
426 if (stage.indirect_groups) {
427 indirect.buffer = m_resources.shared_buffer_handle(stage.indirect_groups->set, stage.indirect_groups->binding).buffer;
428 indirect.offset = stage.indirect_groups->offset_bytes;
429 }
430 indirect_per_key.push_back(indirect);
431 }
432
433 m_gpu_config = original_config;
435 m_bindings = original_bindings;
436 m_image_bindings = original_image_bindings;
437 m_binding_data = original_binding_data;
438 m_passthrough_bytes = original_passthrough_bytes;
439 m_push_constants = original_push_constants;
440
441 return plan;
442}
443
444//==============================================================================
445// Readback helpers
446//==============================================================================
447
448std::vector<float> GpuDispatchCore::readback_primary(size_t float_count)
449{
450 const size_t idx = find_first_output_index();
451
452 for (const auto& b : m_bindings) {
453 if (b.binding != idx)
454 continue;
457 return {};
458 break;
459 }
460
461 const size_t allocated = m_resources.buffer_allocated_bytes(dispatch_key(), idx);
462 const size_t byte_size = std::min(float_count * sizeof(float), allocated);
463 std::vector<float> out(byte_size / sizeof(float));
464 m_resources.download(dispatch_key(), idx, out.data(), byte_size);
465 return out;
466}
467
469{
470 for (const auto& b : m_bindings) {
471 if (b.skip_auto_readback)
472 continue;
473
474 const size_t idx = b.binding;
475 const bool is_image = b.element_type == GpuBufferBinding::ElementType::IMAGE_STORAGE
477
478 if ((b.direction == GpuBufferBinding::Direction::OUTPUT
480 && !is_image
481 && idx < m_output_size_overrides.size()
482 && m_output_size_overrides[idx] > 0) {
483 const size_t sz = m_output_size_overrides[idx];
484 std::vector<uint8_t> raw(sz);
485 m_resources.download(dispatch_key(), idx, reinterpret_cast<float*>(raw.data()), sz);
486 result.aux[idx] = std::move(raw);
487 }
488 }
489}
490
491void GpuDispatchCore::download_binding(size_t index, void* dest, size_t byte_size)
492{
493 m_resources.download(dispatch_key(), index, reinterpret_cast<float*>(dest), byte_size);
494}
495
496//==============================================================================
497// Internal helpers
498//==============================================================================
499
501 const std::vector<std::vector<double>>& channels,
502 const DataStructureInfo& structure_info)
503{
504 m_staging_floats.clear();
506
507 if (Kakshya::is_structured_modality(structure_info.modality))
508 return;
509
510 bool all_inputs_staged = !m_bindings.empty();
511 for (size_t i = 0; i < m_bindings.size(); ++i) {
513 continue;
514 if (i >= m_binding_data.size() || m_binding_data[i].empty()) {
515 all_inputs_staged = false;
516 break;
517 }
518 }
519 if (all_inputs_staged)
520 return;
521
522 size_t total = 0;
523
524 for (const auto& ch : channels)
525 total += ch.size();
526 m_staging_floats.reserve(total);
527
528 for (const auto& ch : channels) {
529 for (double v : ch)
530 m_staging_floats.push_back(static_cast<float>(v));
531 }
532}
533
535 const std::vector<Kakshya::DataVariant>& variants,
536 const DataStructureInfo& structure_info)
537{
539
540 if (variants.empty() || Kakshya::is_structured_modality(structure_info.modality))
541 return;
542
543 size_t total_bytes = 0;
544 for (const auto& v : variants) {
545 std::visit([&](const auto& vec) {
546 total_bytes += vec.size() * sizeof(typename std::decay_t<decltype(vec)>::value_type);
547 },
548 v);
549 }
550
551 m_native_staging_bytes.reserve(total_bytes);
552
553 for (const auto& v : variants) {
554 std::visit([&](const auto& vec) {
555 using T = typename std::decay_t<decltype(vec)>::value_type;
556 const auto* bytes = reinterpret_cast<const uint8_t*>(vec.data());
559 bytes,
560 bytes + vec.size() * sizeof(T));
561 },
562 v);
563 }
564}
565
567{
568 size_t first_inout = SIZE_MAX;
569 for (const auto& b : m_bindings) {
570 if (b.direction == GpuBufferBinding::Direction::OUTPUT)
571 return b.binding;
573 && first_inout == SIZE_MAX)
574 first_inout = b.binding;
575 }
576 if (first_inout != SIZE_MAX)
577 return first_inout;
578
579 error<std::runtime_error>(Journal::Component::Yantra,
581 std::source_location::current(),
582 "GpuDispatchCore: no output buffer declared");
583}
584
586{
587 size_t max_bytes = 0;
588 for (const auto& b : m_bindings) {
589 if (b.direction == GpuBufferBinding::Direction::OUTPUT)
590 continue;
591 const size_t idx = b.binding;
592 if (idx < m_binding_data.size() && !m_binding_data[idx].empty())
593 max_bytes = std::max(max_bytes, m_binding_data[idx].size());
594 }
595 return max_bytes / sizeof(float);
596}
597
604
609
610} // namespace MayaFlux::Yantra
IO::ImageData image
Definition Decoder.cpp:47
bool size
uint32_t total
size_t b
AttributeKind kind
std::vector< float > * out
uint32_t index
Definition VKDevice.cpp:122
uint32_t channels
DependencyPlan prepare_dependency(const std::vector< DependencyStage > &stages)
void readback_aux(GpuChannelResult &result)
Read back all OUTPUT bindings that have explicit size overrides into the aux map of a GpuChannelResul...
void stage_image_at(size_t binding_index, std::shared_ptr< Core::VKImage > image, GpuBufferBinding::ElementType kind, vk::Sampler sampler=nullptr)
Register a VKImage at an explicit binding index.
std::vector< ImageBinding > m_image_bindings
virtual std::array< uint32_t, 3 > calculate_dispatch_size(size_t total_elements, const DataStructureInfo &structure_info) const
Calculate workgroup dispatch counts from structure dimensions.
bool is_gpu_ready() const
Query GPU readiness without attempting initialisation.
const GpuComputeConfig & gpu_config() const
std::vector< uint8_t > m_native_staging_bytes
Native-typed staging buffer.
void download_binding(size_t index, void *dest, size_t byte_size)
Read back a specific binding into a caller-provided destination.
std::shared_ptr< Core::VKImage > get_output_image(size_t binding_index) const
Return the image registered at an IMAGE_STORAGE output binding.
GpuDispatchCore(GpuComputeConfig config)
Portal::Graphics::FenceID dispatch_core_dependency_async(const std::vector< DependencyStage > &stages)
Non-blocking variant of dispatch_core_dependency.
const std::string & dispatch_key() const
The key used for this context's GpuResourceManager unit.
std::vector< uint8_t > m_push_constants
std::vector< std::vector< uint8_t > > m_binding_data
void flatten_native_variants_to_staging(const std::vector< Kakshya::DataVariant > &variants, const DataStructureInfo &structure_info)
Flatten native-typed DataVariant channels into m_native_staging_bytes without any conversion.
GpuChannelResult dispatch_core(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info)
Full single-pass dispatch.
void stage_passthrough(size_t binding_index, const void *data, size_t byte_size)
Stage raw bytes for a PASSTHROUGH binding before dispatch.
Portal::Graphics::FenceID dispatch_core_async(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info)
Non-blocking variant of dispatch_core.
std::vector< GpuBufferBinding > m_bindings
bool ensure_gpu_ready()
Ensure GPU resources are initialised.
std::vector< size_t > m_output_size_overrides
void dispatch_core_dependency(const std::vector< DependencyStage > &stages)
Multi-pipeline dependency dispatch.
GpuChannelResult dispatch_core_chained(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info, const ExecutionContext &ctx)
Multi-pass (chained) dispatch.
virtual void prepare_gpu_inputs(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info)
Marshal channel data into GPU input buffers.
std::vector< std::vector< uint8_t > > m_passthrough_bytes
void stage_native_bytes(size_t binding_index, const void *data, size_t byte_size)
Stage a flat native-typed byte buffer for FLOAT32 bindings, bypassing the double-to-float cast in fla...
virtual void on_before_gpu_dispatch(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info)
Called immediately before dispatch.
void set_output_size(size_t index, size_t byte_size)
Declare the byte capacity of an output binding independently of input data.
std::vector< float > readback_primary(size_t float_count)
Read back the primary output buffer into a float vector.
GpuChannelResult dispatch_core_chained_indirect(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info, const ExecutionContext &ctx)
Multi-pass dispatch where a GPU-resident indirect buffer gates each pass's workgroup count instead of...
void flatten_channels_to_staging(const std::vector< std::vector< double > > &channels, const DataStructureInfo &structure_info)
Flatten planar double channels into m_staging_floats.
virtual std::vector< GpuBufferBinding > declare_buffer_bindings() const
Declare the storage buffers the shader expects.
void set_push_constants(const void *data, size_t bytes)
Set push constant data from a raw byte pointer.
void dispatch_batched_indirect(const std::string &key, uint32_t indirect_set, size_t indirect_binding, const std::array< uint32_t, 3 > &groups, const std::vector< GpuBufferBinding > &bindings, size_t push_constant_size, const ExecutionContext &ctx)
void download(const std::string &key, size_t index, float *dest, size_t byte_size)
bool initialise(const std::string &key, const GpuComputeConfig &config, const std::vector< GpuBufferBinding > &bindings)
Create (or confirm existing) pipeline for the given key.
bool is_ready(const std::string &key) const
void bind_descriptors_batch(const std::string &key, const std::vector< GpuBufferBinding > &bindings)
Bind every non-image buffer binding in one Vulkan call.
void bind_images_batch(const std::string &key, const std::vector< ImageBind > &images)
Bind every image in one Vulkan call.
void dispatch_sequence(const std::vector< std::string > &keys, const std::vector< std::array< uint32_t, 3 > > &groups_per_key, const std::vector< std::vector< uint8_t > > &push_constants_per_key, const std::vector< std::vector< Portal::Graphics::HazardResource > > &hazards_per_key, const std::vector< Portal::Graphics::IndirectDispatch > &indirect_per_key={})
Record a dispatch for each requested key into one command buffer via ComputePress::record_sequence,...
void upload(const std::string &key, size_t index, const float *data, size_t byte_size)
void transition_image(const std::shared_ptr< Core::VKImage > &image, vk::ImageLayout old_layout, vk::ImageLayout new_layout)
Transition a VKImage layout via an immediate command submission.
void dispatch(const std::string &key, const std::array< uint32_t, 3 > &groups, const std::vector< GpuBufferBinding > &bindings, const uint8_t *push_constant_data, size_t push_constant_size)
Portal::Graphics::FenceID dispatch_async(const std::string &key, const std::array< uint32_t, 3 > &groups, const std::vector< GpuBufferBinding > &bindings, const uint8_t *push_constant_data, size_t push_constant_size)
Submit a compute dispatch without blocking.
Portal::Graphics::FenceID dispatch_sequence_async(const std::vector< std::string > &keys, const std::vector< std::array< uint32_t, 3 > > &groups_per_key, const std::vector< std::vector< uint8_t > > &push_constants_per_key, const std::vector< std::vector< Portal::Graphics::HazardResource > > &hazards_per_key, const std::vector< Portal::Graphics::IndirectDispatch > &indirect_per_key={})
Non-blocking counterpart of dispatch_sequence.
void dispatch_batched(const std::string &key, const std::array< uint32_t, 3 > &groups, const std::vector< GpuBufferBinding > &bindings, size_t push_constant_size, const ExecutionContext &ctx)
void ensure_buffer(const std::string &key, size_t index, size_t required_bytes, Portal::Graphics::BufferUsageHint usage_hint=Portal::Graphics::BufferUsageHint::COMPUTE_STORAGE)
void upload_raw(const std::string &key, size_t index, const uint8_t *data, size_t byte_size)
Portal::Graphics::GpuBufferHandle shared_buffer_handle(uint32_t set, size_t binding_index) const
Non-owning view of the shared buffer at (set, binding_index).
size_t buffer_allocated_bytes(const std::string &key, size_t index) const
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Runtime
General runtime operations (default fallback)
@ Yantra
DSP algorithms, computational units, matrix operations, Grammar.
bool is_structured_modality(DataModality modality)
Check if a modality represents structured data (vectors, matrices).
Definition NDData.hpp:170
@ INDIRECT
Indirect draw/dispatch buffer (device-local)
bool is_image(const fs::path &filepath)
Definition Depot.cpp:136
@ SPATIAL_X
Spatial X axis (images, tensors)
ElementType
Element type the shader expects in this binding.
enum MayaFlux::Portal::Graphics::GpuBufferBinding::Direction INPUT
enum MayaFlux::Portal::Graphics::GpuBufferBinding::ElementType FLOAT32
Plain-data description of the compute shader to dispatch.
Optional GPU-resident source of a stage's workgroup counts.
std::vector< Kakshya::DataDimension > dimensions
Dimensions, modality, source type, and optional Composite field schema.
Context information controlling how a compute operation executes.
std::unordered_map< size_t, std::vector< uint8_t > > aux
Erased output of a GPU dispatch: reconstructed float data plus any raw auxiliary outputs keyed by bin...
std::vector< std::vector< uint8_t > > push_constants
std::vector< Portal::Graphics::IndirectDispatch > indirect
std::vector< std::vector< Portal::Graphics::HazardResource > > hazards
std::vector< std::array< uint32_t, 3 > > groups