MayaFlux 0.3.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, 0, 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 0, 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
144// =========================================================================
145// Display Transform
146// =========================================================================
147
148void TextureBuffer::set_position(float x, float y)
149{
150 if (m_position.x != x || m_position.y != y) {
151 m_position = { x, y };
152 m_geometry_dirty = true;
153
155 "TextureBuffer: position set to ({}, {}), geometry marked dirty", x, y);
156 }
157}
158
159void TextureBuffer::set_scale(float width, float height)
160{
161 if (m_scale.x != width || m_scale.y != height) {
162 m_scale = { width, height };
163 m_geometry_dirty = true;
164
166 "TextureBuffer: scale set to ({}, {}), geometry marked dirty", width, height);
167 }
168}
169
170void TextureBuffer::set_rotation(float angle_radians)
171{
172 if (m_rotation != angle_radians) {
173 m_rotation = angle_radians;
174 m_geometry_dirty = true;
175
177 "TextureBuffer: rotation set to {}, geometry marked dirty", angle_radians);
178 }
179}
180
181// =========================================================================
182// Custom Geometry
183// =========================================================================
184
185void TextureBuffer::set_custom_vertices(const std::vector<Nodes::TextureQuadVertex>& vertices)
186{
187 if (vertices.size() != 4) {
189 "set_custom_vertices: must provide exactly 4 vertices, got {}", vertices.size());
190 return;
191 }
192
193 m_vertex_bytes.resize(vertices.size() * sizeof(Nodes::TextureQuadVertex));
194 std::memcpy(m_vertex_bytes.data(), vertices.data(), m_vertex_bytes.size());
196 m_geometry_dirty = true;
197
199 "TextureBuffer: custom vertices set, geometry marked dirty");
200}
201
203{
207 m_geometry_dirty = true;
208
210 "TextureBuffer: reset to default quad, geometry marked dirty");
211 }
212}
213
214// =========================================================================
215// Geometry Generation
216// =========================================================================
217
222
224{
226 m_vertex_bytes.resize(geo.vertices.size() * sizeof(Nodes::TextureQuadVertex));
227 std::memcpy(m_vertex_bytes.data(), geo.vertices.data(), m_vertex_bytes.size());
228 set_vertex_layout(geo.layout);
229
231 "TextureBuffer: generated default quad");
232}
233
235{
238 "TextureBuffer: using custom vertices, skipping transform");
239 return;
240 }
241
243 m_vertex_bytes.resize(geo.vertices.size() * sizeof(Nodes::TextureQuadVertex));
244 std::memcpy(m_vertex_bytes.data(), geo.vertices.data(), m_vertex_bytes.size());
245
247 "TextureBuffer: regenerated quad with transform (pos={},{}, scale={},{}, rot={})",
249}
250
251} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
void setup_processors(ProcessingToken token) override
Setup processors with a processing token.
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::vector< uint8_t > m_pixel_data
std::shared_ptr< RenderProcessor > m_render_processor
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)
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:361
std::shared_ptr< Buffers::BufferProcessingChain > get_processing_chain() override
Access the buffer's processing chain.
Definition VKBuffer.cpp:274
void set_default_processor(const std::shared_ptr< BufferProcessor > &processor) override
Set the buffer's default processor.
Definition VKBuffer.cpp:258
void set_processing_chain(const std::shared_ptr< BufferProcessingChain > &chain, bool force=false) override
Replace the buffer's processing chain.
Definition VKBuffer.cpp:279
void set_default_render_config(const RenderConfig &config)
Called by derived classes to set their context-specific defaults.
Definition VKBuffer.hpp:502
Vulkan-backed buffer wrapper used in processing chains.
Definition VKBuffer.hpp:52
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.