MayaFlux 0.5.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 for (auto b : m_bindings) {
123 const size_t idx = b.binding;
124
125 if (idx < m_binding_data.size() && !m_binding_data[idx].empty()) {
126 m_resources.ensure_buffer(key, idx, m_binding_data[idx].size());
127 m_resources.upload_raw(key, idx, m_binding_data[idx].data(), m_binding_data[idx].size());
128 continue;
129 }
130
131 if (b.direction == GpuBufferBinding::Direction::OUTPUT) {
132 const auto et = b.element_type;
135 } else {
136 const size_t sz = (idx < m_output_size_overrides.size() && m_output_size_overrides[idx] > 0)
138 : fallback_bytes;
139 m_resources.ensure_buffer(key, idx, sz);
140 if (idx < m_output_size_overrides.size() && m_output_size_overrides[idx] > 0) {
141 std::vector<uint8_t> zeros(sz, 0);
142 m_resources.upload_raw(key, idx, zeros.data(), sz);
143 }
144 continue;
145 }
146 }
147
148 switch (b.element_type) {
150 if (idx < m_passthrough_bytes.size() && !m_passthrough_bytes[idx].empty()) {
151 m_resources.ensure_buffer(key, idx, m_passthrough_bytes[idx].size());
152 m_resources.upload_raw(key, idx, m_passthrough_bytes[idx].data(),
153 m_passthrough_bytes[idx].size());
154 }
155 break;
156
158 if (idx >= m_image_bindings.size() || !m_image_bindings[idx].image)
159 continue;
160 auto& img = m_image_bindings[idx].image;
161 if (img->get_current_layout() != vk::ImageLayout::eGeneral) {
162 m_resources.transition_image(img, img->get_current_layout(),
163 vk::ImageLayout::eGeneral);
164 }
165 m_resources.bind_image_storage(key, idx, img, b);
166 } break;
167
169 if (idx >= m_image_bindings.size() || !m_image_bindings[idx].image)
170 continue;
171 auto& img = m_image_bindings[idx].image;
172 auto sampler = m_image_bindings[idx].sampler;
173 if (img->get_current_layout() != vk::ImageLayout::eShaderReadOnlyOptimal) {
174 m_resources.transition_image(img, img->get_current_layout(),
175 vk::ImageLayout::eShaderReadOnlyOptimal);
176 }
177 m_resources.bind_image_sampled(key, idx, img, sampler, b);
178 } break;
179
182 if (!channels.empty()) {
183 const size_t raw_bytes = channels[0].size()
185 ? sizeof(uint32_t)
186 : sizeof(int32_t));
187 m_resources.ensure_buffer(key, idx, raw_bytes);
188 m_resources.upload_raw(key, idx,
189 reinterpret_cast<const uint8_t*>(channels[0].data()),
190 raw_bytes);
191 }
192 break;
193
195 default:
196 if (!m_native_staging_bytes.empty()) {
199 } else {
200 m_resources.ensure_buffer(key, idx, float_byte_size);
201 m_resources.upload(key, idx, m_staging_floats.data(), float_byte_size);
202 }
203 break;
204 }
205 }
206}
207
209 size_t total_elements, const DataStructureInfo& structure_info) const
210{
211 uint64_t sz_x = 0, sz_y = 0, sz_z = 0;
212 for (const auto& dim : structure_info.dimensions) {
213 switch (dim.role) {
215 sz_x = dim.size;
216 break;
218 sz_y = dim.size;
219 break;
221 sz_z = dim.size;
222 break;
223 default:
224 break;
225 }
226 }
227
228 const auto& ws = m_gpu_config.workgroup_size;
229 if (sz_x > 0) {
230 return {
231 static_cast<uint32_t>((sz_x + ws[0] - 1) / ws[0]),
232 sz_y > 0 ? static_cast<uint32_t>((sz_y + ws[1] - 1) / ws[1]) : 1U,
233 sz_z > 0 ? static_cast<uint32_t>((sz_z + ws[2] - 1) / ws[2]) : 1U,
234 };
235 }
236
237 return { static_cast<uint32_t>((total_elements + ws[0] - 1) / ws[0]), 1U, 1U };
238}
239
240//==============================================================================
241// Dispatch
242//==============================================================================
243
245 const std::vector<std::vector<double>>& channels,
246 const DataStructureInfo& structure_info)
247{
248 on_before_gpu_dispatch(channels, structure_info);
249 prepare_gpu_inputs(channels, structure_info);
250
252
253 const size_t effective = m_staging_floats.empty()
255 : m_staging_floats.size();
256 const auto groups = calculate_dispatch_size(effective, structure_info);
257
259 dispatch_key(), groups, m_bindings,
260 m_push_constants.empty() ? nullptr : m_push_constants.data(),
261 m_push_constants.size());
262
263 GpuChannelResult result;
264 result.primary = readback_primary(effective);
265 readback_aux(result);
266 return result;
267}
268
270 const std::vector<std::vector<double>>& channels,
271 const DataStructureInfo& structure_info,
272 const ExecutionContext& ctx)
273{
274 on_before_gpu_dispatch(channels, structure_info);
275 prepare_gpu_inputs(channels, structure_info);
276
278
279 const size_t effective = m_staging_floats.empty()
281 : m_staging_floats.size();
282 const auto groups = calculate_dispatch_size(effective, structure_info);
283
285 dispatch_key(), groups, m_bindings,
287
288 GpuChannelResult result;
289 result.primary = readback_primary(effective);
290 readback_aux(result);
291 return result;
292}
293
295 const std::vector<std::vector<double>>& channels,
296 const DataStructureInfo& structure_info,
297 const ExecutionContext& ctx)
298{
299 on_before_gpu_dispatch(channels, structure_info);
300 prepare_gpu_inputs(channels, structure_info);
301
303 if (!ensure_gpu_ready()) {
304 error<std::runtime_error>(Journal::Component::Yantra,
306 std::source_location::current(),
307 "GpuDispatchCore: dispatch_core_chained_indirect GPU initialisation failed");
308 }
309
311
312 const size_t effective = m_staging_floats.empty()
314 : m_staging_floats.size();
315 const auto groups = calculate_dispatch_size(effective, structure_info);
316
317 const auto indirect_it = std::ranges::find_if(m_bindings, [](const auto& b) {
319 });
320 if (indirect_it == m_bindings.end()) {
321 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::Runtime,
322 std::source_location::current(),
323 "GpuDispatchCore: dispatch_core_chained_indirect requires a binding with usage_hint INDIRECT");
324 }
325
327 dispatch_key(), indirect_it->set, indirect_it->binding, groups, m_bindings,
329
330 GpuChannelResult result;
331 result.primary = readback_primary(effective);
332 readback_aux(result);
333 return result;
334}
335
337 const std::vector<std::vector<double>>& channels,
338 const DataStructureInfo& structure_info)
339{
340 on_before_gpu_dispatch(channels, structure_info);
341 prepare_gpu_inputs(channels, structure_info);
342
344
345 const size_t effective = m_staging_floats.empty()
347 : m_staging_floats.size();
348 const auto groups = calculate_dispatch_size(effective, structure_info);
349
351
353 dispatch_key(), groups, m_bindings,
354 m_push_constants.empty() ? nullptr : m_push_constants.data(),
355 m_push_constants.size());
356}
357
358void GpuDispatchCore::dispatch_core_dependency(const std::vector<DependencyStage>& stages)
359{
360 const GpuComputeConfig original_config = m_gpu_config;
361 const auto original_bindings = m_bindings;
362 const auto original_image_bindings = m_image_bindings;
363 const auto original_binding_data = m_binding_data;
364 const auto original_passthrough_bytes = m_passthrough_bytes;
365 const auto original_push_constants = m_push_constants;
366
367 std::vector<std::string> keys;
368 std::vector<std::array<uint32_t, 3>> groups_per_key;
369 std::vector<std::vector<uint8_t>> pc_per_key;
370 std::vector<std::vector<Portal::Graphics::HazardResource>> hazards_per_key;
371
372 keys.reserve(stages.size());
373 groups_per_key.reserve(stages.size());
374 pc_per_key.reserve(stages.size());
375 hazards_per_key.reserve(stages.size());
376
377 for (const auto& stage : stages) {
378 m_gpu_config = stage.config;
381 m_image_bindings.clear();
382 m_binding_data.clear();
383 m_passthrough_bytes.clear();
384 m_push_constants.clear();
385
386 stage.stage_fn(*this);
387
388 if (!ensure_gpu_ready()) {
389 error<std::runtime_error>(Journal::Component::Yantra,
391 std::source_location::current(),
392 "GpuDispatchCore: dispatch_core_dependency failed to initialise key '{}'",
393 stage.config.shader_path);
394 }
395
396 prepare_gpu_inputs({}, {});
397
399
400 keys.push_back(dispatch_key());
401 groups_per_key.push_back(stage.explicit_groups ? *stage.explicit_groups : calculate_dispatch_size(largest_binding_data_element_count(), {}));
402 pc_per_key.push_back(m_push_constants);
403 hazards_per_key.push_back(stage.hazard_fn ? stage.hazard_fn(*this) : std::vector<Portal::Graphics::HazardResource> {});
404 }
405
406 m_resources.dispatch_sequence(keys, groups_per_key, pc_per_key, hazards_per_key);
407
408 m_gpu_config = original_config;
410 m_bindings = original_bindings;
411 m_image_bindings = original_image_bindings;
412 m_binding_data = original_binding_data;
413 m_passthrough_bytes = original_passthrough_bytes;
414 m_push_constants = original_push_constants;
415}
416
417//==============================================================================
418// Readback helpers
419//==============================================================================
420
421std::vector<float> GpuDispatchCore::readback_primary(size_t float_count)
422{
423 const size_t idx = find_first_output_index();
424
425 for (const auto& b : m_bindings) {
426 if (b.binding != idx)
427 continue;
430 return {};
431 break;
432 }
433
434 const size_t allocated = m_resources.buffer_allocated_bytes(dispatch_key(), idx);
435 const size_t byte_size = std::min(float_count * sizeof(float), allocated);
436 std::vector<float> out(byte_size / sizeof(float));
437 m_resources.download(dispatch_key(), idx, out.data(), byte_size);
438 return out;
439}
440
442{
443 for (const auto& b : m_bindings) {
444 if (b.skip_auto_readback)
445 continue;
446
447 const size_t idx = b.binding;
448 const bool is_image = b.element_type == GpuBufferBinding::ElementType::IMAGE_STORAGE
450
451 if ((b.direction == GpuBufferBinding::Direction::OUTPUT
453 && !is_image
454 && idx < m_output_size_overrides.size()
455 && m_output_size_overrides[idx] > 0) {
456 const size_t sz = m_output_size_overrides[idx];
457 std::vector<uint8_t> raw(sz);
458 m_resources.download(dispatch_key(), idx, reinterpret_cast<float*>(raw.data()), sz);
459 result.aux[idx] = std::move(raw);
460 }
461 }
462}
463
464void GpuDispatchCore::download_binding(size_t index, void* dest, size_t byte_size)
465{
466 m_resources.download(dispatch_key(), index, reinterpret_cast<float*>(dest), byte_size);
467}
468
469//==============================================================================
470// Internal helpers
471//==============================================================================
472
474 const std::vector<std::vector<double>>& channels,
475 const DataStructureInfo& structure_info)
476{
477 m_staging_floats.clear();
479
480 if (Kakshya::is_structured_modality(structure_info.modality))
481 return;
482
483 bool all_inputs_staged = !m_bindings.empty();
484 for (size_t i = 0; i < m_bindings.size(); ++i) {
486 continue;
487 if (i >= m_binding_data.size() || m_binding_data[i].empty()) {
488 all_inputs_staged = false;
489 break;
490 }
491 }
492 if (all_inputs_staged)
493 return;
494
495 size_t total = 0;
496
497 for (const auto& ch : channels)
498 total += ch.size();
499 m_staging_floats.reserve(total);
500
501 for (const auto& ch : channels) {
502 for (double v : ch)
503 m_staging_floats.push_back(static_cast<float>(v));
504 }
505}
506
508 const std::vector<Kakshya::DataVariant>& variants,
509 const DataStructureInfo& structure_info)
510{
512
513 if (variants.empty() || Kakshya::is_structured_modality(structure_info.modality))
514 return;
515
516 size_t total_bytes = 0;
517 for (const auto& v : variants) {
518 std::visit([&](const auto& vec) {
519 total_bytes += vec.size() * sizeof(typename std::decay_t<decltype(vec)>::value_type);
520 },
521 v);
522 }
523
524 m_native_staging_bytes.reserve(total_bytes);
525
526 for (const auto& v : variants) {
527 std::visit([&](const auto& vec) {
528 using T = typename std::decay_t<decltype(vec)>::value_type;
529 const auto* bytes = reinterpret_cast<const uint8_t*>(vec.data());
532 bytes,
533 bytes + vec.size() * sizeof(T));
534 },
535 v);
536 }
537}
538
540{
541 size_t first_inout = SIZE_MAX;
542 for (const auto& b : m_bindings) {
543 if (b.direction == GpuBufferBinding::Direction::OUTPUT)
544 return b.binding;
546 && first_inout == SIZE_MAX)
547 first_inout = b.binding;
548 }
549 if (first_inout != SIZE_MAX)
550 return first_inout;
551
552 error<std::runtime_error>(Journal::Component::Yantra,
554 std::source_location::current(),
555 "GpuDispatchCore: no output buffer declared");
556}
557
559{
560 size_t max_bytes = 0;
561 for (const auto& b : m_bindings) {
562 if (b.direction == GpuBufferBinding::Direction::OUTPUT)
563 continue;
564 const size_t idx = b.binding;
565 if (idx < m_binding_data.size() && !m_binding_data[idx].empty())
566 max_bytes = std::max(max_bytes, m_binding_data[idx].size());
567 }
568 return max_bytes / sizeof(float);
569}
570
577
579{
580 for (auto& m_binding : m_bindings) {
581 const auto et = m_binding.element_type;
584 continue;
585
586 const auto key = std::make_pair(m_binding.set, static_cast<size_t>(m_binding.binding));
587 if (m_shared_bindings.contains(key)) {
588 m_resources.bind_shared_descriptor(dispatch_key(), m_binding.set, m_binding.binding, m_binding);
589 continue;
590 }
591
592 m_resources.bind_descriptor(dispatch_key(), static_cast<size_t>(m_binding.binding), m_binding);
593 }
594}
595
596} // namespace MayaFlux::Yantra
IO::ImageData image
Definition Decoder.cpp:64
size_t b
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.
std::set< std::pair< uint32_t, size_t > > m_shared_bindings
GpuDispatchCore(GpuComputeConfig config)
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 bind_image_sampled(const std::string &key, size_t index, const std::shared_ptr< Core::VKImage > &image, vk::Sampler sampler, const GpuBufferBinding &spec)
Bind a combined image+sampler descriptor at the given slot index.
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 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 bind_descriptor(const std::string &key, size_t index, const GpuBufferBinding &spec)
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.
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)
Record a dispatch for each requested key into one command buffer via ComputePress::record_sequence,...
void bind_shared_descriptor(const std::string &key, uint32_t set, size_t binding_index, const GpuBufferBinding &spec)
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)
size_t buffer_allocated_bytes(const std::string &key, size_t index) const
void bind_image_storage(const std::string &key, size_t index, const std::shared_ptr< Core::VKImage > &image, const GpuBufferBinding &spec)
Bind a storage image descriptor at the given slot index.
@ 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:200
@ INDIRECT
Indirect draw/dispatch buffer (device-local)
bool is_image(const fs::path &filepath)
Definition Depot.cpp:108
@ 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.
std::vector< Kakshya::DataDimension > dimensions
Metadata about data structure for reconstruction.
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...