18 const auto* vb =
std::get_if<
std::vector<uint8_t>>(
19 &data.vertex_variant);
20 return vb ? vb->size() : 0;
23 Kakshya::DataModality::VERTEX_POSITIONS_3D)
24 , m_mesh_data(std::move(data))
26 if (!m_mesh_data.is_valid()) {
27 MF_WARN(Journal::Component::Buffers, Journal::Context::Init,
28 "MeshBuffer constructed with invalid MeshData — "
29 "GPU upload will be skipped until valid data is provided");
32 RenderConfig defaults;
33 defaults.vertex_shader =
"triangle.vert.spv";
34 defaults.topology = Portal::Graphics::PrimitiveTopology::TRIANGLE_LIST;
35 set_default_render_config(defaults);
37 set_needs_depth_attachment(
true);
39 MF_INFO(Journal::Component::Buffers, Journal::Context::Init,
40 "MeshBuffer: {} vertices, {} indices ({} faces), stride {} bytes",
41 m_mesh_data.vertex_count(),
43 m_mesh_data.face_count(),
44 m_mesh_data.layout.stride_bytes);
53 m_mesh_processor = std::make_shared<MeshProcessor>();
54 m_mesh_processor->set_processing_token(token);
55 set_default_processor(m_mesh_processor);
57 auto chain = get_processing_chain();
59 chain = std::make_shared<BufferProcessingChain>();
60 set_processing_chain(chain);
62 chain->set_preferred_token(token);
64 MF_DEBUG(Journal::Component::Buffers, Journal::Context::Init,
65 "MeshBuffer::setup_processors with token {}",
66 static_cast<int>(token));
85 if (!m_render_config.default_texture_binding.empty()
86 && m_diffuse_binding != m_render_config.default_texture_binding) {
87 m_diffuse_binding = m_render_config.default_texture_binding;
91 m_render_config.topology = Portal::Graphics::PrimitiveTopology::TRIANGLE_LIST;
95 m_render_config.additional_textures.emplace_back(name, texture);
99 const bool textured = m_diffuse_texture !=
nullptr
100 || !m_render_config.default_texture_binding.empty();
102 if (textured && m_render_config.default_texture_binding.empty()) {
103 m_render_config.default_texture_binding = m_diffuse_binding;
106 if (m_render_config.fragment_shader.empty()) {
107 m_render_config.fragment_shader = textured
108 ?
"mesh_textured.frag.spv"
109 :
"triangle.frag.spv";
112 if (!m_render_processor) {
115 if (textured && !m_render_config.default_texture_binding.empty()) {
117 0, 1, vk::DescriptorType::eCombinedImageSampler);
120 uint32_t binding_index = 1;
121 for (
const auto& [name, _] : m_render_config.additional_textures) {
123 1, binding_index++, vk::DescriptorType::eCombinedImageSampler);
126 m_render_processor = std::make_shared<RenderProcessor>(sc);
129 m_render_processor->set_fragment_shader(m_render_config.fragment_shader);
130 m_render_processor->set_target_window(
131 m_render_config.target_window,
132 std::dynamic_pointer_cast<VKBuffer>(shared_from_this()));
133 m_render_processor->set_primitive_topology(m_render_config.topology);
135 if (m_diffuse_texture && !m_render_config.default_texture_binding.empty()) {
136 m_render_processor->bind_texture(
137 m_render_config.default_texture_binding,
141 for (
const auto& [name, texture] : m_render_config.additional_textures) {
142 m_render_processor->bind_texture(name, texture);
145 get_processing_chain()->add_final_processor(
149 MF_INFO(Journal::Component::Buffers, Journal::Context::Init,
150 "MeshBuffer::setup_rendering: vert={} frag={} textured={}",
151 m_render_config.vertex_shader,
152 m_render_config.fragment_shader,
160void MeshBuffer::bind_diffuse_texture(
161 std::shared_ptr<Core::VKImage>
image,
162 std::string_view binding_name)
164 m_diffuse_texture = std::move(
image);
165 m_diffuse_binding = std::string(binding_name);
167 if (m_render_processor) {
168 if (m_render_config.default_texture_binding == m_diffuse_binding) {
169 m_render_processor->bind_texture(m_diffuse_binding, m_diffuse_texture);
171 MF_WARN(Journal::Component::Buffers, Journal::Context::BufferProcessing,
172 "MeshBuffer::bind_diffuse_texture: pipeline was created without "
173 "binding '{}' — call before setup_rendering() for correct results",
183void MeshBuffer::set_vertex_data(std::span<const uint8_t> bytes)
185 if (m_mesh_data.layout.stride_bytes > 0
186 && bytes.size() % m_mesh_data.layout.stride_bytes != 0) {
187 MF_ERROR(Journal::Component::Buffers, Journal::Context::BufferProcessing,
188 "MeshBuffer::set_vertex_data: byte count {} not a multiple of stride {}",
189 bytes.size(), m_mesh_data.layout.stride_bytes);
193 m_mesh_data.vertex_variant = std::vector<uint8_t>(bytes.begin(), bytes.end());
194 m_mesh_data.layout.vertex_count = m_mesh_data.layout.stride_bytes > 0
195 ?
static_cast<uint32_t
>(bytes.size() / m_mesh_data.layout.stride_bytes)
198 m_vertices_dirty.store(
true, std::memory_order_release);
201void MeshBuffer::set_index_data(std::span<const uint32_t> indices)
203 if (indices.size() % 3 != 0) {
204 MF_ERROR(Journal::Component::Buffers, Journal::Context::BufferProcessing,
205 "MeshBuffer::set_index_data: index count {} is not a multiple of 3",
210 m_mesh_data.index_variant = std::vector<uint32_t>(indices.begin(), indices.end());
211 m_indices_dirty.store(
true, std::memory_order_release);