MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
InstanceSSBOProcessor.cpp
Go to the documentation of this file.
2
4
7
9
10namespace MayaFlux::Buffers {
11
13 std::shared_ptr<Nodes::Network::InstanceNetwork> network)
14 : m_network(std::move(network))
15{
16}
17
18// =============================================================================
19// VKBufferProcessor interface
20// =============================================================================
21
22void InstanceSSBOProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
23{
24 if (!m_network || m_network->slot_count() == 0) {
26 "InstanceSSBOProcessor attached to empty network");
27 return;
28 }
29
30 auto vk_buf = std::dynamic_pointer_cast<VKBuffer>(buffer);
31 if (!vk_buf) {
33 "InstanceSSBOProcessor: attached buffer is not a VKBuffer");
34 return;
35 }
36
37 ensure_initialized(vk_buf);
38
39 const size_t slot_count = m_network->slot_count();
40
41 m_vertex_staging = create_staging_buffer(vk_buf->get_size_bytes());
42
43 const size_t ssbo_bytes = slot_count * sizeof(glm::mat4);
44 m_transform_ssbo = std::make_shared<VKBuffer>(
47
49
50 upload_template(vk_buf);
51 upload_transforms(vk_buf);
52 push_ssbo_binding(vk_buf);
53
55 "InstanceSSBOProcessor: {} slots, {} bytes template, {} bytes SSBO",
56 slot_count, vk_buf->get_size_bytes(), ssbo_bytes);
57}
58
59void InstanceSSBOProcessor::on_detach(const std::shared_ptr<Buffer>&)
60{
61 m_vertex_staging.reset();
62 m_transform_ssbo.reset();
63 m_transform_staging.reset();
64}
65
66void InstanceSSBOProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
67{
68 auto vk_buf = std::dynamic_pointer_cast<VKBuffer>(buffer);
69 if (!vk_buf || m_network->slot_count() == 0)
70 return;
71
72 const auto& slots = m_network->slots();
73
74 if (slots[0].node && slots[0].node->needs_gpu_update())
75 upload_template(vk_buf);
76
77 if (any_slot_dirty()) {
78 upload_transforms(vk_buf);
80 }
81
82 push_ssbo_binding(vk_buf);
83}
84
85// =============================================================================
86// Private
87// =============================================================================
88
89void InstanceSSBOProcessor::upload_template(const std::shared_ptr<VKBuffer>& vertex_buf)
90{
91 const auto& slots = m_network->slots();
92 if (slots.empty() || !slots[0].node)
93 return;
94
95 const auto span = slots[0].node->get_vertex_data();
96 if (span.empty())
97 return;
98
99 upload_resizing(span.data(), span.size_bytes(), vertex_buf, m_vertex_staging);
100
101 if (!vertex_buf->has_vertex_layout()) {
102 if (auto layout = slots[0].node->get_vertex_layout()) {
103 layout->vertex_count = static_cast<uint32_t>(span.size_bytes() / layout->stride_bytes);
104 vertex_buf->set_vertex_layout(*layout);
105 }
106 }
107}
108
109void InstanceSSBOProcessor::upload_transforms(const std::shared_ptr<VKBuffer>& vertex_buf)
110{
111 const auto& slots = m_network->slots();
112 m_transform_scratch.resize(slots.size());
113
114 for (const auto& slot : slots)
115 m_transform_scratch[slot.index] = slot.transform;
116
118 m_transform_scratch.data(),
119 m_transform_scratch.size() * sizeof(glm::mat4),
122
123 if (auto rp = vertex_buf->get_render_processor())
124 rp->set_instance_count(static_cast<uint32_t>(slots.size()));
125}
126
127void InstanceSSBOProcessor::push_ssbo_binding(const std::shared_ptr<VKBuffer>& vertex_buf)
128{
129 if (!m_transform_ssbo)
130 return;
131
132 auto& bindings = vertex_buf->get_engine_context().ssbo_bindings;
133
135 info.set = 0;
137 info.type = vk::DescriptorType::eStorageBuffer;
138 info.buffer_info.buffer = m_transform_ssbo->get_buffer();
139 info.buffer_info.offset = 0;
140 info.buffer_info.range = m_transform_ssbo->get_size_bytes();
141
142 auto it = std::ranges::find_if(bindings, [](const auto& b) {
143 return b.set == 0 && b.binding == k_transform_ssbo_binding;
144 });
145 if (it != bindings.end()) {
146 *it = info;
147 } else {
148 bindings.push_back(info);
149 }
150}
151
153{
154 return std::ranges::any_of(m_network->slots(), [](const auto& s) { return s.dirty; });
155}
156
158{
159 for (auto& slot : m_network->slots())
160 slot.dirty = false;
161}
162
163} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
Core::GlobalNetworkConfig network
Definition Config.cpp:37
size_t b
void push_ssbo_binding(const std::shared_ptr< VKBuffer > &vertex_buf)
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
std::shared_ptr< Nodes::Network::InstanceNetwork > m_network
void upload_transforms(const std::shared_ptr< VKBuffer > &vertex_buf)
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void upload_template(const std::shared_ptr< VKBuffer > &vertex_buf)
InstanceSSBOProcessor(std::shared_ptr< Nodes::Network::InstanceNetwork > network)
void ensure_initialized(const std::shared_ptr< VKBuffer > &buffer)
Definition VKBuffer.cpp:471
@ COMPUTE
Storage buffer for compute shaders (device-local)
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.
std::shared_ptr< VKBuffer > create_staging_buffer(size_t size)
Create staging buffer for transfers.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
@ UNKNOWN
Unknown or undefined modality.