MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureBuffer.hpp
Go to the documentation of this file.
1#pragma once
2
6
7namespace MayaFlux::Buffers {
8
9class TextureProcessor;
10class RenderProcessor;
11
12/**
13 * @class TextureBuffer
14 * @brief A hybrid buffer managing both a textured quad geometry and its pixel data.
15 *
16 * TextureBuffer serves a dual purpose:
17 * 1. Geometry: It acts as a VKBuffer containing vertex data for a 2D quad (Position + UVs).
18 * This geometry can be transformed (translated, scaled, rotated) or customized.
19 * 2. Texture: It manages raw pixel data in system memory and synchronizes it with a
20 * GPU-resident VKImage via the TextureProcessor.
21 *
22 * Unlike a raw texture resource, this class represents a "renderable sprite" or "surface".
23 * The vertex data is dynamic and updates automatically when transforms change.
24 * The pixel data can be static (loaded once) or dynamic (procedural/video), with
25 * dirty-flag tracking to minimize bus traffic.
26 *
27 * Key Features:
28 * - Automatic quad generation based on dimensions.
29 * - Built-in 2D transform support (Position, Scale, Rotation) affecting vertex positions.
30 * - CPU-side pixel storage with automatic upload to GPU VKImage on change.
31 * - Support for custom vertex geometry (e.g., for non-rectangular sprites).
32 */
33class MAYAFLUX_API TextureBuffer : public VKBuffer {
34public:
35 /**
36 * @brief Create texture buffer with dimensions
37 * @param width Texture width in pixels
38 * @param height Texture height in pixels
39 * @param format Pixel format
40 * @param initial_pixel_data Optional initial pixel data (nullptr = uninitialized)
41 *
42 * The VKBuffer itself contains fullscreen quad vertices.
43 * The texture pixels are stored separately and uploaded to VKImage.
44 */
46 uint32_t width,
47 uint32_t height,
49 const void* initial_pixel_data = nullptr);
50
51 ~TextureBuffer() override = default;
52
53 void setup_processors(ProcessingToken token) override;
54
55 // =========================================================================
56 // Texture Metadata
57 // =========================================================================
58
59 [[nodiscard]] uint32_t get_width() const { return m_width; }
60 [[nodiscard]] uint32_t get_height() const { return m_height; }
61 [[nodiscard]] Portal::Graphics::ImageFormat get_format() const { return m_format; }
62
63 // =========================================================================
64 // GPU Texture Access
65 // =========================================================================
66
67 /**
68 * @brief Get GPU texture image
69 * Suitable for binding to shaders via RenderProcessor::bind_texture()
70 */
71 [[nodiscard]] std::shared_ptr<Core::VKImage> get_texture() const { return m_gpu_texture; }
72 [[nodiscard]] bool has_texture() const { return m_gpu_texture != nullptr; }
73
74 /**
75 * @brief Inject a pre-existing GPU texture, bypassing TextureProcessor allocation.
76 *
77 * Safe to call before or after setup_processors(). When called before
78 * setup_processors(), TextureProcessor skips create_gpu_texture() and
79 * upload_initial_pixels() because has_texture() returns true. When called
80 * after setup_processors(), the RenderProcessor descriptor set is updated
81 * immediately so the new image is visible from the next rendered frame.
82 *
83 * No pixel upload occurs in either case — the image is assumed to already
84 * be resident on the GPU.
85 *
86 * @param image Initialized VKImage. Must not be null.
87 */
88 void set_gpu_texture(std::shared_ptr<Core::VKImage> image);
89
90 /**
91 * @brief Get the GPU texture image
92 * @return Shared pointer to the GPU-resident VKImage, or nullptr if not set
93 */
94 std::shared_ptr<Core::VKImage> get_gpu_texture() { return m_gpu_texture; }
95 std::shared_ptr<Core::VKImage> get_gpu_texture() const { return m_gpu_texture; }
96
97 // === Processor Access ===
98 [[nodiscard]] std::shared_ptr<TextureProcessor> get_texture_processor() const
99 {
100 return m_texture_processor;
101 }
102
103 /**
104 * @brief Replace pixel data
105 * @param data Pointer to pixel data (size must match width*height*channels)
106 * @param size Size in bytes
107 *
108 * Marks texture as dirty. TextureProcessor will re-upload on next frame.
109 */
110 void set_pixel_data(const void* data, size_t size);
111
112 /**
113 * @brief Mark pixel data as changed
114 * Use this if you modify pixel data in-place without calling set_pixel_data()
115 */
116 void mark_pixels_dirty();
117
118 /**
119 * @brief Reallocate the GPU texture at new dimensions.
120 *
121 * Resets the GPU texture handle so TextureProcessor allocates a fresh
122 * VKImage at the updated dimensions on the next processing cycle.
123 * Marks texture and geometry dirty. Invalidates the streaming staging
124 * buffer so it is reallocated at the correct size.
125 *
126 * @param new_width New texture width in pixels.
127 * @param new_height New texture height in pixels.
128 */
129 void resize_texture(uint32_t new_width, uint32_t new_height);
130
131 // =========================================================================
132 // Display Transform
133 // =========================================================================
134
135 /**
136 * @brief Set screen position (NDC or pixel coords depending on rendering setup)
137 * @param x X position
138 * @param y Y position
139 *
140 * Marks geometry as dirty. TextureProcessor will recalculate vertices on next frame.
141 */
142 void set_position(float x, float y);
143
144 /**
145 * @brief Set display size
146 * @param width Width in pixels/units
147 * @param height Height in pixels/units
148 *
149 * Marks geometry as dirty.
150 */
151 void set_scale(float width, float height);
152
153 /**
154 * @brief Set rotation around center
155 * @param angle_radians Rotation in radians
156 *
157 * Marks geometry as dirty.
158 */
159 void set_rotation(float angle_radians);
160
161 [[nodiscard]] glm::vec2 get_position() const { return m_position; }
162 [[nodiscard]] glm::vec2 get_scale() const { return m_scale; }
163 [[nodiscard]] float get_rotation() const { return m_rotation; }
164
165 // =========================================================================
166 // Advanced: Custom Geometry
167 // =========================================================================
168
169 void set_custom_vertices(const std::vector<Nodes::TextureQuadVertex>& vertices);
170
171 /**
172 * @brief Reset to default fullscreen quad
173 * Uses position and scale to generate quad geometry.
174 */
175 void use_default_quad();
176
177 [[nodiscard]] const std::vector<uint8_t>& get_pixel_data() const { return m_pixel_data; }
178 [[nodiscard]] std::vector<uint8_t>& get_pixel_data_mutable() { return m_pixel_data; }
179
180 void mark_texture_dirty() { m_texture_dirty = true; }
181 [[nodiscard]] bool is_texture_dirty() const { return m_texture_dirty; }
182 void clear_dirty_flag() { m_texture_dirty = false; }
183
184 /**
185 * @brief Setup rendering with RenderProcessor
186 * @param config Rendering configuration
187 */
188 virtual void setup_rendering(const RenderConfig& config);
189
190 std::shared_ptr<RenderProcessor> get_render_processor() const override
191 {
192 return m_render_processor;
193 }
194
195protected:
196 /**
197 * @brief Allow inherited classes to set the TextureProcessor directly
198 * @param processor Shared pointer to the TextureProcessor managing this buffer
199 */
200 inline void set_texture_processor(const std::shared_ptr<TextureProcessor>& processor)
201 {
202 m_texture_processor = processor;
203 }
204
205private:
206 friend class TextureProcessor;
207
208 std::shared_ptr<RenderProcessor> m_render_processor;
209
210 // Texture metadata
211 uint32_t m_width;
212 uint32_t m_height;
214
215 // Pixel data
216 std::vector<uint8_t> m_pixel_data;
217 bool m_texture_dirty = true;
218
219 // Display transform
220 glm::vec2 m_position { 0.0F, 0.0F };
221 glm::vec2 m_scale { 1.0F, 1.0F };
222 float m_rotation { 0.0F };
223 bool m_geometry_dirty = true;
224
225 // Geometry
226 std::vector<uint8_t> m_vertex_bytes;
227 bool m_uses_custom_vertices = false;
228
229 // GPU resources
230 std::shared_ptr<Core::VKImage> m_gpu_texture;
231 std::shared_ptr<TextureProcessor> m_texture_processor;
232
233 // Geometry generation
234 void generate_default_quad();
235 void generate_quad_with_transform();
236 static size_t calculate_quad_vertex_size();
237};
238
239} // namespace MayaFlux::Buffers
IO::ImageData image
uint32_t width
Range size
std::shared_ptr< TextureProcessor > get_texture_processor() const
std::shared_ptr< TextureProcessor > m_texture_processor
std::shared_ptr< Core::VKImage > m_gpu_texture
Portal::Graphics::ImageFormat get_format() const
std::vector< uint8_t > m_pixel_data
std::shared_ptr< RenderProcessor > m_render_processor
std::shared_ptr< RenderProcessor > get_render_processor() const override
Get a RenderProcessor suitable for rendering this buffer.
~TextureBuffer() override=default
const std::vector< uint8_t > & get_pixel_data() const
std::shared_ptr< Core::VKImage > get_gpu_texture() const
Portal::Graphics::ImageFormat m_format
std::shared_ptr< Core::VKImage > get_texture() const
Get GPU texture image Suitable for binding to shaders via RenderProcessor::bind_texture()
std::vector< uint8_t > m_vertex_bytes
void set_texture_processor(const std::shared_ptr< TextureProcessor > &processor)
Allow inherited classes to set the TextureProcessor directly.
std::vector< uint8_t > & get_pixel_data_mutable()
std::shared_ptr< Core::VKImage > get_gpu_texture()
Get the GPU texture image.
A hybrid buffer managing both a textured quad geometry and its pixel data.
Internal processor: handles CPU→GPU transfers for TextureBuffer.
Vulkan-backed buffer wrapper used in processing chains.
Definition VKBuffer.hpp:67
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
ImageFormat
User-friendly image format enum.