MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureContainer.hpp
Go to the documentation of this file.
1#pragma once
2
5
7
8namespace MayaFlux::Core {
9class VKImage;
10}
11
12namespace MayaFlux::Buffers {
13class VKBuffer;
14}
15
16namespace MayaFlux::Kakshya {
17
18/**
19 * @class TextureContainer
20 * @brief SignalSourceContainer wrapping GPU texture data as addressable pixel bytes.
21 *
22 * TextureContainer is the Kakshya-layer representation of a 2D texture.
23 * It owns a flat interleaved RGBA/float pixel buffer matching the declared
24 * ImageFormat, described with IMAGE_COLOR or IMAGE_2D dimensions.
25 *
26 * The container is the data carrier for Yantra::Texture workflow pipelines.
27 * GPU materialization is intentionally not automatic: callers drive upload
28 * and download explicitly via from_image() and to_image(), keeping the
29 * container decoupled from any specific VKImage lifetime.
30 *
31 * Dimension convention (IMAGE_COLOR, INTERLEAVED):
32 * dims[0] -> SPATIAL_Y (height)
33 * dims[1] -> SPATIAL_X (width)
34 * dims[2] -> CHANNEL (bytes per pixel for format)
35 *
36 * Processing model:
37 * No default processor is created. The container holds bytes passively.
38 * Workflow operations receive and return TextureContainer instances;
39 * TextureExecutionContext dispatches compute shaders against them.
40 * Concurrent image materialization calls on one container are serialized.
41 */
42class MAYAFLUX_API TextureContainer : public SignalSourceContainer {
43public:
44 /**
45 * @brief Construct an empty container with declared dimensions.
46 * @param width Texture width in pixels.
47 * @param height Texture height in pixels.
48 * @param format Pixel format; determines bytes per pixel.
49 * @param layers Number of array layers (default 1). set when using with array textures.
50 *
51 * Allocates a zeroed pixel buffer. No GPU resource is created.
52 */
53 TextureContainer(uint32_t width, uint32_t height, ImageFormat format, uint32_t layers = 1);
54
55 /**
56 * @brief Construct from an existing VKImage, downloading its pixel data.
57 * @param image Source GPU texture. Must be initialized.
58 * @param format Pixel format of the image.
59 *
60 * Performs a blocking GPU->CPU download via TextureLoom.
61 * Equivalent to constructing empty then calling from_image().
62 */
64 const std::shared_ptr<Core::VKImage>& image,
66
67 ~TextureContainer() override = default;
68
73
74 [[nodiscard]] uint32_t get_layer_count() const { return static_cast<uint32_t>(m_data.size()); }
75
76 //=========================================================================
77 // GPU bridge
78 //=========================================================================
79
80 /**
81 * @brief Download pixel data from a VKImage into this container.
82 * @param image Source GPU texture. Must be initialized and match dimensions.
83 * @param layer Array layer index for array textures (default 0).
84 *
85 * Blocking. Overwrites the existing pixel buffer. Does not change
86 * declared width, height, or format — caller must ensure consistency.
87 */
88 void from_image(const std::shared_ptr<Core::VKImage>& image, uint32_t layer = 0);
89
90 /**
91 * @brief Download pixel data from a VKImage, reusing a caller-supplied
92 * persistent staging buffer.
93 *
94 * Identical to from_image() but passes @p staging through to
95 * TextureLoom::download_data, eliminating the per-call Vulkan object
96 * allocation. Use Buffers::create_image_staging_buffer(byte_size())
97 * to allocate the staging buffer once before the render loop.
98 *
99 * @param image Source GPU texture. Must be initialised and match dimensions.
100 * @param staging Host-visible staging VKBuffer sized to at least byte_size().
101 * @param layer Array layer index (default 0).
102 */
103 void from_image(
104 const std::shared_ptr<Core::VKImage>& image,
105 const std::shared_ptr<Buffers::VKBuffer>& staging,
106 uint32_t layer = 0);
107
108 /**
109 * @brief Download each array layer of a Vulkan 2D array image into
110 * the corresponding layer slot.
111 *
112 * Expects @p image to have array_layers == get_layer_count(). Downloads
113 * each layer via a separate blocking TextureLoom::download_data call.
114 * Resizes m_data to match if necessary.
115 *
116 * @param image Source VKImage with array_layers >= get_layer_count().
117 */
118 void from_image_array(const std::shared_ptr<Core::VKImage>& image);
119
120 /**
121 * @brief Download all array layers from a VKImage, reusing a caller-supplied
122 * persistent staging buffer.
123 *
124 * Identical to from_image_array() but passes @p staging through to
125 * TextureLoom::download_data. The staging buffer must be at least
126 * byte_size() * get_layer_count() bytes.
127 * Use Buffers::create_image_staging_buffer(byte_size() * get_layer_count())
128 * to allocate it once before the render loop.
129 *
130 * @param image Source VKImage with array_layers >= get_layer_count().
131 * @param staging Host-visible staging VKBuffer sized to at least
132 * byte_size() * get_layer_count().
133 */
134 void from_image_array(
135 const std::shared_ptr<Core::VKImage>& image,
136 const std::shared_ptr<Buffers::VKBuffer>& staging);
137
138 /**
139 * @brief Refresh the container-owned VKImage for one layer.
140 * @param layer Array layer index for array textures (default 0).
141 * @return Cached and uploaded VKImage. Null on failure.
142 *
143 * Reuses a container-owned image for this layer while dimensions and
144 * format match. Later calls refresh the same image, so it is live rather
145 * than a snapshot. A layer held on the GPU is returned as is, without an
146 * upload.
147 */
148 [[nodiscard]] std::shared_ptr<Core::VKImage> to_image(uint32_t layer = 0) const;
149
150 /**
151 * @brief Refresh one layer's cached VKImage with caller-supplied staging.
152 *
153 * Reuses the container-owned image and uploads via the supplied staging
154 * buffer.
155 *
156 * @param layer Array layer index (default 0).
157 * @param staging Host-visible staging VKBuffer sized to at least byte_size().
158 * @return Cached VKImage, or nullptr on failure.
159 */
160 [[nodiscard]] std::shared_ptr<Core::VKImage> to_image(
161 uint32_t layer,
162 const std::shared_ptr<Buffers::VKBuffer>& staging) const;
163
164 /**
165 * @brief Upload all layers as a Vulkan 2D array texture.
166 *
167 * Concatenates pixel data from all layers in order (layer 0 first) and
168 * refreshes a container-owned array image. The returned VKImage has
169 * array_layers == get_layer_count() and an image view of type
170 * VK_IMAGE_VIEW_TYPE_2D_ARRAY, making it bindable as sampler2DArray
171 * in GLSL.
172 *
173 * All layers must have the expected byte count; otherwise this returns null.
174 *
175 * @return Cached array image when multiple layers exist, or a cached 2D
176 * image for one layer. Null on failure.
177 */
178 [[nodiscard]] std::shared_ptr<Core::VKImage> to_image_array() const;
179
180 /**
181 * @brief Upload all layers as a Vulkan 2D array texture, reusing a staging buffer.
182 *
183 * Concatenates pixel data from all layers in order (layer 0 first) and
184 * refreshes a container-owned array image. The returned VKImage has
185 * array_layers == get_layer_count() and an image view of type
186 * VK_IMAGE_VIEW_TYPE_2D_ARRAY, making it bindable as sampler2DArray
187 * in GLSL.
188 *
189 * All layers must have the expected byte count; otherwise this returns null.
190 *
191 * @param staging Host-visible staging VKBuffer sized to at least
192 * byte_size() * get_layer_count().
193 * @return Cached array image when multiple layers exist, or a cached 2D
194 * image for one layer. Null on failure.
195 */
196 [[nodiscard]] std::shared_ptr<Core::VKImage> to_image_array(
197 const std::shared_ptr<Buffers::VKBuffer>& staging) const;
198
199 /**
200 * @brief Upload one layer into an existing VKImage instead of creating one.
201 *
202 * Use this for an image retained separately from the container, such as
203 * an execution context's input image.
204 *
205 * @param image Target image. Must match this container's width, height
206 * and format, and be a single layer 2D image.
207 * @param layer Array layer index (default 0).
208 * @param staging Host-visible staging VKBuffer sized to at least byte_size().
209 * @return True when the layer was uploaded, false when the layer is out of
210 * range, empty, or the image is null.
211 */
212 bool upload_image(
213 const std::shared_ptr<Core::VKImage>& image,
214 uint32_t layer,
215 const std::shared_ptr<Buffers::VKBuffer>& staging) const;
216
217 /**
218 * @brief Upload all layers into an existing VKImage instead of creating one.
219 *
220 * The counterpart of to_image_array(staging). A single layer container
221 * targets a plain 2D image, more layers a 2D array image with
222 * array_layers == get_layer_count().
223 *
224 * @param image Target image created by to_image_array.
225 * @param staging Host-visible staging VKBuffer sized to at least
226 * byte_size() * get_layer_count().
227 * @return True when every layer was uploaded, false on a null image, an
228 * empty container, or a layer of unexpected size.
229 */
230 bool upload_image_array(
231 const std::shared_ptr<Core::VKImage>& image,
232 const std::shared_ptr<Buffers::VKBuffer>& staging) const;
233
234 //=========================================================================
235 // Pixel access
236 //=========================================================================
237
238 /**
239 * @brief Read-only byte-level view over the pixel buffer.
240 *
241 * The returned span covers the raw byte footprint of the layer,
242 * regardless of the underlying variant type. For uint8 formats this
243 * is the natural view; for uint16 and float formats the caller can
244 * reinterpret_cast for typed access, or prefer the as_uint16 /
245 * as_float accessors below.
246 *
247 * @param layer Array layer index for array textures (default 0).
248 */
249 [[nodiscard]] std::span<const uint8_t> pixel_bytes(uint32_t layer = 0) const;
250
251 /**
252 * @brief Read-write byte-level view over the pixel buffer.
253 * @param layer Array layer index for array textures (default 0).
254 */
255 [[nodiscard]] std::span<uint8_t> pixel_bytes(uint32_t layer = 0);
256
257 /**
258 * @brief Typed view over the uint8 variant.
259 * Returns an empty span if the layer's variant is not uint8.
260 */
261 [[nodiscard]] std::span<const uint8_t> as_uint8(uint32_t layer = 0) const;
262
263 /**
264 * @brief Typed view over the uint16 variant.
265 * Returns an empty span if the layer's variant is not uint16.
266 * 16-bit UNORM formats and half-float formats both reside here;
267 * for half-float, the uint16 bits are the IEEE-754 binary16
268 * encoding.
269 */
270 [[nodiscard]] std::span<const uint16_t> as_uint16(uint32_t layer = 0) const;
271
272 /**
273 * @brief Typed view over the float variant.
274 * Returns an empty span if the layer's variant is not float.
275 */
276 [[nodiscard]] std::span<const float> as_float(uint32_t layer = 0) const;
277
278 /**
279 * @brief Replace the layer's pixel buffer with a byte source.
280 * Valid only when the declared format is uint8-backed.
281 * Size must equal width * height * bytes_per_pixel.
282 */
283 void set_pixels(std::span<const uint8_t> data, uint32_t layer = 0);
284
285 /**
286 * @brief Replace the layer's pixel buffer with a uint16 source.
287 * Valid when the declared format is uint16-backed
288 * (R16/RG16/RGBA16, R16F/RG16F/RGBA16F).
289 * Size must equal width * height * channels.
290 */
291 void set_pixels(std::span<const uint16_t> data, uint32_t layer = 0);
292
293 /**
294 * @brief Replace the layer's pixel buffer with a float source.
295 * Valid when the declared format is float-backed
296 * (R32F/RG32F/RGBA32F).
297 * Size must equal width * height * channels.
298 */
299 void set_pixels(std::span<const float> data, uint32_t layer = 0);
300
301 /**
302 * @brief Layer pixel data as a normalised float span.
303 *
304 * uint8_t source is divided by 255.0f. uint16_t by 65535.0f.
305 * float source is zero-copy into the variant's own storage.
306 * Returns empty span if layer is out of range or the variant
307 * holds a non-pixel type.
308 *
309 * Result is cached per layer and reused until set_pixels()
310 * or from_image() invalidates it for that layer.
311 *
312 * @param layer Array layer index. Defaults to 0.
313 * @return Normalised float span, w * h * channels elements.
314 */
315 [[nodiscard]] std::span<const float> as_normalised_float(uint32_t layer = 0) const;
316
317 //=========================================================================
318 // Metadata
319 //=========================================================================
320
321 [[nodiscard]] uint32_t get_width() const { return m_width; }
322 [[nodiscard]] uint32_t get_height() const { return m_height; }
323 [[nodiscard]] ImageFormat get_format() const { return m_format; }
324 [[nodiscard]] uint32_t get_channel_count() const { return m_channels; }
325
326 /** @brief Byte count of one complete pixel row. */
327 [[nodiscard]] size_t row_stride() const { return static_cast<size_t>(m_width) * m_bpp; }
328
329 /** @brief Total byte count of the pixel buffer. */
330 [[nodiscard]] size_t byte_size() const { return static_cast<size_t>(m_width) * m_height * m_bpp; }
331
332 //=========================================================================
333 // NDDimensionalContainer
334 //=========================================================================
335
336 [[nodiscard]] std::vector<DataDimension> get_dimensions() const override;
337 [[nodiscard]] uint64_t get_total_elements() const override;
338 [[nodiscard]] MemoryLayout get_memory_layout() const override;
339 void set_memory_layout(MemoryLayout layout) override;
340 [[nodiscard]] uint64_t get_frame_size() const override;
341 [[nodiscard]] uint64_t get_num_frames() const override;
342
343 [[nodiscard]] std::vector<DataVariant> get_region_data(const Region& region) const override;
344 [[nodiscard]] std::vector<DataVariant> get_segments_data(
345 const std::vector<RegionSegment>& segments) const override;
346 [[nodiscard]] std::vector<DataVariant> get_region_group_data(const RegionGroup&) const override { return m_processed_data; }
347
348 [[nodiscard]] std::type_index value_element_type() const override;
349 [[nodiscard]] uint64_t coordinates_to_linear_index(const std::vector<uint64_t>& coords) const override;
350 [[nodiscard]] std::vector<uint64_t> linear_index_to_coordinates(uint64_t index) const override;
351 void clear() override;
352
353 //=========================================================================
354 // SignalSourceContainer
355 //=========================================================================
356
357 /**
358 * @brief Write DataVariant bytes into the pixel buffer at the region bounds.
359 *
360 * The region's SPATIAL_Y / SPATIAL_X coordinates are used as the destination
361 * rectangle. The first DataVariant in @p data must hold std::vector<uint8_t>
362 * with exactly region_width * region_height * channels bytes.
363 *
364 * @param region Destination region (start/end SPATIAL_Y, SPATIAL_X coords).
365 * @param data Source data. First element must be vector<uint8_t>.
366 */
367 void set_region_data(const Region& region,
368 const std::vector<DataVariant>& data) override;
369
370 [[nodiscard]] ProcessingState get_processing_state() const override;
371 void update_processing_state(ProcessingState state) override;
372 void register_state_change_callback(
373 std::function<void(const std::shared_ptr<SignalSourceContainer>&, ProcessingState)> cb) override;
374 void unregister_state_change_callback() override;
375
376 [[nodiscard]] bool is_ready_for_processing() const override;
377 void mark_ready_for_processing(bool ready) override;
378
379 [[nodiscard]] std::vector<DataVariant>& get_processed_data() override;
380 [[nodiscard]] const std::vector<DataVariant>& get_processed_data() const override;
381 [[nodiscard]] const std::vector<DataVariant>& get_data() override;
382
383 /** @brief No-op. TextureContainer has no BufferManager integration. */
384 void mark_buffers_for_processing(bool) override { }
385
386 /** @brief No-op. TextureContainer has no BufferManager integration. */
387 void mark_buffers_for_removal() override { }
388
389 [[nodiscard]] DataAccess channel_data(size_t channel_index) override;
390 [[nodiscard]] std::vector<DataAccess> all_channel_data() override;
391
392 /** @brief No-op. All pixel data is always resident; no streaming regions. */
393 void load_region(const Region&) override { }
394
395 /** @brief No-op. All pixel data is always resident; no streaming regions. */
396 void unload_region(const Region&) override { }
397 [[nodiscard]] bool is_region_loaded(const Region&) const override { return true; }
398
399 void add_region_group(const RegionGroup& group) override;
400 [[nodiscard]] RegionGroup get_region_group(const std::string& name) const override;
401 [[nodiscard]] std::unordered_map<std::string, RegionGroup> get_all_region_groups() const override;
402 void remove_region_group(const std::string& name) override;
403
404 [[nodiscard]] const void* get_raw_data() const override;
405 [[nodiscard]] bool has_data() const override;
406
407 [[nodiscard]] ContainerDataStructure& get_structure() override { return m_structure; }
408 [[nodiscard]] const ContainerDataStructure& get_structure() const override { return m_structure; }
409 void set_structure(ContainerDataStructure s) override { m_structure = std::move(s); }
410
411 void reset_processing_token() { m_processing_token.store(-1); }
413 {
414 int expected = -1;
415 return m_processing_token.compare_exchange_strong(expected, ch);
416 }
417 [[nodiscard]] bool has_processing_token(int ch) const
418 {
419 return m_processing_token.load() == ch;
420 }
421
422 /** @brief No-op. TextureContainer holds bytes passively; no processor lifecycle. */
423 void create_default_processor() override { }
424
425 /** @brief No-op. TextureContainer holds bytes passively; no processor lifecycle. */
426 void process_default() override { }
427
428 void set_default_processor(const std::shared_ptr<DataProcessor>& p) override { m_processor = p; }
429 std::shared_ptr<DataProcessor> get_default_processor() const override { return m_processor; }
430 std::shared_ptr<DataProcessingChain> get_processing_chain() override;
431 void set_processing_chain(const std::shared_ptr<DataProcessingChain>& c) override { m_chain = c; }
432
433 /**
434 * @brief No-op. TextureContainer does not track concurrent dimension readers.
435 * @return Always 0.
436 */
437 uint32_t register_dimension_reader(uint32_t) override { return 0; }
438
439 /** @brief No-op. TextureContainer does not track concurrent dimension readers. */
440 void unregister_dimension_reader(uint32_t) override { }
441
442 /**
443 * @brief No-op. TextureContainer does not track concurrent dimension readers.
444 * @return Always false.
445 */
446 [[nodiscard]] bool has_active_readers() const override { return false; }
447
448 /** @brief No-op. TextureContainer does not track concurrent dimension readers. */
449 void mark_dimension_consumed(uint32_t, uint32_t) override { }
450
451 /**
452 * @brief No-op. TextureContainer does not track concurrent dimension readers.
453 * @return Always true.
454 */
455 [[nodiscard]] bool all_dimensions_consumed() const override { return true; }
456
457protected:
458 /** @brief Exact layer count for subclasses, zero allowed. */
459 struct LayerCount {
460 uint32_t value {};
461 };
462
463 /**
464 * @brief Construct with exactly @p layers layers, which may be zero.
465 */
466 TextureContainer(uint32_t width, uint32_t height, ImageFormat format, LayerCount layers);
467
468 /**
469 * @brief Append one layer held on the GPU by @p image.
470 *
471 * The layer has no CPU pixels until a CPU accessor reads it, which
472 * downloads @p image once. Writing CPU pixels replaces the content.
473 * @p image must be a single layer sampled 2D image with this container's
474 * width, height and format. Not safe while another thread reads or writes
475 * the container.
476 *
477 * @return Index of the new layer.
478 */
479 uint32_t append_image_layer(std::shared_ptr<Core::VKImage> image);
480
481 /**
482 * @brief The GPU image backing @p layer, without uploading CPU pixels.
483 * @return Null when @p layer is out of range or has no image yet.
484 */
485 [[nodiscard]] std::shared_ptr<Core::VKImage> layer_image(uint32_t layer) const;
486
487 /**
488 * @brief Mark @p layer as held on the GPU after its image was rewritten.
489 *
490 * Drops the layer's CPU pixels, which a CPU accessor downloads again on
491 * its next read. Not safe while another thread reads or writes the
492 * container.
493 */
494 void hold_layer(uint32_t layer);
495
496 [[nodiscard]] auto get_frame_span_impl(uint64_t frame_index) const -> DataSpanVariant override
497 {
498 return get_frame_typed(frame_index);
499 }
500
501 void get_frames_impl(void* output, size_t count, uint64_t start_frame, uint64_t num_frames, const std::type_info& type) const override;
502
503 void get_value_impl(const std::vector<uint64_t>& coords,
504 void* out, const std::type_info& type) const override;
505
506 void set_value_impl(const std::vector<uint64_t>& coords,
507 const void* in, const std::type_info& type) override;
508
509private:
510 void setup_dimensions();
511
512 uint32_t m_width {};
513 uint32_t m_height {};
514 ImageFormat m_format {};
515 uint32_t m_channels {};
516 size_t m_bpp {};
517
518 mutable std::vector<DataVariant> m_data;
519 std::vector<DataVariant> m_processed_data;
520 mutable std::vector<Portal::Graphics::ImageCacheEntry> m_layer_image_cache;
523 std::shared_ptr<DataProcessor> m_processor;
524 std::shared_ptr<DataProcessingChain> m_chain;
525
526 mutable std::vector<std::vector<float>> m_normalised_cache;
527 mutable std::vector<std::atomic<bool>> m_normalised_dirty;
528
529 /** @brief Per layer: the GPU image in m_layer_image_cache holds the content, m_data does not. */
530 mutable std::vector<std::atomic<bool>> m_cpu_stale;
531
533
534 std::atomic<ProcessingState> m_processing_state { ProcessingState::IDLE };
535 std::atomic<bool> m_ready_for_processing { false };
536 std::atomic<int> m_processing_token { -1 };
537
541
542 std::function<void(const std::shared_ptr<SignalSourceContainer>&, ProcessingState)> m_state_cb;
543 std::unordered_map<std::string, RegionGroup> m_region_groups;
544
545 /** @brief Row cache backing the double span returned by get_frame(). */
546 mutable std::vector<double> m_frame_cache;
547
548 [[nodiscard]] std::shared_ptr<Core::VKImage> cached_layer_image(
549 uint32_t layer, const std::shared_ptr<Buffers::VKBuffer>& staging) const;
550 [[nodiscard]] std::shared_ptr<Core::VKImage> cached_array_image(
551 const std::shared_ptr<Buffers::VKBuffer>& staging) const;
552
553 /** @brief Download a GPU-held layer into m_data before a CPU read. */
554 void ensure_cpu(uint32_t layer) const;
555 void ensure_cpu_all() const;
556
557 /** @brief Give a GPU-held layer fresh CPU storage before a full overwrite. */
558 void claim_cpu(uint32_t layer);
559
560 [[nodiscard]] auto get_frame_typed(uint64_t frame_index) const -> DataSpanVariant;
561 void get_frames_typed(void* output, size_t count, uint64_t start_frame, uint64_t num_frames, const std::type_info& type) const;
562
563 template <typename T>
564 [[nodiscard]] auto get_frame_typed_as(uint64_t frame_index) const -> std::span<const T>;
565
566 template <typename T>
567 void get_frames_typed_as(std::span<T> output, uint64_t start_frame, uint64_t num_frames) const;
568};
569
570} // namespace MayaFlux::Kakshya
IO::ImageData image
Definition Decoder.cpp:47
bool format
std::vector< float > * out
glm::vec3 value
std::vector< glm::ivec3 > coords
Definition VDBWriter.cpp:25
vk::PhysicalDeviceType type
Definition VKDevice.cpp:126
std::string name
Definition VKDevice.cpp:123
uint32_t index
Definition VKDevice.cpp:122
size_t count
uint32_t width
uint32_t height
Type-erased accessor for NDData with semantic view construction.
Data-driven interface for managing arbitrary processable signal sources.
void unload_region(const Region &) override
No-op.
void load_region(const Region &) override
No-op.
std::vector< std::atomic< bool > > m_normalised_dirty
std::unordered_map< std::string, RegionGroup > m_region_groups
void set_processing_chain(const std::shared_ptr< DataProcessingChain > &c) override
Set the processing chain for this container.
void set_structure(ContainerDataStructure s) override
Set the data structure for this container.
~TextureContainer() override=default
TextureContainer(const TextureContainer &)=delete
ContainerDataStructure & get_structure() override
Get the data structure defining this container's layout.
std::vector< std::atomic< bool > > m_cpu_stale
Per layer: the GPU image in m_layer_image_cache holds the content, m_data does not.
bool has_active_readers() const override
No-op.
TextureContainer(TextureContainer &&)=delete
std::function< void(const std::shared_ptr< SignalSourceContainer > &, ProcessingState)> m_state_cb
std::vector< DataVariant > m_processed_data
void unregister_dimension_reader(uint32_t) override
No-op.
bool all_dimensions_consumed() const override
No-op.
const ContainerDataStructure & get_structure() const override
auto get_frame_span_impl(uint64_t frame_index) const -> DataSpanVariant override
Implementation-specific method to retrieve a frame span.
void set_default_processor(const std::shared_ptr< DataProcessor > &p) override
Set the default data processor for this container.
void mark_buffers_for_removal() override
No-op.
size_t row_stride() const
Byte count of one complete pixel row.
std::shared_ptr< DataProcessor > get_default_processor() const override
Get the current default data processor.
std::shared_ptr< DataProcessingChain > m_chain
uint32_t register_dimension_reader(uint32_t) override
No-op.
std::vector< double > m_frame_cache
Row cache backing the double span returned by get_frame().
std::vector< Portal::Graphics::ImageCacheEntry > m_layer_image_cache
void create_default_processor() override
No-op.
TextureContainer & operator=(const TextureContainer &)=delete
bool is_region_loaded(const Region &) const override
Check if a region is loaded in memory.
void mark_buffers_for_processing(bool) override
No-op.
std::vector< DataVariant > get_region_group_data(const RegionGroup &) const override
Get data for multiple regions efficiently.
std::vector< std::vector< float > > m_normalised_cache
std::shared_ptr< DataProcessor > m_processor
TextureContainer & operator=(TextureContainer &&)=delete
void mark_dimension_consumed(uint32_t, uint32_t) override
No-op.
size_t byte_size() const
Total byte count of the pixel buffer.
Portal::Graphics::ImageCacheEntry m_array_image_cache
SignalSourceContainer wrapping GPU texture data as addressable pixel bytes.
Indexed collection of independent, equal-ranked Seqlock instances.
Definition SeqLock.hpp:315
Sequence lock for fixed-size data regions.
Definition SeqLock.hpp:44
ProcessingState
Represents the current processing lifecycle state of a container.
void remove_region_group(std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Remove a RegionGroup by name from a group map.
ImageFormat
User-friendly image format enum.
Definition ImageData.hpp:12
std::optional< RegionGroup > get_region_group(const std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Get a RegionGroup by name from a group map.
typename detail::span_const_from_vector_variant< DataVariant >::type DataSpanVariant
Definition NDData.hpp:625
std::span< const float > as_normalised_float(const DataVariant &variant, std::vector< float > &storage)
Extract a DataVariant holding pixel data as a normalised float span.
Definition DataUtils.cpp:61
MemoryLayout
Memory layout for multi-dimensional data.
Definition NDData.hpp:33
void add_region_group(std::unordered_map< std::string, RegionGroup > &groups, const RegionGroup &group)
Add a RegionGroup to a group map.
Container structure for consistent dimension ordering.
Organizes related signal regions into a categorized collection.
Represents a point or span in N-dimensional space.
Definition Region.hpp:73
Exact layer count for subclasses, zero allowed.
Image retained by the producing owner.