MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FormaBuffer.cpp
Go to the documentation of this file.
1#include "FormaBuffer.hpp"
2
7
9
11
12namespace MayaFlux::Buffers {
13
14namespace {
15 constexpr size_t k_capacity_bytes = 4 * 1024 * 1024; // 4 MiB default capacity, can be overridden by constructor
16}
17
19 size_t capacity_bytes,
21 : VKBuffer(capacity_bytes, Buffers::VKBuffer::Usage::VERTEX,
22 Kakshya::DataModality::VERTEX_POSITIONS_3D)
23 , m_topology(topology)
24{
25}
26
29 : FormaBuffer(k_capacity_bytes, topology)
30{
31}
32
34{
35 auto proc = std::make_shared<Buffers::FormaProcessor>(m_topology);
37 m_processor = proc;
38
39 auto chain = std::make_shared<Buffers::BufferProcessingChain>();
40 chain->set_preferred_token(token);
42
43 if (!m_pending_geometry.empty()) {
44 m_processor->set_bytes(std::move(m_pending_geometry));
45 m_pending_geometry.clear();
46 }
47
48 for (auto& [img, binding] : m_pending_textures)
49 m_processor->set_texture(std::move(img), std::move(binding));
50
51 m_pending_textures.clear();
52}
53
55{
56 RenderConfig resolved = config;
57 resolved.topology = m_topology;
58
59 const bool single_tex = !config.default_texture_binding.empty();
60 const auto multi_count = static_cast<uint32_t>(config.additional_textures.size());
61 const bool multi_tex = multi_count > 0;
62
63 switch (resolved.topology) {
65 if (resolved.vertex_shader.empty())
66 resolved.vertex_shader = "point.vert.spv";
67 if (resolved.fragment_shader.empty())
68 resolved.fragment_shader = "point.frag.spv";
69 break;
70
73 if (resolved.fragment_shader.empty())
74 resolved.fragment_shader = "line.frag.spv";
75#ifndef MAYAFLUX_PLATFORM_MACOS
76 if (resolved.vertex_shader.empty())
77 resolved.vertex_shader = "line.vert.spv";
78 if (resolved.geometry_shader.empty())
79 resolved.geometry_shader = "line.geom.spv";
80#else
81 if (resolved.vertex_shader.empty())
82 resolved.vertex_shader = "line_fallback.vert.spv";
84#endif
85
86 break;
87
90 if (resolved.vertex_shader.empty())
91 resolved.vertex_shader = multi_tex ? "triangle_multi.vert.spv" : "triangle.vert.spv";
92 if (resolved.fragment_shader.empty()) {
93 if (multi_tex) {
94 resolved.fragment_shader = "forma_multi.frag.spv";
95 } else if (single_tex) {
96 resolved.fragment_shader = "forma_textured.frag.spv";
97 } else {
98 resolved.fragment_shader = "triangle.frag.spv";
99 }
100 }
101 break;
102
103 default:
104 if (resolved.vertex_shader.empty())
105 resolved.vertex_shader = "point.vert.spv";
106 if (resolved.fragment_shader.empty())
107 resolved.fragment_shader = "point.frag.spv";
108 break;
109 }
110
111 ShaderConfig sc { resolved.vertex_shader };
112 if (multi_tex) {
113 const uint32_t total = single_tex ? 1 + multi_count : multi_count;
114 sc.bindings["textures"] = ShaderBinding(
115 0, 1, vk::DescriptorType::eCombinedImageSampler, total);
116 } else if (single_tex) {
117 sc.bindings[config.default_texture_binding] = ShaderBinding(
118 0, 1, vk::DescriptorType::eCombinedImageSampler);
119 }
120
121 apply_render_config(resolved, sc);
122 m_render_processor->enable_alpha_blending();
123
124 if (multi_tex) {
125 uint32_t slot = 1;
126 if (single_tex && !config.default_texture_binding.empty()) {
127 auto it = std::ranges::find_if(config.additional_textures,
128 [&](const auto& p) { return p.first == config.default_texture_binding; });
129 if (it != config.additional_textures.end()) {
130 m_render_processor->bind_texture(slot, it->second);
131 ++slot;
132 }
133 }
134 for (const auto& [name, img] : config.additional_textures) {
135 if (single_tex && name == config.default_texture_binding)
136 continue;
137
138 if (img)
139 m_render_processor->bind_texture(slot, img);
140
141 ++slot;
142 }
143 }
144
145 get_processing_chain()->add_final_processor(m_render_processor, shared_from_this());
147}
148
149void FormaBuffer::submit(const std::vector<uint8_t>& bytes)
150{
151 if (!m_processor) {
152 m_pending_geometry = bytes;
154 "FormaBuffer::submit called before setup_processors, storing {} bytes for later submission", bytes.size());
155 return;
156 }
157 m_processor->set_bytes(bytes);
158}
159
160void FormaBuffer::set_texture(std::shared_ptr<Core::VKImage> image, std::string binding)
161{
162 if (!m_processor) {
163 m_pending_textures.emplace_back(std::move(image), std::move(binding));
165 "FormaBuffer::set_texture called before setup_processors, storing texture for later submission");
166 return;
167 }
168 m_processor->set_texture(std::move(image), std::move(binding));
169}
170
171void FormaBuffer::bind_texture(uint32_t array_index, const std::shared_ptr<Core::VKImage>& image)
172{
174 m_render_processor->bind_texture(1 + array_index, image);
175}
176
177} // namespace MayaFlux::Buffers
#define MF_RT_TRACE(comp, ctx,...)
IO::ImageData image
Definition Decoder.cpp:57
void submit(const std::vector< uint8_t > &bytes)
Write vertex bytes into the buffer.
std::vector< uint8_t > m_pending_geometry
Geometry bytes from submit() before setup_processors(). Drained in setup_processors().
std::shared_ptr< Buffers::FormaProcessor > m_processor
void setup_rendering(const RenderConfig &config)
Attach a RenderProcessor targeting the given window.
void bind_texture(uint32_t array_index, const std::shared_ptr< Core::VKImage > &image)
Bind a texture to a slot in the multi-texture array at runtime.
void set_texture(std::shared_ptr< Core::VKImage > image, std::string binding)
Supply a texture to be bound on the next graphics tick.
void setup_processors(ProcessingToken token) override
Register with the graphics subsystem.
Portal::Graphics::PrimitiveTopology m_topology
FormaBuffer(size_t capacity_bytes, Portal::Graphics::PrimitiveTopology topology)
Construct a FormaBuffer.
std::vector< std::pair< std::shared_ptr< Core::VKImage >, std::string > > m_pending_textures
Textures from set_texture() before setup_processors(). Drained in setup_processors().
VKBuffer for 2D screen-space Forma geometry.
std::shared_ptr< Buffers::BufferProcessingChain > get_processing_chain() override
Access the buffer's processing chain.
Definition VKBuffer.cpp:286
void set_default_processor(const std::shared_ptr< BufferProcessor > &processor) override
Set the buffer's default processor.
Definition VKBuffer.cpp:270
void set_processing_chain(const std::shared_ptr< BufferProcessingChain > &chain, bool force=false) override
Replace the buffer's processing chain.
Definition VKBuffer.cpp:291
void apply_render_config(const RenderConfig &config, const ShaderConfig &shader_config)
Configure the internal m_render_processor from a RenderConfig.
Definition VKBuffer.cpp:359
std::shared_ptr< RenderProcessor > m_render_processor
Definition VKBuffer.hpp:618
void set_default_render_config(const RenderConfig &config)
Called by derived classes to set their context-specific defaults.
Definition VKBuffer.hpp:595
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)
@ Buffers
Buffers, Managers, processors and processing chains.
constexpr size_t k_capacity_bytes
Definition Forma.hpp:50
PrimitiveTopology
Vertex assembly primitive topology.
Describes how a VKBuffer binds to a shader descriptor.
std::vector< std::pair< std::string, std::shared_ptr< Core::VKImage > > > additional_textures
For child-specific fields.
Unified rendering configuration for graphics buffers.