MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GeometryBuffer.cpp
Go to the documentation of this file.
1#include "GeometryBuffer.hpp"
2
5
7
8namespace MayaFlux::Buffers {
9
11 std::shared_ptr<Nodes::GpuSync::GeometryWriterNode> node,
12 const std::string& binding_name,
13 float over_allocate_factor)
14 : VKBuffer(
15 calculate_buffer_size(node, over_allocate_factor),
16 Usage::VERTEX,
17 Kakshya::DataModality::VERTEX_POSITIONS_3D)
18 , m_geometry_node(std::move(node))
19 , m_binding_name(binding_name)
20{
21 if (!m_geometry_node) {
22 error<std::invalid_argument>(
25 std::source_location::current(),
26 "Cannot create GeometryBuffer with null GeometryWriterNode");
27 }
28
30 "Created GeometryBuffer '{}' for {} vertices ({} bytes, stride: {})",
32 m_geometry_node->get_vertex_count(),
34 m_geometry_node->get_vertex_stride());
35}
36
38{
39 auto self = std::dynamic_pointer_cast<GeometryBuffer>(shared_from_this());
40
41 m_bindings_processor = std::make_shared<GeometryBindingsProcessor>();
42 m_bindings_processor->set_processing_token(token);
43 m_bindings_processor->bind_geometry_node(
46 self);
47
49
51 if (!chain) {
52 chain = std::make_shared<BufferProcessingChain>();
54 }
55 chain->set_preferred_token(token);
56
57 for (auto& [img, binding] : m_pending_textures)
58 m_bindings_processor->set_texture(std::move(img), std::move(binding));
59 m_pending_textures.clear();
60}
61
63{
64 RenderConfig resolved_config = config;
65
66 const bool textured = m_diffuse_texture != nullptr
67 || !resolved_config.default_texture_binding.empty();
68
70 && m_geometry_node->get_primitive_topology()
72 resolved_config.topology = m_geometry_node->get_primitive_topology();
73 }
74
75 switch (resolved_config.topology) {
77 if (resolved_config.triangulate) {
78 if (config.vertex_shader.empty())
79 resolved_config.vertex_shader = "milled_shape.vert.spv";
80 if (config.fragment_shader.empty()) {
81 resolved_config.fragment_shader = textured
82 ? "milled_shape_textured.frag.spv"
83 : "milled_shape.frag.spv";
84 }
85 } else {
86 if (config.vertex_shader.empty())
87 resolved_config.vertex_shader = "point.vert.spv";
88 if (config.fragment_shader.empty())
89 resolved_config.fragment_shader = "point.frag.spv";
90 }
91 break;
92
95
96 if (config.vertex_shader.empty())
97 resolved_config.vertex_shader = "line.vert.spv";
98
99 if (config.fragment_shader.empty())
100 resolved_config.fragment_shader = "line.frag.spv";
101
102#ifdef MAYAFLUX_PLATFORM_MACOS
103 resolved_config.triangulate = true;
104#endif
105
106 if (resolved_config.triangulate) {
107 resolved_config.geometry_shader.clear();
108 } else if (config.geometry_shader.empty()) {
109 resolved_config.geometry_shader = "line.geom.spv";
110 }
111
112 break;
113
116 if (config.vertex_shader.empty())
117 resolved_config.vertex_shader = "triangle.vert.spv";
118 if (config.fragment_shader.empty()) {
119 resolved_config.fragment_shader = textured
120 ? "mesh_textured.frag.spv"
121 : "triangle.frag.spv";
122 }
123 break;
124
125 default:
126 if (config.vertex_shader.empty())
127 resolved_config.vertex_shader = "point.vert.spv";
128 if (config.fragment_shader.empty())
129 resolved_config.fragment_shader = "point.frag.spv";
130 }
131
132 const bool frag_samples_texture = !resolved_config.default_texture_binding.empty()
133 || resolved_config.fragment_shader.find("textured") != std::string::npos;
134
135 if (textured && !frag_samples_texture) {
137 "GeometryBuffer::setup_rendering: texture supplied but fragment shader '{}' "
138 "does not sample a texture — texture will be ignored",
139 resolved_config.fragment_shader);
140 }
141
142 const bool apply_texture = textured && frag_samples_texture;
143
144 ShaderConfig sc { resolved_config.vertex_shader };
145 if (apply_texture) {
146 const std::string slot = resolved_config.default_texture_binding.empty()
148 : resolved_config.default_texture_binding;
149 sc.bindings[slot] = ShaderBinding(0, 1, vk::DescriptorType::eCombinedImageSampler);
150 }
151
152 apply_render_config(resolved_config, sc);
153
154 get_processing_chain()->add_final_processor(m_render_processor, shared_from_this());
155
156 if (apply_texture && m_diffuse_texture)
158
159 set_default_render_config(resolved_config);
160}
161
162void GeometryBuffer::set_texture(std::shared_ptr<Core::VKImage> image, std::string binding)
163{
165 m_diffuse_binding = binding;
166
168 m_pending_textures.emplace_back(std::move(image), std::move(binding));
169 return;
170 }
171 m_bindings_processor->set_texture(std::move(image), std::move(binding));
172}
173
175 const std::shared_ptr<Nodes::GpuSync::GeometryWriterNode>& node,
176 float over_allocate_factor)
177{
178 if (!node) {
179 return 0;
180 }
181
182 size_t base_size = node->get_vertex_buffer_size_bytes();
183
184 if (base_size == 0) {
186 "GeometryWriterNode has zero-size vertex buffer. "
187 "Did you forget to call set_vertex_stride() or resize_vertex_buffer()?");
188 return 4096;
189 }
190
191 auto allocated_size = static_cast<size_t>(
192 static_cast<float>(base_size) * over_allocate_factor);
193
194 if (over_allocate_factor > 1.0F) {
196 "Over-allocated geometry buffer: {} → {} bytes ({}x)",
197 base_size, allocated_size, over_allocate_factor);
198 }
199
200 return allocated_size;
201}
202
203} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
IO::ImageData image
Definition Decoder.cpp:47
BufferProcessingChain * chain
std::vector< std::pair< std::shared_ptr< Core::VKImage >, std::string > > m_pending_textures
std::shared_ptr< Core::VKImage > m_diffuse_texture
std::shared_ptr< Nodes::GpuSync::GeometryWriterNode > m_geometry_node
void setup_processors(ProcessingToken token) override
Initialize the buffer and its processors.
void setup_rendering(const RenderConfig &config)
Setup rendering with RenderProcessor.
static size_t calculate_buffer_size(const std::shared_ptr< Nodes::GpuSync::GeometryWriterNode > &node, float over_allocate_factor)
Calculate initial buffer size with optional over-allocation.
void set_texture(std::shared_ptr< Core::VKImage > image, std::string binding="diffuseTex")
Supply a diffuse texture, bound on the next graphics tick.
GeometryBuffer(std::shared_ptr< Nodes::GpuSync::GeometryWriterNode > node, const std::string &binding_name="geometry", float over_allocate_factor=1.5F)
Create geometry buffer from generative node.
std::shared_ptr< GeometryBindingsProcessor > m_bindings_processor
std::shared_ptr< Buffers::BufferProcessingChain > get_processing_chain() override
Access the buffer's processing chain.
Definition VKBuffer.cpp:271
void set_default_processor(const std::shared_ptr< BufferProcessor > &processor) override
Set the buffer's default processor.
Definition VKBuffer.cpp:255
vk::DeviceSize get_size_bytes() const
Definition VKBuffer.hpp:280
void set_processing_chain(const std::shared_ptr< BufferProcessingChain > &chain, bool force=false) override
Replace the buffer's processing chain.
Definition VKBuffer.cpp:276
void apply_render_config(const RenderConfig &config, const ShaderConfig &shader_config)
Configure the internal m_render_processor from a RenderConfig.
Definition VKBuffer.cpp:344
std::shared_ptr< RenderProcessor > m_render_processor
Definition VKBuffer.hpp:654
void set_default_render_config(const RenderConfig &config)
Called by derived classes to set their context-specific defaults.
Definition VKBuffer.hpp:631
Vulkan-backed buffer wrapper used in processing chains.
Definition VKBuffer.hpp:76
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
@ BufferManagement
Buffer Management (Buffers::BufferManager, creating buffers)
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
BufferUsageHint
Semantic usage hint for buffer allocation and memory properties.
Describes how a VKBuffer binds to a shader descriptor.
bool triangulate
Reduce supplied spans to triangles before drawing them.
Unified rendering configuration for graphics buffers.