13 std::shared_ptr<Nodes::Network::MeshNetwork> network)
14 : m_network(
std::move(network))
28 "MeshNetworkProcessor attached to empty network");
32 auto vk_buf = std::dynamic_pointer_cast<VKBuffer>(buffer);
35 "MeshNetworkProcessor: attached buffer is not a VKBuffer");
49 "MeshNetworkProcessor: initialised — {} slots, {} bytes vertex, {} indices",
73 auto vk_buf = std::dynamic_pointer_cast<VKBuffer>(buffer);
88 "MeshNetworkProcessor: re-uploaded {} bytes vertex, {} indices",
97 const std::shared_ptr<VKBuffer>& vertex_buf)
102 if (v_bytes == 0 || i_bytes == 0) {
104 "MeshNetworkProcessor::allocate_gpu_buffers: network has no geometry");
108 if (!vertex_buf->is_host_visible())
117 "MeshNetworkProcessor: allocated vertex ({} bytes) + index ({} bytes)",
122 const std::shared_ptr<VKBuffer>& vertex_buf)
125 const auto& order =
m_network->sorted_indices();
132 uint32_t running_vertex_count = 0;
134 for (uint32_t idx : order) {
135 const auto& slot = slots[idx];
139 const auto& verts = slot.node->get_mesh_vertices();
140 const auto& indices = slot.node->get_mesh_indices();
143 const auto* v_src =
reinterpret_cast<const uint8_t*
>(verts.data());
146 for (uint32_t i : indices)
151 const auto sorted_slot_pos =
static_cast<uint32_t
>(
m_model_aggregate.size() - 1);
155 running_vertex_count +=
static_cast<uint32_t
>(verts.size());
162 if (v_required > vertex_buf->get_size_bytes()) {
163 const auto new_size =
static_cast<size_t>(
164 static_cast<float>(v_required) * 1.5F);
165 vertex_buf->resize(new_size,
false);
178 const auto new_size =
static_cast<size_t>(
179 static_cast<float>(i_required) * 1.5F);
193 for (uint32_t idx : order) {
194 const auto& slot = slots[idx];
195 if (slot.node && slot.node->get_mesh_vertex_count() > 0) {
196 if (
auto layout = slot.node->get_vertex_layout()) {
197 layout->vertex_count = running_vertex_count;
198 vertex_buf->set_vertex_layout(*layout);
206 const std::shared_ptr<VKBuffer>& vertex_buf)
211 vertex_buf->set_index_resources(
219 return std::ranges::any_of(
m_network->slots(), [](
const auto& slot) {
220 return slot.dirty || (slot.node && slot.node->needs_gpu_update());
229 slot.node->clear_gpu_update_flag();
236 for (
const auto& slot :
m_network->slots()) {
246 for (
const auto& slot :
m_network->slots()) {
248 total += slot.node->get_mesh_indices().size();
258 if (model_bytes == 0 || slot_index_bytes == 0) {
295 auto& bindings = buffer->get_engine_context().ssbo_bindings;
297 auto push = [&](uint32_t binding_idx,
const std::shared_ptr<VKBuffer>& ssbo) {
301 info.
type = vk::DescriptorType::eStorageBuffer;
306 auto it = std::ranges::find_if(bindings, [&](
const auto&
b) {
309 if (it != bindings.end()) {
312 bindings.push_back(info);
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_RT_TRACE(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
ProcessingToken m_processing_token
size_t total_vertex_bytes() const
std::shared_ptr< VKBuffer > m_slot_index_ssbo
Per-vertex slot index. One uint32_t per concatenated vertex.
std::vector< uint32_t > m_slot_index_aggregate
CPU-side scratch for per-vertex slot indices, reused each cycle.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
std::vector< uint8_t > m_vertex_aggregate
Aggregate scratch buffers reused each cycle to avoid allocation.
std::shared_ptr< VKBuffer > m_index_staging
void link_index_resources(const std::shared_ptr< VKBuffer > &vertex_buf)
void upload_combined(const std::shared_ptr< VKBuffer > &vertex_buf)
void clear_slot_dirty_flags()
std::vector< uint32_t > m_index_aggregate
MeshNetworkProcessor(std::shared_ptr< Nodes::Network::MeshNetwork > network)
size_t total_index_count() const
bool any_slot_dirty() const
void allocate_gpu_buffers(const std::shared_ptr< VKBuffer > &vertex_buf)
std::shared_ptr< VKBuffer > m_vertex_staging
void allocate_ssbo_buffers()
std::shared_ptr< VKBuffer > m_gpu_index_buffer
void push_ssbo_bindings(const std::shared_ptr< VKBuffer > &buffer)
std::shared_ptr< Nodes::Network::MeshNetwork > m_network
std::shared_ptr< VKBuffer > m_model_ssbo
Per-slot world matrices in sorted_indices order. One mat4 per slot.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
std::vector< glm::mat4 > m_model_aggregate
CPU-side scratch for model matrices, reused each cycle.
void initialize_buffer_service()
Registry::Service::BufferService * m_buffer_service
void ensure_initialized(const std::shared_ptr< VKBuffer > &buffer)
@ COMPUTE
Storage buffer for compute shaders.
void upload_resizing(const void *data, size_t size, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging, float growth_factor)
Upload size bytes to target, growing both buffers first if needed.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
std::shared_ptr< VKBuffer > create_staging_buffer(size_t size)
Create staging buffer for transfers.
void upload_to_gpu(const void *data, size_t size, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging)
Upload raw data to GPU buffer (auto-detects host-visible vs device-local)
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
@ UNKNOWN
Unknown or undefined modality.
Vertex type for indexed triangle mesh primitives (TRIANGLE_LIST topology)
vk::DescriptorBufferInfo buffer_info
std::function< void(const std::shared_ptr< void > &)> initialize_buffer
Initialize a buffer object.