MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VKBuffer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Buffer.hpp"
4
6
8
10struct BufferService;
11struct ComputeService;
12}
13
14namespace MayaFlux::Core {
15class Window;
16}
17
18namespace MayaFlux::Buffers {
19
20class RenderProcessor;
21struct ShaderConfig;
22
23/**
24 * @struct VKBufferResources
25 * @brief Raw Vulkan handles owned by a VKBuffer instance.
26 *
27 * The index_buffer / index_memory / index_size_bytes fields are populated
28 * by GeometryBindingsProcessor after index data upload and consumed by
29 * RenderProcessor to select the indexed draw path. They are null/zero for
30 * all non-indexed geometry; no separate allocation object is required.
31 * back_buffers are reserved for double-buffered or N-buffered ping-pong state or
32 * other auxiliary buffers owned by a VKBuffer subclass. They are empty when unused.
33 */
35 vk::Buffer buffer;
36 vk::DeviceMemory memory;
37 void* mapped_ptr { nullptr };
38
39 vk::Buffer index_buffer;
40 vk::DeviceMemory index_memory;
41 size_t index_size_bytes { 0 };
42
44 vk::Buffer buffer { VK_NULL_HANDLE };
45 vk::DeviceMemory memory { VK_NULL_HANDLE };
46 void* mapped_ptr { nullptr };
47 };
48 std::vector<GenerationSlot> back_buffers;
49};
50
51using RenderPipelineID = uint64_t;
52using CommandBufferID = uint64_t;
53
54/**
55 * @class VKBuffer
56 * @brief Vulkan-backed buffer wrapper used in processing chains
57 *
58 * VKBuffer is a lightweight, high-level representation of a GPU buffer used by
59 * the MayaFlux processing pipeline. It carries semantic metadata (Kakshya
60 * modalities and dimensions), integrates with the Buffer processing chain and
61 * BufferManager, and exposes Vulkan handles once the backend registers the
62 * buffer. Prior to registration the object contains no GPU resources and can
63 * be manipulated cheaply (like AudioBuffer).
64 *
65 * Responsibilities:
66 * - Store buffer size, usage intent and semantic modality
67 * - Provide inferred data dimensions for processors and pipeline inspection
68 * - Hold Vulkan handles (VkBuffer, VkDeviceMemory) assigned by graphics backend
69 * - Provide convenience helpers for common Vulkan creation flags and memory props
70 * - Integrate with BufferProcessor / BufferProcessingChain for default processing
71 *
72 * Note: Actual allocation, mapping and command-based transfers are performed by
73 * the graphics backend / BufferManager. VKBuffer only stores handles and
74 * metadata and provides helpers for processors to operate on it.
75 */
76class MAYAFLUX_API VKBuffer : public Buffer {
77public:
79
81
82 /**
83 * @brief Context shared with BufferProcessors during pipeline execution
84 *
85 * Processors can use this struct to share data (e.g., push constant staging)
86 * and metadata during processing of this buffer in a chain.
87 */
89 std::vector<Portal::Graphics::PushConstantBindingInfo> push_constant_bindings;
90
91 std::vector<Portal::Graphics::DescriptorBindingInfo> descriptor_buffer_bindings;
92
93 std::unordered_map<std::string, std::any> metadata;
94 };
95
96 /**
97 * @brief Engine-internal per-frame binding state
98 *
99 * Carries descriptor bindings written by engine processors (e.g.
100 * MeshNetworkProcessor SSBOs) that must reach RenderProcessor::execute_shader
101 * without passing through the user-facing PipelineContext. Access is
102 * unrestricted by convention only: engine processors write here, user code
103 * should not.
104 */
106 std::vector<Portal::Graphics::DescriptorBindingInfo> ssbo_bindings;
107 };
108
109 /**
110 * @brief Construct an unregistered VKBuffer
111 *
112 * Creates a VKBuffer object with the requested capacity, usage intent and
113 * semantic modality. No Vulkan resources are created by this constructor —
114 * registration with the BufferManager / backend is required to allocate
115 * VkBuffer and VkDeviceMemory.
116 *
117 * @param size_bytes Buffer capacity in bytes.
118 * @param usage Intended usage pattern (affects Vulkan flags and memory).
119 * @param modality Semantic interpretation of the buffer contents.
120 */
121 VKBuffer(
122 size_t size_bytes,
123 Usage usage,
124 Kakshya::DataModality modality = Kakshya::DataModality::VERTICES_3D);
125
126 VKBuffer() = default;
127
128 /**
129 * @brief Virtual destructor
130 *
131 * VKBuffer does not own Vulkan resources directly; cleanup is handled by
132 * the backend during unregistration. The destructor ensures derived class
133 * cleanup and safe destruction semantics.
134 */
135 ~VKBuffer() override;
136
137 /**
138 * @brief Get the Vulkan device address for this buffer (if applicable)
139 * @return 64-bit device address, or 0 if not BDA-capable or not initialized
140 *
141 * Only buffers created with Usage::UNIFORM_BDA or Usage::STORAGE_BDA and
142 * registered with the backend will return a valid device address. This is
143 * used by processors that need to bind buffers via device address (e.g.,
144 * for ray tracing or bindless access).
145 */
146 [[nodiscard]] uint64_t get_device_address() const;
147
148 /**
149 * @brief Clear buffer contents
150 *
151 * If the buffer is host-visible and mapped the memory is zeroed. For
152 * device-local buffers the backend must provide a ClearBufferProcessor
153 * that performs the appropriate GPU-side clear.
154 */
155 void clear() override;
156
157 /**
158 * @brief Read buffer contents as Kakshya DataVariant
159 *
160 * For host-visible buffers this returns a single DataVariant containing the
161 * raw bytes. For device-local buffers this warns and returns empty — a
162 * BufferDownloadProcessor should be used to read GPU-only memory.
163 *
164 * @return Vector of DataVariant objects representing buffer contents.
165 */
166 std::vector<Kakshya::DataVariant> get_data();
167
168 /**
169 * @brief Write data into the buffer
170 *
171 * If the buffer is host-visible and mapped the provided data is copied into
172 * the mapped memory. For device-local buffers, a BufferUploadProcessor must
173 * be present in the processing chain to perform the staging/upload.
174 *
175 * @param data Vector of Kakshya::DataVariant containing the payload to copy.
176 */
177 void set_data(const std::vector<Kakshya::DataVariant>& data);
178
179 /**
180 * @brief Resize buffer and recreate GPU resources if needed
181 * @param new_size New size in bytes
182 * @param preserve_data If true, copy existing data to new buffer
183 *
184 * If buffer is already initialized (has GPU resources), this will:
185 * 1. Create new GPU buffer with new size
186 * 2. Optionally copy old data
187 * 3. Destroy old GPU buffer
188 * 4. Update buffer resources
189 *
190 * If buffer is not initialized, just updates logical size.
191 */
192 void resize(size_t new_size, bool preserve_data = false);
193
194 /**
195 * @brief Get current logical size in bytes
196 * @return Buffer size in bytes.
197 */
198 size_t get_size() const { return m_size_bytes; }
199
200 /**
201 * @brief Run the buffer's default processor (if set and enabled)
202 *
203 * Invokes the attached default BufferProcessor. Processors should be
204 * prepared to handle mapped/unmapped memory according to buffer usage.
205 */
206 void process_default() override;
207
208 /**
209 * @brief Set the buffer's default processor
210 *
211 * Attaches a processor that will be invoked by process_default(). The
212 * previous default processor (if any) is detached first.
213 *
214 * @param processor Shared pointer to a BufferProcessor or nullptr to clear.
215 */
216 void set_default_processor(const std::shared_ptr<BufferProcessor>& processor) override;
217
218 /**
219 * @brief Get the currently attached default processor
220 * @return Shared pointer to the default BufferProcessor or nullptr.
221 */
222 std::shared_ptr<Buffers::BufferProcessor> get_default_processor() const override;
223
224 /**
225 * @brief Access the buffer's processing chain
226 * @return Shared pointer to the BufferProcessingChain used for this buffer.
227 */
228 std::shared_ptr<Buffers::BufferProcessingChain> get_processing_chain() override;
229
230 /**
231 * @brief Replace the buffer's processing chain
232 * @param chain New processing chain to assign.
233 * @param force If true, replaces existing chain even if one is set.
234 */
235 void set_processing_chain(const std::shared_ptr<BufferProcessingChain>& chain, bool force = false) override;
236
237 bool has_data_for_cycle() const override { return m_has_data; }
238 bool needs_removal() const override { return m_needs_removal; }
239 void mark_for_processing(bool has_data) override { m_has_data = has_data; }
240 void mark_for_removal() override { m_needs_removal = true; }
241 void enforce_default_processing(bool should_process) override { m_process_default = should_process; }
242 bool needs_default_processing() override { return m_process_default; }
243
244 /**
245 * @brief Try to acquire processing lock for this buffer
246 * @return True if lock acquired, false if already processing.
247 *
248 * Uses an atomic flag to guard concurrent processing attempts.
249 */
250 inline bool try_acquire_processing() override
251 {
252 bool expected = false;
253 return m_is_processing.compare_exchange_strong(expected, true,
254 std::memory_order_acquire, std::memory_order_relaxed);
255 }
256
257 /**
258 * @brief Release previously acquired processing lock
259 */
260 inline void release_processing() override
261 {
262 m_is_processing.store(false, std::memory_order_release);
263 }
264
265 /**
266 * @brief Query whether the buffer is currently being processed
267 * @return True if a processing operation holds the lock.
268 */
269 inline bool is_processing() const override
270 {
271 return m_is_processing.load(std::memory_order_acquire);
272 }
273
274 /** Get VkBuffer handle (VK_NULL_HANDLE if not registered) */
275 vk::Buffer& get_buffer() { return m_resources.buffer; }
276
277 /* Get logical buffer size as VkDeviceSize */
278 vk::DeviceSize get_size_bytes() const { return m_size_bytes; }
279
280 /** Check whether Vulkan handles are present (buffer registered) */
281 bool is_initialized() const { return m_resources.buffer != VK_NULL_HANDLE; }
282
283 /**
284 * @brief Setup processors with a processing token
285 * @param token ProcessingToken to assign.
286 *
287 * For VKBuffer this is a no-op as processors get the token.
288 * This is meant for derived classes that need to setup default processors
289 */
290 virtual void setup_processors(ProcessingToken token) { }
291
292 /** Get the buffer's semantic modality */
293 Kakshya::DataModality get_modality() const { return m_modality; }
294
295 /** Get the inferred data dimensions for the buffer contents */
296 const std::vector<Kakshya::DataDimension>& get_dimensions() const { return m_dimensions; }
297
298 /**
299 * @brief Update the semantic modality and re-infer dimensions
300 * @param modality New Kakshya::DataModality to apply.
301 */
302 void set_modality(Kakshya::DataModality modality);
303
304 /** Retrieve the declared usage intent */
305 Usage get_usage() const { return m_usage; }
306
307 /** Set VkBuffer handle after backend allocation */
308 void set_buffer(vk::Buffer buffer) { m_resources.buffer = buffer; }
309
310 /** Set device memory handle after backend allocation */
311 void set_memory(vk::DeviceMemory memory) { m_resources.memory = memory; }
312
313 /** Set mapped host pointer (for host-visible allocations) */
314 void set_mapped_ptr(void* ptr) { m_resources.mapped_ptr = ptr; }
315
316 /** Set all buffer resources at once */
317 inline void set_buffer_resources(const VKBufferResources& resources)
318 {
319 m_resources = resources;
320 }
321
322 /**
323 * @brief Store raw index buffer handles produced by the geometry upload path.
324 *
325 * Called by GeometryBindingsProcessor after allocating and uploading index
326 * data. Overwrites any previously stored handles. Pass null handles and
327 * zero size to clear (non-indexed geometry).
328 *
329 * @param buf Allocated vk::Buffer with INDEX usage flags.
330 * @param mem Backing vk::DeviceMemory.
331 * @param size Byte size of the index buffer.
332 */
333 void set_index_resources(vk::Buffer buf, vk::DeviceMemory mem, size_t size)
334 {
335 m_resources.index_buffer = buf;
336 m_resources.index_memory = mem;
337 m_resources.index_size_bytes = size;
338 }
339
340 /** Get all buffer resources at once (read-only) */
341 inline const VKBufferResources& get_buffer_resources() const { return m_resources; }
342
343 /** Get all buffer resources at once (mutable). */
344 inline VKBufferResources& get_buffer_resources() { return m_resources; }
345
346 /**
347 * @brief Return the raw index buffer handle.
348 * @return vk::Buffer; operator bool() returns false when non-indexed.
349 */
350 [[nodiscard]] vk::Buffer get_index_buffer() const { return m_resources.index_buffer; }
351
352 /**
353 * @brief Number of bytes in the index buffer.
354 * @return Byte count; divide by sizeof(uint32_t) for index count.
355 * Zero when non-indexed.
356 */
357 [[nodiscard]] size_t get_index_buffer_size() const { return m_resources.index_size_bytes; }
358
359 /**
360 * @brief True when an index buffer has been associated with this buffer.
361 */
362 [[nodiscard]] bool has_index_buffer() const
363 {
364 return static_cast<bool>(m_resources.index_buffer);
365 }
366
367 /**
368 * @brief Whether this VKBuffer should be host-visible
369 * @return True for staging or uniform buffers, false for device-local types.
370 */
371 bool is_host_visible() const
372 {
373 return m_usage == Usage::STAGING
374 || m_usage == Usage::UNIFORM
375 || m_usage == Usage::UNIFORM_BDA
376 || m_usage == Usage::STORAGE_BDA
377 || m_usage == Usage::HOST_STORAGE;
378 }
379
380 /**
381 * @brief Get appropriate VkBufferUsageFlags for creation based on Usage
382 * @return VkBufferUsageFlags to be used when creating VkBuffer.
383 */
384 vk::BufferUsageFlags get_usage_flags() const;
385
386 /**
387 * @brief Get appropriate VkMemoryPropertyFlags for allocation based on Usage
388 * @return VkMemoryPropertyFlags to request during memory allocation.
389 */
390 vk::MemoryPropertyFlags get_memory_properties() const;
391
392 /** Get mapped host pointer (nullptr if not host-visible or unmapped) */
393 void* get_mapped_ptr() const { return m_resources.mapped_ptr; }
394
395 /** Get device memory handle */
396 void mark_dirty_range(size_t offset, size_t size);
397
398 /** Mark a range as invalid (needs download) */
399 void mark_invalid_range(size_t offset, size_t size);
400
401 /** Retrieve and clear all dirty ranges */
402 std::vector<std::pair<size_t, size_t>> get_and_clear_dirty_ranges();
403
404 /** Retrieve and clear all invalid ranges */
405 std::vector<std::pair<size_t, size_t>> get_and_clear_invalid_ranges();
406
407 /**
408 * @brief Associate this buffer with a window for rendering
409 * @param window Target window for rendering this buffer's content
410 *
411 * When this buffer is processed, its content will be rendered to the associated window.
412 * Currently supports one window per buffer (will be extended to multiple windows).
413 */
414 void set_pipeline_window(RenderPipelineID id, const std::shared_ptr<Core::Window>& window)
415 {
416 m_window_pipelines[id] = window;
417 }
418
419 /**
420 * @brief Get the window associated with this buffer
421 * @return Target window, or nullptr if not set
422 */
423 std::shared_ptr<Core::Window> get_pipeline_window(RenderPipelineID id) const
424 {
425 auto it = m_window_pipelines.find(id);
426 if (it != m_window_pipelines.end()) {
427 return it->second;
428 }
429 return nullptr;
430 }
431
432 /**
433 * @brief Check if this buffer has a rendering pipeline configured
434 */
436 {
437 return !m_window_pipelines.empty();
438 }
439
440 /**
441 * @brief Get all render pipelines associated with this buffer
442 * @return Map of RenderPipelineID to associated windows
443 */
444 std::unordered_map<RenderPipelineID, std::shared_ptr<Core::Window>> get_render_pipelines() const
445 {
446 return m_window_pipelines;
447 }
448
449 /**
450 * @brief Store recorded command buffer for a pipeline
451 */
453 CommandBufferID cmd_id)
454 {
455 m_pipeline_commands[pipeline_id] = cmd_id;
456 }
457
458 /**
459 * @brief Get recorded command buffer for a pipeline
460 */
462 {
463 auto it = m_pipeline_commands.find(pipeline_id);
464 return it != m_pipeline_commands.end() ? it->second : 0;
465 }
466
467 /**
468 * @brief Clear all recorded commands (called after presentation)
469 */
471 {
472 m_pipeline_commands.clear();
473 }
474
475 /**
476 * @brief Set vertex layout for this buffer
477 *
478 * Required before using buffer with graphics rendering.
479 * Describes how to interpret buffer data as vertices.
480 *
481 * @param layout VertexLayout describing vertex structure
482 */
483 void set_vertex_layout(const Kakshya::VertexLayout& layout);
484
485 /**
486 * @brief Get vertex layout if set
487 * @return Optional containing layout, or empty if not set
488 */
489 std::optional<Kakshya::VertexLayout> get_vertex_layout() const { return m_vertex_layout; }
490
491 /**
492 * @brief Check if this buffer has vertex layout configured
493 */
494 bool has_vertex_layout() const { return m_vertex_layout.has_value(); }
495
496 /**
497 * @brief Clear vertex layout
498 */
500 {
501 m_vertex_layout.reset();
502 }
503
504 std::shared_ptr<Buffer> clone_to(uint8_t dest_desc) override;
505
506 /**
507 * @brief Create a clone of this buffer with the same data and properties
508 * @param usage Usage enum for the cloned buffer
509 * @return Shared pointer to the cloned VKBuffer
510 *
511 * The cloned buffer will have the same size, modality, dimensions,
512 * processing chain and default processor as the original. Changes to
513 * one buffer after cloning do not affect the other.
514 */
515 std::shared_ptr<VKBuffer> clone_to(Usage usage);
516
517 /** Set whether this buffer is for internal engine usage */
518 void force_internal_usage(bool internal) override { m_internal_usage = internal; }
519
520 /** Check whether this buffer is for internal engine usage */
521 bool is_internal_only() const override { return m_internal_usage; }
522
523 /** Access the pipeline context for custom metadata (non-const) */
524 PipelineContext& get_pipeline_context() { return m_pipeline_context; }
525
526 /** Access the pipeline context for custom metadata (const) */
527 const PipelineContext& get_pipeline_context() const { return m_pipeline_context; }
528
529 [[nodiscard]] EngineContext& get_engine_context() { return m_engine_context; }
530 [[nodiscard]] const EngineContext& get_engine_context() const { return m_engine_context; }
531
532 /**
533 * @brief Mark config as changed (processors will detect and react)
534 * @param is_dirty Whether the config is now dirty (default: true)
535 * NOTE: Child classes override this to call their internal setup_rendering() with the new config, which may have additional side effects.
536 */
537 virtual void mark_render_config_dirty(bool is_dirty = true) { m_render_config_dirty = is_dirty; }
538
539 /**
540 * @brief Check if config has changed since last frame
541 */
542 [[nodiscard]] bool is_render_config_dirty() const { return m_render_config_dirty; }
543
544 /**
545 * @brief Get the current render configuration
546 * @return RenderConfig struct with current settings
547 */
548 RenderConfig get_render_config() const { return m_render_config; }
549
550 /**
551 * @brief Update the render configuration and mark as dirty
552 * @param config New RenderConfig to apply
553 *
554 * This will update the buffer's render configuration and set the dirty flag,
555 * signaling to any RenderProcessor that it needs to reconfigure rendering for this buffer.
556 * NOTE: Child classes override this to call their internal setup_rendering() with the new config, which may have additional side effects.
557 */
558 virtual void set_render_config(const RenderConfig& config)
559 {
560 m_render_config = config;
561 m_render_config_dirty = true;
562 }
563
564 /**
565 * @brief Mark this buffer as requiring depth testing when rendered
566 */
567 void set_needs_depth_attachment(bool needs) { m_needs_depth = needs; }
568
569 /**
570 * @brief Check if this buffer requires depth attachment for rendering
571 */
572 [[nodiscard]] bool needs_depth_attachment() const { return m_needs_depth; }
573
574 /**
575 * @brief Get a RenderProcessor suitable for rendering this buffer
576 * @return Shared pointer to a RenderProcessor, or nullptr if not renderable
577 *
578 * By default returns nullptr. Derived classes that support rendering should
579 * override this to return an appropriate RenderProcessor instance.
580 */
581 virtual std::shared_ptr<RenderProcessor> get_render_processor() const { return m_render_processor; }
582
583 inline void set_render_processor(std::shared_ptr<RenderProcessor> rp) { m_render_processor = std::move(rp); }
584
585protected:
586 /**
587 * @brief Called by derived classes to set their context-specific defaults
588 * @param config RenderConfig with default values for this buffer type
589 *
590 * Example (GeometryBuffer calls this in constructor):
591 * RenderConfig defaults;
592 * defaults.vertex_shader = "point.vert.spv";
593 * defaults.fragment_shader = "point.frag.spv";
594 * defaults.topology = PrimitiveTopology::POINT_LIST;
595 * set_default_render_config(defaults);
596 */
598 {
599 m_render_config = config;
600 m_render_config_dirty = false;
601 }
602
603 /**
604 * @brief Configure the internal m_render_processor from a RenderConfig.
605 */
606 void apply_render_config(const RenderConfig& config, const ShaderConfig& shader_config);
607
608 /**
609 * @brief Configure a RenderProcessor, creating one if null.
610 * @param render_processor Existing processor to configure, or nullptr to create one.
611 * @param config RenderConfig with settings to apply
612 */
613 void apply_render_config(
614 std::shared_ptr<RenderProcessor>& render_processor,
615 const RenderConfig& config,
616 const ShaderConfig& shader_config);
617
618 bool m_render_config_dirty {};
620 std::shared_ptr<RenderProcessor> m_render_processor;
621
622private:
624
625 // Buffer parameters
626 size_t m_size_bytes {};
627 Usage m_usage {};
628 bool m_needs_depth {};
629
630 // Semantic metadata
632 std::vector<Kakshya::DataDimension> m_dimensions;
633
634 std::optional<Kakshya::VertexLayout> m_vertex_layout;
635
636 // Buffer interface state
637 bool m_has_data { true };
638 bool m_needs_removal {};
639 bool m_process_default { true };
640 bool m_internal_usage {};
641 std::atomic<bool> m_is_processing;
642 std::shared_ptr<Buffers::BufferProcessor> m_default_processor;
643 std::shared_ptr<Buffers::BufferProcessingChain> m_processing_chain;
647
648 std::unordered_map<RenderPipelineID, std::shared_ptr<Core::Window>> m_window_pipelines;
649 std::unordered_map<RenderPipelineID, CommandBufferID> m_pipeline_commands;
650
651 std::vector<std::pair<size_t, size_t>> m_dirty_ranges;
652 std::vector<std::pair<size_t, size_t>> m_invalid_ranges;
653
654 /**
655 * @brief Infer Kakshya::DataDimension entries from a given byte count
656 *
657 * Uses the current modality and provided byte count to populate
658 * m_dimensions so processors and UI code can reason about the buffer's layout.
659 *
660 * @param byte_count Number of bytes of data to infer dimensions from.
661 */
662 void infer_dimensions_from_data(size_t byte_count);
663};
664
666protected:
669
672 void ensure_initialized(const std::shared_ptr<VKBuffer>& buffer);
673};
674
675/**
676 * @concept GpuImageSource
677 * @brief Satisfied by any VKBuffer subclass that exposes a GPU-resident image.
678 *
679 * Covers all pixel-bearing buffer types via whichever accessor they provide:
680 * - get_texture() TextureBuffer and all its children
681 * - get_gpu_texture() NodeTextureBuffer
682 *
683 * New pixel-bearing buffer types satisfy this concept automatically by
684 * implementing either method with the correct return type. No registration
685 * or base class change required.
686 *
687 * Processors constrained by GpuImageSource use if constexpr to select
688 * the correct accessor at compile time.
689 */
690template <typename T>
691concept GpuImageSource = std::derived_from<T, VKBuffer> && (requires(const T& b) {
692 { b.get_texture() } -> std::convertible_to<std::shared_ptr<Core::VKImage>>; } || requires(const T& b) {
693 { b.get_gpu_texture() } -> std::convertible_to<std::shared_ptr<Core::VKImage>>; });
694
695} // namespace MayaFlux::Buffers
size_t b
const uint8_t * ptr
float offset
Central computational transformation interface for continuous buffer processing.
Backend-agnostic interface for sequential data storage and transformation.
Definition Buffer.hpp:37
Registry::Service::ComputeService * m_compute_service
Definition VKBuffer.hpp:668
Registry::Service::BufferService * m_buffer_service
Definition VKBuffer.hpp:667
void ensure_initialized(const std::shared_ptr< VKBuffer > &buffer)
Definition VKBuffer.cpp:448
std::vector< std::pair< size_t, size_t > > m_dirty_ranges
Definition VKBuffer.hpp:651
bool is_render_config_dirty() const
Check if config has changed since last frame.
Definition VKBuffer.hpp:542
std::unordered_map< RenderPipelineID, std::shared_ptr< Core::Window > > get_render_pipelines() const
Get all render pipelines associated with this buffer.
Definition VKBuffer.hpp:444
size_t get_index_buffer_size() const
Number of bytes in the index buffer.
Definition VKBuffer.hpp:357
void * get_mapped_ptr() const
Get mapped host pointer (nullptr if not host-visible or unmapped)
Definition VKBuffer.hpp:393
CommandBufferID get_pipeline_command(RenderPipelineID pipeline_id) const
Get recorded command buffer for a pipeline.
Definition VKBuffer.hpp:461
ProcessingToken m_processing_token
Definition VKBuffer.hpp:644
void set_pipeline_command(RenderPipelineID pipeline_id, CommandBufferID cmd_id)
Store recorded command buffer for a pipeline.
Definition VKBuffer.hpp:452
PipelineContext m_pipeline_context
Definition VKBuffer.hpp:645
void set_render_processor(std::shared_ptr< RenderProcessor > rp)
Definition VKBuffer.hpp:583
std::unordered_map< RenderPipelineID, std::shared_ptr< Core::Window > > m_window_pipelines
Definition VKBuffer.hpp:648
std::optional< Kakshya::VertexLayout > m_vertex_layout
Definition VKBuffer.hpp:634
std::vector< Kakshya::DataDimension > m_dimensions
Definition VKBuffer.hpp:632
std::shared_ptr< Buffers::BufferProcessingChain > m_processing_chain
Definition VKBuffer.hpp:643
bool is_processing() const override
Query whether the buffer is currently being processed.
Definition VKBuffer.hpp:269
RenderConfig get_render_config() const
Get the current render configuration.
Definition VKBuffer.hpp:548
EngineContext m_engine_context
Definition VKBuffer.hpp:646
bool has_render_pipeline() const
Check if this buffer has a rendering pipeline configured.
Definition VKBuffer.hpp:435
bool needs_depth_attachment() const
Check if this buffer requires depth attachment for rendering.
Definition VKBuffer.hpp:572
bool needs_removal() const override
Checks if the buffer should be removed from processing chains.
Definition VKBuffer.hpp:238
bool has_data_for_cycle() const override
Checks if the buffer has data for the current processing cycle.
Definition VKBuffer.hpp:237
VKBufferResources & get_buffer_resources()
Get all buffer resources at once (mutable).
Definition VKBuffer.hpp:344
virtual std::shared_ptr< RenderProcessor > get_render_processor() const
Get a RenderProcessor suitable for rendering this buffer.
Definition VKBuffer.hpp:581
void clear_pipeline_commands()
Clear all recorded commands (called after presentation)
Definition VKBuffer.hpp:470
vk::Buffer get_index_buffer() const
Return the raw index buffer handle.
Definition VKBuffer.hpp:350
Usage get_usage() const
Retrieve the declared usage intent.
Definition VKBuffer.hpp:305
const EngineContext & get_engine_context() const
Definition VKBuffer.hpp:530
Kakshya::DataModality get_modality() const
Get the buffer's semantic modality.
Definition VKBuffer.hpp:293
const PipelineContext & get_pipeline_context() const
Access the pipeline context for custom metadata (const)
Definition VKBuffer.hpp:527
EngineContext & get_engine_context()
Definition VKBuffer.hpp:529
std::vector< std::pair< size_t, size_t > > m_invalid_ranges
Definition VKBuffer.hpp:652
void set_mapped_ptr(void *ptr)
Set mapped host pointer (for host-visible allocations)
Definition VKBuffer.hpp:314
vk::DeviceSize get_size_bytes() const
Definition VKBuffer.hpp:278
bool has_index_buffer() const
True when an index buffer has been associated with this buffer.
Definition VKBuffer.hpp:362
std::optional< Kakshya::VertexLayout > get_vertex_layout() const
Get vertex layout if set.
Definition VKBuffer.hpp:489
VKBufferResources m_resources
Definition VKBuffer.hpp:623
PipelineContext & get_pipeline_context()
Access the pipeline context for custom metadata (non-const)
Definition VKBuffer.hpp:524
void clear_vertex_layout()
Clear vertex layout.
Definition VKBuffer.hpp:499
void set_memory(vk::DeviceMemory memory)
Set device memory handle after backend allocation.
Definition VKBuffer.hpp:311
void set_needs_depth_attachment(bool needs)
Mark this buffer as requiring depth testing when rendered.
Definition VKBuffer.hpp:567
vk::Buffer & get_buffer()
Get VkBuffer handle (VK_NULL_HANDLE if not registered)
Definition VKBuffer.hpp:275
bool needs_default_processing() override
Checks if the buffer should undergo default processing.
Definition VKBuffer.hpp:242
std::shared_ptr< Buffers::BufferProcessor > m_default_processor
Definition VKBuffer.hpp:642
virtual void setup_processors(ProcessingToken token)
Setup processors with a processing token.
Definition VKBuffer.hpp:290
virtual void mark_render_config_dirty(bool is_dirty=true)
Mark config as changed (processors will detect and react)
Definition VKBuffer.hpp:537
void set_pipeline_window(RenderPipelineID id, const std::shared_ptr< Core::Window > &window)
Associate this buffer with a window for rendering.
Definition VKBuffer.hpp:414
bool is_initialized() const
Check whether Vulkan handles are present (buffer registered)
Definition VKBuffer.hpp:281
void enforce_default_processing(bool should_process) override
Controls whether the buffer should use default processing.
Definition VKBuffer.hpp:241
bool is_internal_only() const override
Check whether this buffer is for internal engine usage.
Definition VKBuffer.hpp:521
void set_buffer(vk::Buffer buffer)
Set VkBuffer handle after backend allocation.
Definition VKBuffer.hpp:308
bool has_vertex_layout() const
Check if this buffer has vertex layout configured.
Definition VKBuffer.hpp:494
const std::vector< Kakshya::DataDimension > & get_dimensions() const
Get the inferred data dimensions for the buffer contents.
Definition VKBuffer.hpp:296
std::shared_ptr< RenderProcessor > m_render_processor
Definition VKBuffer.hpp:620
virtual void set_render_config(const RenderConfig &config)
Update the render configuration and mark as dirty.
Definition VKBuffer.hpp:558
void set_index_resources(vk::Buffer buf, vk::DeviceMemory mem, size_t size)
Store raw index buffer handles produced by the geometry upload path.
Definition VKBuffer.hpp:333
std::atomic< bool > m_is_processing
Definition VKBuffer.hpp:641
void set_default_render_config(const RenderConfig &config)
Called by derived classes to set their context-specific defaults.
Definition VKBuffer.hpp:597
Kakshya::DataModality m_modality
Definition VKBuffer.hpp:631
void release_processing() override
Release previously acquired processing lock.
Definition VKBuffer.hpp:260
void set_buffer_resources(const VKBufferResources &resources)
Set all buffer resources at once.
Definition VKBuffer.hpp:317
const VKBufferResources & get_buffer_resources() const
Get all buffer resources at once (read-only)
Definition VKBuffer.hpp:341
void force_internal_usage(bool internal) override
Set whether this buffer is for internal engine usage.
Definition VKBuffer.hpp:518
size_t get_size() const
Get current logical size in bytes.
Definition VKBuffer.hpp:198
void mark_for_removal() override
Marks the buffer for removal from processing chains.
Definition VKBuffer.hpp:240
std::unordered_map< RenderPipelineID, CommandBufferID > m_pipeline_commands
Definition VKBuffer.hpp:649
bool is_host_visible() const
Whether this VKBuffer should be host-visible.
Definition VKBuffer.hpp:371
void mark_for_processing(bool has_data) override
Marks the buffer's data availability for the current processing cycle.
Definition VKBuffer.hpp:239
std::shared_ptr< Core::Window > get_pipeline_window(RenderPipelineID id) const
Get the window associated with this buffer.
Definition VKBuffer.hpp:423
~VKBuffer() override
Virtual destructor.
bool try_acquire_processing() override
Try to acquire processing lock for this buffer.
Definition VKBuffer.hpp:250
Vulkan-backed buffer wrapper used in processing chains.
Definition VKBuffer.hpp:76
Satisfied by any VKBuffer subclass that exposes a GPU-resident image.
Definition VKBuffer.hpp:691
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
uint64_t RenderPipelineID
Definition VKBuffer.hpp:51
uint64_t CommandBufferID
Definition VKBuffer.hpp:52
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:164
BufferUsageHint
Semantic usage hint for buffer allocation and memory properties.
std::vector< GenerationSlot > back_buffers
Definition VKBuffer.hpp:48
Raw Vulkan handles owned by a VKBuffer instance.
Definition VKBuffer.hpp:34
std::vector< Portal::Graphics::DescriptorBindingInfo > ssbo_bindings
Definition VKBuffer.hpp:106
Engine-internal per-frame binding state.
Definition VKBuffer.hpp:105
std::vector< Portal::Graphics::DescriptorBindingInfo > descriptor_buffer_bindings
Definition VKBuffer.hpp:91
std::vector< Portal::Graphics::PushConstantBindingInfo > push_constant_bindings
Definition VKBuffer.hpp:89
std::unordered_map< std::string, std::any > metadata
Definition VKBuffer.hpp:93
Context shared with BufferProcessors during pipeline execution.
Definition VKBuffer.hpp:88
Complete description of vertex data layout in a buffer.
Unified rendering configuration for graphics buffers.
Backend buffer management service interface.
Backend compute shader and pipeline service interface.