MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureBuffer.cpp
Go to the documentation of this file.
1#include "TextureBuffer.hpp"
2
7
9
10namespace MayaFlux::Buffers {
11
13 uint32_t width,
14 uint32_t height,
16 const void* initial_pixel_data)
17 : VKBuffer(
18 calculate_quad_vertex_size(),
19 Usage::VERTEX,
20 Kakshya::DataModality::VERTEX_POSITIONS_3D)
21 , m_width(width)
22 , m_height(height)
23 , m_format(format)
24{
25 RenderConfig default_config;
26 default_config.vertex_shader = "texture.vert.spv";
27 default_config.fragment_shader = "texture.frag.spv";
28 default_config.default_texture_binding = "texSampler";
30 set_default_render_config(default_config);
31
32 if (initial_pixel_data) {
33 size_t pixel_bytes = static_cast<size_t>(width) * height * Portal::Graphics::TextureLoom::get_bytes_per_pixel(format);
34 m_pixel_data.resize(pixel_bytes);
35 std::memcpy(m_pixel_data.data(), initial_pixel_data, pixel_bytes);
36 }
37
39
41 "Created TextureBuffer: {}x{} ({} pixel bytes, {} vertex bytes)",
43}
44
46{
47 auto self = std::dynamic_pointer_cast<TextureBuffer>(shared_from_this());
48
49 m_texture_processor = std::make_shared<TextureProcessor>();
50 m_texture_processor->set_processing_token(token);
51
53
54 auto chain = get_processing_chain();
55 if (!chain) {
56 chain = std::make_shared<BufferProcessingChain>();
58 }
59 chain->set_preferred_token(token);
60
62 "TextureBuffer setup_processors: TextureProcessor will be attached on first registration");
63}
64
66{
67 if (!user_config.vertex_shader.empty()) {
69 }
70 if (!user_config.fragment_shader.empty()) {
72 }
73 if (!user_config.default_texture_binding.empty()) {
75 }
78 "TextureBuffer only supports TRIANGLE_STRIP topology. Ignoring provided topology.");
79 } else {
80 if (user_config.topology != m_render_config.topology) {
81 m_render_config.topology = user_config.topology;
82 }
83 }
85
86 if (!user_config.additional_textures.empty()) {
87 for (const auto& [name, texture] : user_config.additional_textures) {
88 m_render_config.additional_textures.emplace_back(name, texture);
89 }
90 }
91
92 if (!m_render_processor) {
95 0, 1, vk::DescriptorType::eCombinedImageSampler);
96
97 uint32_t binding_index = 1;
98 for (const auto& [name, _] : m_render_config.additional_textures) {
99 shader_config.bindings[name] = ShaderBinding(
100 1, binding_index++, vk::DescriptorType::eCombinedImageSampler);
101 }
102
103 m_render_processor = std::make_shared<RenderProcessor>(shader_config);
104 }
105
107 m_render_processor->set_target_window(m_render_config.target_window, std::dynamic_pointer_cast<VKBuffer>(shared_from_this()));
108 m_render_processor->set_primitive_topology(m_render_config.topology);
109
111
112 for (const auto& [name, texture] : m_render_config.additional_textures) {
113 m_render_processor->bind_texture(name, texture);
114 }
115
116 get_processing_chain()->add_final_processor(m_render_processor, shared_from_this());
117}
118
119// =========================================================================
120// Pixel Data Management
121// =========================================================================
122
123void TextureBuffer::set_pixel_data(const void* data, size_t size)
124{
125 if (!data || size == 0) {
127 "set_pixel_data called with null or empty data");
128 return;
129 }
130
131 m_pixel_data.resize(size);
132 std::memcpy(m_pixel_data.data(), data, size);
133 m_texture_dirty = true;
134
136 "TextureBuffer: pixel data updated ({} bytes, marked dirty)", size);
137}
138
143
144void TextureBuffer::set_gpu_texture(std::shared_ptr<Core::VKImage> image)
145{
146 m_gpu_texture = std::move(image);
147
149 m_render_processor->bind_texture(
152 }
153}
154
155void TextureBuffer::resize_texture(uint32_t new_width, uint32_t new_height)
156{
157 if (new_width == m_width && new_height == m_height) {
158 return;
159 }
160
161 m_width = new_width;
162 m_height = new_height;
163 m_gpu_texture.reset();
164 m_texture_dirty = true;
165 m_geometry_dirty = true;
166
167 if (auto proc = get_texture_processor()) {
168 proc->invalidate_staging();
169 }
170}
171
172// =========================================================================
173// Display Transform
174// =========================================================================
175
176void TextureBuffer::set_position(float x, float y)
177{
178 if (m_position.x != x || m_position.y != y) {
179 m_position = { x, y };
180 m_geometry_dirty = true;
181
183 "TextureBuffer: position set to ({}, {}), geometry marked dirty", x, y);
184 }
185}
186
187void TextureBuffer::set_scale(float width, float height)
188{
189 if (m_scale.x != width || m_scale.y != height) {
190 m_scale = { width, height };
191 m_geometry_dirty = true;
192
194 "TextureBuffer: scale set to ({}, {}), geometry marked dirty", width, height);
195 }
196}
197
198void TextureBuffer::set_rotation(float angle_radians)
199{
200 if (m_rotation != angle_radians) {
201 m_rotation = angle_radians;
202 m_geometry_dirty = true;
203
205 "TextureBuffer: rotation set to {}, geometry marked dirty", angle_radians);
206 }
207}
208
209// =========================================================================
210// Custom Geometry
211// =========================================================================
212
213void TextureBuffer::set_custom_vertices(const std::vector<Nodes::TextureQuadVertex>& vertices)
214{
215 if (vertices.size() != 4) {
217 "set_custom_vertices: must provide exactly 4 vertices, got {}", vertices.size());
218 return;
219 }
220
221 m_vertex_bytes.resize(vertices.size() * sizeof(Nodes::TextureQuadVertex));
222 std::memcpy(m_vertex_bytes.data(), vertices.data(), m_vertex_bytes.size());
224 m_geometry_dirty = true;
225
227 "TextureBuffer: custom vertices set, geometry marked dirty");
228}
229
231{
235 m_geometry_dirty = true;
236
238 "TextureBuffer: reset to default quad, geometry marked dirty");
239 }
240}
241
242// =========================================================================
243// Geometry Generation
244// =========================================================================
245
250
252{
254 m_vertex_bytes.resize(geo.vertices.size() * sizeof(Nodes::TextureQuadVertex));
255 std::memcpy(m_vertex_bytes.data(), geo.vertices.data(), m_vertex_bytes.size());
256 set_vertex_layout(geo.layout);
257
259 "TextureBuffer: generated default quad");
260}
261
263{
266 "TextureBuffer: using custom vertices, skipping transform");
267 return;
268 }
269
271 m_vertex_bytes.resize(geo.vertices.size() * sizeof(Nodes::TextureQuadVertex));
272 std::memcpy(m_vertex_bytes.data(), geo.vertices.data(), m_vertex_bytes.size());
273
275 "TextureBuffer: regenerated quad with transform (pos={},{}, scale={},{}, rot={})",
277}
278
279} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
IO::ImageData image
uint32_t width
Range size
void setup_processors(ProcessingToken token) override
Setup processors with a processing token.
void set_gpu_texture(std::shared_ptr< Core::VKImage > image)
Inject a pre-existing GPU texture, bypassing TextureProcessor allocation.
std::shared_ptr< TextureProcessor > get_texture_processor() const
void use_default_quad()
Reset to default fullscreen quad Uses position and scale to generate quad geometry.
std::shared_ptr< TextureProcessor > m_texture_processor
std::shared_ptr< Core::VKImage > m_gpu_texture
std::vector< uint8_t > m_pixel_data
std::shared_ptr< RenderProcessor > m_render_processor
virtual void setup_rendering(const RenderConfig &config)
Setup rendering with RenderProcessor.
void mark_pixels_dirty()
Mark pixel data as changed Use this if you modify pixel data in-place without calling set_pixel_data(...
void set_position(float x, float y)
Set screen position (NDC or pixel coords depending on rendering setup)
void resize_texture(uint32_t new_width, uint32_t new_height)
Reallocate the GPU texture at new dimensions.
TextureBuffer(uint32_t width, uint32_t height, Portal::Graphics::ImageFormat format, const void *initial_pixel_data=nullptr)
Create texture buffer with dimensions.
void set_custom_vertices(const std::vector< Nodes::TextureQuadVertex > &vertices)
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_rotation(float angle_radians)
Set rotation around center.
void set_scale(float width, float height)
Set display size.
void set_pixel_data(const void *data, size_t size)
Replace pixel data.
void set_vertex_layout(const Kakshya::VertexLayout &layout)
Set vertex layout for this buffer.
Definition VKBuffer.cpp:401
std::shared_ptr< Buffers::BufferProcessingChain > get_processing_chain() override
Access the buffer's processing chain.
Definition VKBuffer.cpp:314
void set_default_processor(const std::shared_ptr< BufferProcessor > &processor) override
Set the buffer's default processor.
Definition VKBuffer.cpp:298
void set_processing_chain(const std::shared_ptr< BufferProcessingChain > &chain, bool force=false) override
Replace the buffer's processing chain.
Definition VKBuffer.cpp:319
void set_default_render_config(const RenderConfig &config)
Called by derived classes to set their context-specific defaults.
Definition VKBuffer.hpp:597
Vulkan-backed buffer wrapper used in processing chains.
Definition VKBuffer.hpp:67
static size_t get_bytes_per_pixel(ImageFormat format)
Get bytes per pixel for a format.
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
QuadGeometry generate_quad(glm::vec2 position, glm::vec2 scale, float rotation)
Generate a textured quad centred on the origin.
ImageFormat
User-friendly image format enum.
Describes how a VKBuffer binds to a shader descriptor.
Vertex layout for textured quad geometry (position + UV).
std::shared_ptr< Core::Window > target_window
std::vector< std::pair< std::string, std::shared_ptr< Core::VKImage > > > additional_textures
For child-specific fields.
Unified rendering configuration for graphics buffers.