MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MeshNetworkBuffer.cpp
Go to the documentation of this file.
2
6
8
10
11namespace MayaFlux::Buffers {
12
13// =============================================================================
14// Construction
15// =============================================================================
16
18 std::shared_ptr<Nodes::Network::MeshNetwork> network,
19 float over_allocate_factor)
20 : VKBuffer(
21 estimate_vertex_bytes(network, over_allocate_factor),
22 Usage::VERTEX,
23 Kakshya::DataModality::VERTEX_POSITIONS_3D)
24 , m_network(std::move(network))
25{
26 if (!m_network) {
27 error<std::invalid_argument>(
29 std::source_location::current(),
30 "MeshNetworkBuffer: null MeshNetwork");
31 }
32
33 RenderConfig defaults;
37
38 m_render_config = defaults;
39
41 "MeshNetworkBuffer: {} slots, {} bytes estimated",
42 m_network->slot_count(), get_size_bytes());
43}
44
45// =============================================================================
46// setup_processors
47// =============================================================================
48
50{
51 m_processor = std::make_shared<MeshNetworkProcessor>(m_network);
52 m_processor->set_processing_token(token);
54
55 auto chain = get_processing_chain();
56 if (!chain) {
57 chain = std::make_shared<BufferProcessingChain>();
59 }
60 chain->set_preferred_token(token);
61
63 "MeshNetworkBuffer::setup_processors with token {}",
64 static_cast<int>(token));
65}
66
67// =============================================================================
68// setup_rendering
69// =============================================================================
70
72{
73 if (!config.vertex_shader.empty())
75 if (!config.fragment_shader.empty())
77 if (!config.default_texture_binding.empty()) {
80 }
81
86
87 for (const auto& [name, tex] : config.additional_textures)
88 m_render_config.additional_textures.emplace_back(name, tex);
89
90 const auto slot_count = static_cast<uint32_t>(m_network->slot_count());
91
92 const bool has_slot_textures = std::ranges::any_of(
93 m_network->slots(),
94 [](const auto& slot) { return slot.diffuse_texture != nullptr; });
95
96 const bool textured = m_diffuse_texture != nullptr
98 || has_slot_textures;
99
100 if (textured && m_render_config.default_texture_binding.empty())
102
103 if (m_render_config.vertex_shader.empty())
104 m_render_config.vertex_shader = "mesh_network.vert.spv";
105
106 if (m_render_config.fragment_shader.empty()) {
108 ? "mesh_network_textured.frag.spv"
109 : "mesh_network.frag.spv";
110 }
111
113
114 sc.bindings["modelMatrices"] = ShaderBinding(0, 1, vk::DescriptorType::eStorageBuffer);
115 sc.bindings["slotIndices"] = ShaderBinding(0, 2, vk::DescriptorType::eStorageBuffer);
116
117 if (has_slot_textures) {
118 sc.bindings["diffuseTex"] = ShaderBinding(
119 0, 3, vk::DescriptorType::eCombinedImageSampler, slot_count);
120 } else if (textured && !m_render_config.default_texture_binding.empty()) {
122 0, 3, vk::DescriptorType::eCombinedImageSampler);
123 }
124
125 uint32_t binding_idx = 0;
126 for (const auto& [name, _] : m_render_config.additional_textures)
127 sc.bindings[name] = ShaderBinding(1, binding_idx++, vk::DescriptorType::eCombinedImageSampler);
128
129 m_render_processor = std::make_shared<RenderProcessor>(sc);
131 m_render_processor->set_target_window(
133 std::dynamic_pointer_cast<VKBuffer>(shared_from_this()));
134 m_render_processor->set_primitive_topology(m_render_config.topology);
137
138 if (has_slot_textures) {
139 const auto& slots = m_network->slots();
140 const auto& order = m_network->sorted_indices();
141 for (uint32_t i = 0; i < static_cast<uint32_t>(order.size()); ++i) {
142 const auto& slot = slots[order[i]];
143 if (slot.diffuse_texture)
144 m_render_processor->bind_texture(3 + i, slot.diffuse_texture);
145 }
148 }
149
150 for (const auto& [name, tex] : m_render_config.additional_textures)
151 m_render_processor->bind_texture(name, tex);
152
153 get_processing_chain()->add_final_processor(
155 shared_from_this());
156
158 "MeshNetworkBuffer::setup_rendering: vert={} frag={} textured={}",
161 textured);
162}
163
164// =============================================================================
165// bind_diffuse_texture
166// =============================================================================
167
169 std::shared_ptr<Core::VKImage> image,
170 std::string_view binding_name)
171{
172 m_diffuse_texture = std::move(image);
173 m_diffuse_binding = std::string(binding_name);
174
175 if (m_render_processor) {
178 } else {
180 "MeshNetworkBuffer::bind_diffuse_texture: pipeline compiled without "
181 "binding '{}' — call before setup_rendering() for correct results",
183 }
184 }
185}
186
187// =============================================================================
188// Private helpers
189// =============================================================================
190
192 const std::shared_ptr<Nodes::Network::MeshNetwork>& network,
193 float over_allocate_factor)
194{
195 constexpr size_t k_min = 4096;
196 if (!network || network->slot_count() == 0)
197 return k_min;
198
199 size_t total = 0;
200 for (const auto& slot : network->slots()) {
201 if (slot.node)
202 total += slot.node->get_mesh_vertex_count() * sizeof(Nodes::MeshVertex);
203 }
204
205 if (total == 0)
206 return k_min;
207
208 return static_cast<size_t>(static_cast<float>(total) * over_allocate_factor);
209}
210
211} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
IO::ImageData image
std::shared_ptr< Core::VKImage > m_diffuse_texture
void setup_rendering(const RenderConfig &config)
Attach a RenderProcessor with optional texture support.
void setup_processors(ProcessingToken token) override
Create and attach MeshNetworkProcessor as the default processor.
MeshNetworkBuffer(std::shared_ptr< Nodes::Network::MeshNetwork > network, float over_allocate_factor=1.5F)
Construct from an existing MeshNetwork.
std::shared_ptr< RenderProcessor > m_render_processor
std::shared_ptr< MeshNetworkProcessor > m_processor
std::shared_ptr< Nodes::Network::MeshNetwork > m_network
static size_t estimate_vertex_bytes(const std::shared_ptr< Nodes::Network::MeshNetwork > &network, float over_allocate_factor)
void bind_diffuse_texture(std::shared_ptr< Core::VKImage > image, std::string_view binding_name="diffuseTex")
Bind a single shared diffuse texture for all slots.
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
vk::DeviceSize get_size_bytes() const
Definition VKBuffer.hpp:278
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_needs_depth_attachment(bool needs)
Mark this buffer as requiring depth testing when rendered.
Definition VKBuffer.hpp:569
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
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.
Describes how a VKBuffer binds to a shader descriptor.
Vertex type for indexed triangle mesh primitives (TRIANGLE_LIST topology)
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.