MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GpuDispatchCore.hpp
Go to the documentation of this file.
1#pragma once
2
5
7
8namespace MayaFlux::Core {
9class VKImage;
10}
11
12namespace MayaFlux::Yantra {
13
14/**
15 * @struct GpuChannelResult
16 * @brief Erased output of a GPU dispatch: reconstructed float data plus
17 * any raw auxiliary outputs keyed by binding index.
18 */
20 std::vector<float> primary;
21 std::unordered_map<size_t, std::vector<uint8_t>> aux;
22};
23
24/**
25 * @class GpuDispatchCore
26 * @brief Non-template base that owns all type-independent GPU dispatch logic.
27 *
28 * Separates resource management, buffer staging, and dispatch orchestration
29 * from the type-parameterised boundary in GpuExecutionContext. All virtual
30 * override points that do not reference InputType/OutputType live here so
31 * that implementations can be placed in a .cpp file.
32 *
33 * Subclasses (including GpuExecutionContext) implement the two remaining
34 * type-dependent steps -- channel extraction and output reconstruction --
35 * without duplicating anything that is type-independent.
36 */
37class MAYAFLUX_API GpuDispatchCore {
38public:
39 explicit GpuDispatchCore(GpuShaderConfig config);
40 virtual ~GpuDispatchCore() = default;
41
46
47 /**
48 * @brief Set push constant data from a raw byte pointer.
49 * @param data Pointer to trivially-copyable push constant struct.
50 * @param bytes Size in bytes.
51 */
52 void set_push_constants(const void* data, size_t bytes);
53
54 /**
55 * @brief Typed convenience wrapper for set_push_constants(const void*, size_t).
56 * @tparam T Trivially copyable type matching shader push constant layout.
57 */
58 template <typename T>
59 void set_push_constants(const T& data)
60 {
61 set_push_constants(&data, sizeof(T));
62 }
63
64 /**
65 * @brief Pre-stage typed data for a specific binding slot, bypassing
66 * the default channel-flattening path in prepare_gpu_inputs.
67 * @tparam T Trivially copyable element type.
68 * @param index Binding index matching declare_buffer_bindings order.
69 * @param data Elements to upload.
70 */
71 template <typename T>
72 void set_binding_data(size_t index, std::span<const T> data)
73 {
74 if (index >= m_binding_data.size())
75 m_binding_data.resize(index + 1);
76 auto& slot = m_binding_data[index];
77 slot.resize(data.size_bytes());
78 std::memcpy(slot.data(), data.data(), data.size_bytes());
79 }
80
81 template <typename T>
82 void set_binding_data(size_t index, const std::vector<T>& data)
83 {
84 set_binding_data(index, std::span<const T>(data));
85 }
86
87 /**
88 * @brief Declare the byte capacity of an output binding independently
89 * of input data. Required for edge lists, histograms, count
90 * buffers, and any output whose size cannot be derived from input.
91 * @param index Binding index.
92 * @param byte_size Required allocation in bytes.
93 */
94 void set_output_size(size_t index, size_t byte_size);
95
96 /**
97 * @brief Ensure GPU resources are initialised. Safe to call repeatedly.
98 * @return True if GPU is ready after this call.
99 */
100 bool ensure_gpu_ready();
101
102 /**
103 * @brief Query GPU readiness without attempting initialisation.
104 */
105 [[nodiscard]] bool is_gpu_ready() const;
106
107 /**
108 * @brief Return the image registered at an IMAGE_STORAGE output binding.
109 *
110 * Valid after dispatch_core completes (dispatch is synchronous via
111 * submit_and_wait). Callers may then bind it directly to a render pass
112 * or read it back via TextureLoom.
113 *
114 * @param binding_index Index of the IMAGE_STORAGE binding.
115 * @return Shared pointer to the VKImage, or nullptr if not registered.
116 */
117 [[nodiscard]] std::shared_ptr<Core::VKImage> get_output_image(size_t binding_index) const;
118
119protected:
120 /**
121 * @brief Declare the storage buffers the shader expects.
122 *
123 * Default: INPUT at (0,0) FLOAT32, OUTPUT at (0,1) FLOAT32.
124 */
125 [[nodiscard]] virtual std::vector<GpuBufferBinding> declare_buffer_bindings() const;
126
127 /**
128 * @brief Called immediately before dispatch. Override to write push
129 * constants or perform any per-dispatch reconfiguration.
130 */
131 virtual void on_before_gpu_dispatch(
132 const std::vector<std::vector<double>>& channels,
133 const DataStructureInfo& structure_info);
134
135 /**
136 * @brief Marshal channel data into GPU input buffers.
137 *
138 * Handles FLOAT32, UINT32, INT32, PASSTHROUGH, IMAGE_STORAGE, and
139 * IMAGE_SAMPLED binding kinds. Called after flatten_channels_to_staging.
140 */
141 virtual void prepare_gpu_inputs(
142 const std::vector<std::vector<double>>& channels,
143 const DataStructureInfo& structure_info);
144
145 /**
146 * @brief Calculate workgroup dispatch counts from structure dimensions.
147 *
148 * Reads SPATIAL_X/Y/Z roles for 2D/3D shaders; falls back to 1D
149 * element-count dispatch when no spatial dimensions exist.
150 *
151 * @param total_elements Flat element count for the 1D fallback.
152 * @param structure_info Dimension metadata.
153 */
154 [[nodiscard]] virtual std::array<uint32_t, 3> calculate_dispatch_size(
155 size_t total_elements,
156 const DataStructureInfo& structure_info) const;
157
158 /**
159 * @brief Stage raw bytes for a PASSTHROUGH binding before dispatch.
160 * @param binding_index Index matching declare_buffer_bindings order.
161 * @param data Raw byte pointer.
162 * @param byte_size Size in bytes.
163 */
164 void stage_passthrough(size_t binding_index, const void* data, size_t byte_size);
165
166 /**
167 * @brief Register a VKImage for an IMAGE_STORAGE binding.
168 *
169 * The image will be transitioned to eGeneral layout if not already there.
170 *
171 * @param binding_index Index matching the IMAGE_STORAGE declaration.
172 * @param image Initialised VKImage.
173 */
174 void stage_image_storage(size_t binding_index, std::shared_ptr<Core::VKImage> image);
175
176 /**
177 * @brief Register a VKImage + sampler for an IMAGE_SAMPLED binding.
178 *
179 * The image will be transitioned to eShaderReadOnlyOptimal if needed.
180 *
181 * @param binding_index Index matching the IMAGE_SAMPLED declaration.
182 * @param image Initialised VKImage.
183 * @param sampler Vulkan sampler handle.
184 */
185 void stage_image_sampled(size_t binding_index,
186 std::shared_ptr<Core::VKImage> image,
187 vk::Sampler sampler);
188
189 [[nodiscard]] const GpuShaderConfig& gpu_config() const;
190
191 /**
192 * @brief Full single-pass dispatch. Drives prepare_gpu_inputs,
193 * on_before_gpu_dispatch, bind_descriptor, and GpuResourceManager::dispatch.
194 *
195 * @param channels Extracted double channels from the input Datum.
196 * @param structure_info Dimension/modality metadata from OperationHelper.
197 * @return GpuChannelResult containing primary float readback and aux buffers.
198 */
199 GpuChannelResult dispatch_core(
200 const std::vector<std::vector<double>>& channels,
201 const DataStructureInfo& structure_info);
202
203 /**
204 * @brief Multi-pass (chained) dispatch. Calls dispatch_batched on
205 * GpuResourceManager and reads back once after all passes.
206 *
207 * @param channels Extracted double channels.
208 * @param structure_info Dimension/modality metadata.
209 * @param ctx ExecutionContext carrying pass_count and pc_updater.
210 * @return GpuChannelResult containing primary float readback and aux buffers.
211 */
212 GpuChannelResult dispatch_core_chained(
213 const std::vector<std::vector<double>>& channels,
214 const DataStructureInfo& structure_info,
215 const ExecutionContext& ctx);
216
217 /**
218 * @brief Read back the primary output buffer into a float vector.
219 *
220 * Selects the first OUTPUT or INPUT_OUTPUT binding. Caps readback to
221 * the lesser of the requested float count and the allocated buffer size.
222 *
223 * @param float_count Number of float elements to attempt to read.
224 * @return Float vector of length min(float_count, allocated / sizeof(float)).
225 */
226 [[nodiscard]] std::vector<float> readback_primary(size_t float_count);
227
228 /**
229 * @brief Read back all OUTPUT bindings that have explicit size overrides
230 * into the aux map of a GpuChannelResult.
231 *
232 * @param result GpuChannelResult to write aux entries into.
233 */
234 void readback_aux(GpuChannelResult& result);
235
236 /**
237 * @brief Flatten planar double channels into m_staging_floats.
238 *
239 * Skipped for structured modalities (glm::vec3 etc.) since those are
240 * handled per-binding via PASSTHROUGH or integer paths.
241 */
242 void flatten_channels_to_staging(
243 const std::vector<std::vector<double>>& channels,
244 const DataStructureInfo& structure_info);
245
246 [[nodiscard]] size_t find_first_output_index() const;
247 [[nodiscard]] size_t largest_binding_data_element_count() const;
248
250 std::vector<GpuBufferBinding> m_bindings;
251 std::vector<float> m_staging_floats;
252 std::vector<uint8_t> m_push_constants;
253 std::vector<size_t> m_output_size_overrides;
254 std::vector<std::vector<uint8_t>> m_passthrough_bytes;
255 std::vector<std::vector<uint8_t>> m_binding_data;
256
258 std::shared_ptr<Core::VKImage> image;
259 vk::Sampler sampler;
261 };
262 std::vector<ImageBinding> m_image_bindings;
263
264private:
266};
267
268} // namespace MayaFlux::Yantra
IO::ImageData image
std::string kind
std::vector< ImageBinding > m_image_bindings
GpuDispatchCore(GpuDispatchCore &&)=delete
std::vector< uint8_t > m_push_constants
void set_binding_data(size_t index, const std::vector< T > &data)
std::vector< std::vector< uint8_t > > m_binding_data
std::vector< GpuBufferBinding > m_bindings
std::vector< size_t > m_output_size_overrides
virtual ~GpuDispatchCore()=default
void set_push_constants(const T &data)
Typed convenience wrapper for set_push_constants(const void*, size_t).
GpuDispatchCore & operator=(GpuDispatchCore &&)=delete
std::vector< std::vector< uint8_t > > m_passthrough_bytes
GpuDispatchCore(const GpuDispatchCore &)=delete
GpuDispatchCore & operator=(const GpuDispatchCore &)=delete
void set_binding_data(size_t index, std::span< const T > data)
Pre-stage typed data for a specific binding slot, bypassing the default channel-flattening path in pr...
Non-template base that owns all type-independent GPU dispatch logic.
Encapsulates all Vulkan resource lifecycle behind Portal facades.
Metadata about data structure for reconstruction.
Context information controlling how a compute operation executes.
ElementType
Element type the shader expects in this buffer.
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...
Plain-data description of the compute shader to dispatch.