MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RenderProcessor.cpp
Go to the documentation of this file.
1#include "RenderProcessor.hpp"
2
7
12
14
15namespace MayaFlux::Buffers {
16
18 std::unordered_map<std::shared_ptr<VKBuffer>, RenderProcessor::VertexInfo>& buffer_info,
19 const std::shared_ptr<VKBuffer>& buffer)
20{
21 auto info_it = buffer_info.find(buffer);
22 if (info_it == buffer_info.end()) {
23 if (buffer->has_vertex_layout()) {
24 auto vertex_layout = buffer->get_vertex_layout();
25 if (vertex_layout.has_value()) {
26 buffer_info[buffer] = { .semantic_layout = vertex_layout.value(), .use_reflection = false };
27 info_it = buffer_info.find(buffer);
28 }
29 }
30 if (info_it == buffer_info.end()) {
31 return nullptr;
32 }
33 }
34 return &info_it->second.semantic_layout;
35}
36
43
44void RenderProcessor::set_fragment_shader(const std::string& fragment_path)
45{
47 m_fragment_shader_id = foundry.load_shader(fragment_path, Portal::Graphics::ShaderStage::FRAGMENT);
49}
50
51void RenderProcessor::set_geometry_shader(const std::string& geometry_path)
52{
54 m_geometry_shader_id = foundry.load_shader(geometry_path, Portal::Graphics::ShaderStage::GEOMETRY);
56}
57
58void RenderProcessor::set_tess_control_shader(const std::string& tess_control_path)
59{
61 m_tess_control_shader_id = foundry.load_shader(tess_control_path, Portal::Graphics::ShaderStage::TESS_CONTROL);
63}
64
65void RenderProcessor::set_tess_eval_shader(const std::string& tess_eval_path)
66{
68 m_tess_eval_shader_id = foundry.load_shader(tess_eval_path, Portal::Graphics::ShaderStage::TESS_EVALUATION);
70}
71
72void RenderProcessor::set_target_window(const std::shared_ptr<Core::Window>& window, const std::shared_ptr<VKBuffer>& buffer)
73{
74 m_target_window = window;
75 window->register_rendering_buffer(buffer);
76}
77
82
89
91{
92 if (enabled) {
94 } else {
96 }
97}
98
105
114
126
138
140 uint32_t binding,
141 const std::shared_ptr<Core::VKImage>& texture,
142 vk::Sampler sampler)
143{
144 if (!texture || !texture->is_initialized() || !texture->get_image_view()) {
146 "Cannot bind null texture to binding {}", binding);
147 return;
148 }
149
150 if (!sampler) {
152 sampler = loom.get_default_sampler();
153 }
154
155 m_texture_bindings[binding] = { .texture = texture, .sampler = sampler };
157
159
160 auto& foundry = Portal::Graphics::get_shader_foundry();
161 auto cfg_it = std::ranges::find_if(m_config.bindings,
162 [binding](const auto& pair) {
163 return binding >= pair.second.binding
164 && binding < pair.second.binding + pair.second.count;
165 });
166
167 if (cfg_it != m_config.bindings.end() && !m_descriptor_set_ids.empty()) {
168 const uint32_t cfg_set = cfg_it->second.set;
169 if (cfg_set == 0) {
171 uint32_t array_idx = 0;
172 if (cfg_it->second.count > 1 && binding >= cfg_it->second.binding) {
173 array_idx = binding - cfg_it->second.binding;
174 }
175 foundry.update_descriptor_image(
177 cfg_it->second.binding,
178 texture->get_image_view(),
179 sampler,
180 vk::ImageLayout::eShaderReadOnlyOptimal,
181 array_idx);
182 }
183 } else {
184 auto ds_index = resolve_ds_index(cfg_set);
185 if (ds_index && *ds_index < m_descriptor_set_ids.size()) {
186 foundry.update_descriptor_image(
187 m_descriptor_set_ids[*ds_index],
188 cfg_it->second.binding,
189 texture->get_image_view(),
190 sampler,
191 vk::ImageLayout::eShaderReadOnlyOptimal);
192 }
193 }
194 }
195 }
196
198 "Bound texture to binding {}", binding);
199}
200
202 const std::string& descriptor_name,
203 const std::shared_ptr<Core::VKImage>& texture,
204 vk::Sampler sampler)
205{
206 auto binding_it = m_config.bindings.find(descriptor_name);
207 if (binding_it == m_config.bindings.end()) {
209 "No binding configured for descriptor '{}'", descriptor_name);
210 return;
211 }
212
213 bind_texture(binding_it->second.binding, texture, sampler);
214}
215
216void RenderProcessor::initialize_pipeline(const std::shared_ptr<VKBuffer>& buffer)
217{
220 "Vertex shader not loaded");
221 return;
222 }
223
226 "Fragment shader not loaded");
227 return;
228 }
229
230 if (!m_target_window) {
232 "Target window not set");
233 return;
234 }
235
237
239
241 pipeline_config.vertex_shader = m_shader_id;
242 pipeline_config.fragment_shader = m_fragment_shader_id;
243 pipeline_config.geometry_shader = m_geometry_shader_id;
245 pipeline_config.tess_eval_shader = m_tess_eval_shader_id;
246
247 pipeline_config.topology = m_primitive_topology;
248 pipeline_config.rasterization.polygon_mode = m_polygon_mode;
249 pipeline_config.rasterization.cull_mode = m_cull_mode;
250
251 if (m_blend_attachment.has_value()) {
252 pipeline_config.blend_attachments.push_back(m_blend_attachment.value());
253 } else {
254 pipeline_config.blend_attachments.emplace_back();
255 }
256
257 pipeline_config.depth_stencil = m_depth_stencil;
258
259 if (m_buffer_info.find(buffer) == m_buffer_info.end()) {
260 if (buffer->has_vertex_layout()) {
261 auto vertex_layout = buffer->get_vertex_layout();
262 if (vertex_layout.has_value()) {
263 m_buffer_info[buffer] = {
264 .semantic_layout = vertex_layout.value(),
265 .use_reflection = false
266 };
267 }
268 }
269 }
270
272 if (!local_layout) {
274 "initialize_pipeline: layout not yet available, deferring");
275 return;
276 }
277
278 pipeline_config.semantic_vertex_layout = *local_layout;
279 pipeline_config.use_vertex_shader_reflection = m_buffer_info[buffer].use_reflection;
280
281 const auto& staging = buffer->get_pipeline_context().push_constant_staging;
282 if (!staging.empty()) {
283 pipeline_config.push_constant_size = staging.size();
284 } else {
285 pipeline_config.push_constant_size = std::max(m_config.push_constant_size, m_push_constant_data.size());
286 }
287
288 auto& descriptor_bindings = buffer->get_pipeline_context().descriptor_buffer_bindings;
289 std::map<std::pair<uint32_t, uint32_t>, Portal::Graphics::DescriptorBindingInfo> unified_bindings;
290
291 for (const auto& binding : descriptor_bindings) {
292 unified_bindings[{ binding.set, binding.binding }] = binding;
293 }
294
295 for (const auto& [name, binding] : m_config.bindings) {
296 auto key = std::make_pair(binding.set, binding.binding);
297 if (unified_bindings.find(key) == unified_bindings.end()) {
298 unified_bindings[key] = Portal::Graphics::DescriptorBindingInfo {
299 .set = binding.set,
300 .binding = binding.binding,
301 .type = binding.type,
302 .buffer_info = {},
303 .name = name,
304 .count = binding.count
305 };
306 }
307 }
308
309 std::map<uint32_t, std::vector<Portal::Graphics::DescriptorBindingInfo>> bindings_by_set;
310 for (const auto& [key, binding] : unified_bindings) {
311 bindings_by_set[binding.set].push_back(binding);
312 }
313
314 for (const auto& [set_index, set_bindings] : bindings_by_set) {
315 pipeline_config.descriptor_sets.push_back(set_bindings);
316 }
317
318 vk::Format swapchain_format = static_cast<vk::Format>(
320
321 vk::Format depth_format = m_depth_enabled
322 ? vk::Format::eD32Sfloat
323 : vk::Format::eUndefined;
324
325 m_pipeline_id = flow.create_pipeline(pipeline_config, { swapchain_format }, depth_format);
326
329 "Failed to create render pipeline");
330 return;
331 }
332
333 if (m_depth_enabled) {
334 buffer->set_needs_depth_attachment(true);
335 }
336
339
341}
342
343void RenderProcessor::initialize_descriptors(const std::shared_ptr<VKBuffer>& buffer)
344{
347 "Cannot allocate descriptor sets without pipeline");
348 return;
349 }
350
352
354 auto& foundry = Portal::Graphics::get_shader_foundry();
355
356 auto vt_layout = flow.get_view_transform_layout(m_pipeline_id);
357 if (vt_layout) {
358 m_view_transform_descriptor_set_id = foundry.allocate_descriptor_set(vt_layout);
359
360 m_view_transform_ubo = std::make_shared<VKBuffer>(
365
366 foundry.update_descriptor_buffer(
368 0,
369 vk::DescriptorType::eUniformBuffer,
370 m_view_transform_ubo->get_buffer(),
371 0,
372 sizeof(Kinesis::ViewTransform));
373
375 "ViewTransform UBO allocated (pipeline {})", m_pipeline_id);
376 }
377
378 m_descriptor_set_ids = flow.allocate_pipeline_descriptors(m_pipeline_id, 1);
379
380 for (const auto& [binding, tex_binding] : m_texture_bindings) {
381 if (!tex_binding.texture
382 || !tex_binding.texture->is_initialized()
383 || !tex_binding.texture->get_image_view()) {
384 continue;
385 }
386
387 auto config_it = std::ranges::find_if(m_config.bindings,
388 [binding](const auto& pair) {
389 return binding >= pair.second.binding
390 && binding < pair.second.binding + pair.second.count;
391 });
392
393 if (config_it == m_config.bindings.end()) {
395 "No config for binding {}", binding);
396 continue;
397 }
398
399 const uint32_t set_index = config_it->second.set;
400
401 if (set_index == 0) {
404 "Engine descriptor set not allocated for set=0 texture binding {}", binding);
405 continue;
406 }
407 foundry.update_descriptor_image(
409 config_it->second.binding,
410 tex_binding.texture->get_image_view(),
411 tex_binding.sampler,
412 vk::ImageLayout::eShaderReadOnlyOptimal,
413 binding - config_it->second.binding);
414 continue;
415 }
416
417 auto ds_index = resolve_ds_index(set_index);
418 if (!ds_index) {
420 "Descriptor set index {} out of range", binding);
421 continue;
422 }
423
424 foundry.update_descriptor_image(
425 m_descriptor_set_ids[*ds_index],
426 config_it->second.binding,
427 tex_binding.texture->get_image_view(),
428 tex_binding.sampler,
429 vk::ImageLayout::eShaderReadOnlyOptimal,
430 binding - config_it->second.binding);
431 }
432
434 "Allocated {} descriptor sets and updated {} texture bindings",
436
437 update_descriptors(buffer);
439}
440
441void RenderProcessor::set_vertex_range(uint32_t first_vertex, uint32_t vertex_count)
442{
443 m_first_vertex = first_vertex;
444 m_vertex_count = vertex_count;
445
447 "RenderProcessor: Set vertex range [offset={}, count={}]",
448 first_vertex, vertex_count);
449}
450
452 const std::shared_ptr<VKBuffer>& buffer,
453 const Kakshya::VertexLayout& layout)
454{
455 m_buffer_info[buffer] = {
456 .semantic_layout = layout,
457 .use_reflection = false
458 };
460}
461
462bool RenderProcessor::on_before_execute(Portal::Graphics::CommandBufferID /*cmd_id*/, const std::shared_ptr<VKBuffer>& /*buffer*/)
463{
464 if (!m_target_window) {
466 "Target window not set");
467 return false;
468 }
469 return m_target_window->is_graphics_registered();
470}
471
472void RenderProcessor::execute_shader(const std::shared_ptr<VKBuffer>& buffer)
473{
474 if (m_buffer_info.find(buffer) == m_buffer_info.end()) {
475 if (buffer->has_vertex_layout()) {
476 auto vertex_layout = buffer->get_vertex_layout();
477 if (vertex_layout.has_value()) {
478 m_buffer_info[buffer] = {
479 .semantic_layout = vertex_layout.value(),
480 .use_reflection = false
481 };
482 }
483 }
484 }
485
486 if (!m_target_window->is_graphics_registered()) {
487 return;
488 }
489
491 return;
492 }
493
495 if (!local_layout) {
497 "VKBuffer has no vertex layout set. Use buffer->set_vertex_layout()");
498 return;
499 }
500
501 buffer->set_pipeline_window(m_pipeline_id, m_target_window);
502
503 auto& foundry = Portal::Graphics::get_shader_foundry();
505
506 vk::Format color_format = static_cast<vk::Format>(
508
509 vk::Format depth_format = m_depth_enabled
510 ? vk::Format::eD32Sfloat
511 : vk::Format::eUndefined;
512
513 auto cmd_id = foundry.begin_secondary_commands(color_format, depth_format);
514 auto cmd = foundry.get_command_buffer(cmd_id);
515
516 uint32_t width = 0, height = 0;
518
519 if (width > 0 && height > 0) {
520 auto cmd = foundry.get_command_buffer(cmd_id);
521
522 vk::Viewport viewport {
523 0.0F,
524 static_cast<float>(height),
525 static_cast<float>(width),
526 -static_cast<float>(height),
527 0.0F,
528 1.0F
529 };
530 cmd.setViewport(0, 1, &viewport);
531
532 vk::Rect2D scissor { { 0, 0 }, { width, height } };
533 cmd.setScissor(0, 1, &scissor);
534 }
535
536 flow.bind_pipeline(cmd_id, m_pipeline_id);
537
538 auto& engine_bindings = buffer->get_engine_context().ssbo_bindings;
539 for (const auto& binding : engine_bindings) {
540 if (binding.set == 0 && binding.binding == 0) {
542 "Engine SSBO at binding=0 is reserved for ViewTransform UBO");
543 continue;
544 }
547 "Engine SSBO binding {} skipped: engine descriptor set not allocated", binding.binding);
548 continue;
549 }
550 foundry.update_descriptor_buffer(
552 binding.binding,
553 binding.type,
554 binding.buffer_info.buffer,
555 binding.buffer_info.offset,
556 binding.buffer_info.range);
557 }
558
559 auto& descriptor_bindings = buffer->get_pipeline_context().descriptor_buffer_bindings;
560 if (!descriptor_bindings.empty()) {
561 for (const auto& binding : descriptor_bindings) {
562 auto ds_index = resolve_ds_index(binding.set);
563 if (!ds_index) {
565 "Descriptor set index {} out of range or reserved", binding.set);
566 continue;
567 }
568
569 foundry.update_descriptor_buffer(
570 m_descriptor_set_ids[*ds_index],
571 binding.binding,
572 binding.type,
573 binding.buffer_info.buffer,
574 binding.buffer_info.offset,
575 binding.buffer_info.range);
576 }
577 }
578
579 if (!m_descriptor_set_ids.empty()) {
580 flow.bind_descriptor_sets(cmd_id, m_pipeline_id, m_descriptor_set_ids);
581 }
582
583 {
589 }
590
591 if (m_view_transform_ubo && m_view_transform_ubo->get_mapped_ptr()) {
592 std::memcpy(
593 m_view_transform_ubo->get_mapped_ptr(),
594 &vt,
595 sizeof(Kinesis::ViewTransform));
596 }
597 }
598
600 flow.bind_descriptor_sets(
601 cmd_id, m_pipeline_id,
603 0);
604 }
605
606 if (!m_descriptor_set_ids.empty()) {
607 flow.bind_descriptor_sets(
608 cmd_id, m_pipeline_id,
610 1);
611 }
612
613 const auto& staging = buffer->get_pipeline_context();
614 if (!staging.push_constant_staging.empty()) {
615 flow.push_constants(
616 cmd_id,
618 staging.push_constant_staging.data(),
619 staging.push_constant_staging.size());
620 } else if (!m_push_constant_data.empty()) {
621 flow.push_constants(
622 cmd_id,
625 m_push_constant_data.size());
626 }
627
628 on_before_execute(cmd_id, buffer);
629
630 flow.bind_vertex_buffers(cmd_id, { buffer });
631
632 uint32_t draw_count = 0;
633 if (m_vertex_count > 0) {
634 draw_count = m_vertex_count;
635 } else {
636 auto current_layout = buffer->get_vertex_layout();
637 if (!current_layout.has_value() || current_layout->vertex_count == 0) {
639 "Vertex layout has zero vertices, skipping draw");
640 return;
641 }
642 draw_count = current_layout->vertex_count;
643 }
644
645 if (buffer->has_index_buffer()) {
646 const auto index_count = static_cast<uint32_t>(
647 buffer->get_index_buffer_size() / sizeof(uint32_t));
648 flow.bind_index_buffer(cmd_id, buffer);
649 flow.draw_indexed(cmd_id, index_count, m_instance_count, 0, 0, 0);
650 } else {
651 flow.draw(cmd_id, draw_count, m_instance_count, m_first_vertex, 0);
652 }
653
654 foundry.end_commands(cmd_id);
655
656 buffer->set_pipeline_command(m_pipeline_id, cmd_id);
657 m_target_window->track_frame_command(cmd_id);
658
660 "Recorded secondary command buffer {} for window '{}'",
661 cmd_id, m_target_window->get_create_info().title);
662}
663
664void RenderProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
665{
666 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
667 if (!vk_buffer)
668 return;
669
671 "RenderProcessor attached to VKBuffer (size: {} bytes, modality: {})",
672 vk_buffer->get_size_bytes(),
673 static_cast<int>(vk_buffer->get_modality()));
674
675 if (vk_buffer && vk_buffer->has_vertex_layout()) {
676 auto vertex_layout = vk_buffer->get_vertex_layout();
677 if (vertex_layout.has_value()) {
679 "RenderProcessor: Auto-injecting vertex layout "
680 "({} vertices, {} attributes)",
681 vertex_layout->vertex_count,
682 vertex_layout->attributes.size());
683
685 m_buffer_info[vk_buffer] = { .semantic_layout = vertex_layout.value(), .use_reflection = false };
686 }
687 }
688
689 if (m_depth_enabled) {
690 vk_buffer->set_needs_depth_attachment(true);
691 }
692
693 if (!m_display_service) {
696 }
697}
698
700{
701 auto& foundry = Portal::Graphics::get_shader_foundry();
703
705 flow.destroy_pipeline(m_pipeline_id);
707 }
708
710 foundry.destroy_shader(m_geometry_shader_id);
712 }
713
715 foundry.destroy_shader(m_tess_control_shader_id);
717 }
718
720 foundry.destroy_shader(m_tess_eval_shader_id);
722 }
723
725 foundry.destroy_shader(m_fragment_shader_id);
727 }
728
729 m_view_transform_ubo.reset();
732
733 if (m_target_window) {
734 flow.unregister_window(m_target_window);
735 m_target_window.reset();
736 }
737
739
741 "RenderProcessor cleanup complete");
742}
743
744} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_RT_TRACE(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
#define MF_RT_DEBUG(comp, ctx,...)
vk::CommandBuffer cmd
uint32_t width
Definition Decoder.cpp:59
void bind_texture(uint32_t binding, const std::shared_ptr< Core::VKImage > &texture, vk::Sampler sampler=nullptr)
Bind a texture to a descriptor binding point.
Portal::Graphics::DescriptorSetID m_view_transform_descriptor_set_id
void set_blend_attachment(const Portal::Graphics::BlendAttachmentConfig &config)
Set blend mode for color attachment.
Portal::Graphics::ShaderID m_fragment_shader_id
std::unordered_map< std::shared_ptr< VKBuffer >, VertexInfo > m_buffer_info
void disable_alpha_blending()
Disable blending on the color attachment, restoring opaque writes.
void set_buffer_vertex_layout(const std::shared_ptr< VKBuffer > &buffer, const Kakshya::VertexLayout &layout)
Override the vertex layout used when building the pipeline for buffer.
std::optional< Portal::Graphics::BlendAttachmentConfig > m_blend_attachment
Registry::Service::DisplayService * m_display_service
Portal::Graphics::ShaderID m_geometry_shader_id
void set_tess_eval_shader(const std::string &tess_eval_path)
bool on_before_execute(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer) override
Called before each process callback.
void enable_alpha_blending()
Enable standard alpha blending (src_alpha, one_minus_src_alpha).
std::function< Kinesis::ViewTransform()> m_view_transform_source
void set_tess_control_shader(const std::string &tess_control_path)
Portal::Graphics::RenderPipelineID m_pipeline_id
void enable_depth_test(Portal::Graphics::CompareOp compare_op=Portal::Graphics::CompareOp::LESS)
Enable depth testing for this processor's pipeline.
Portal::Graphics::ShaderID m_tess_control_shader_id
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void initialize_descriptors(const std::shared_ptr< VKBuffer > &buffer) override
std::optional< Kinesis::ViewTransform > m_view_transform
Portal::Graphics::DepthStencilConfig m_depth_stencil
void initialize_pipeline(const std::shared_ptr< VKBuffer > &buffer) override
std::unordered_map< uint32_t, TextureBinding > m_texture_bindings
void disable_depth_test()
Disable depth testing and depth writes for this processor's pipeline.
void set_geometry_shader(const std::string &geometry_path)
void set_vertex_range(uint32_t first_vertex, uint32_t vertex_count)
Set vertex range for drawing subset of buffer.
Portal::Graphics::PrimitiveTopology m_primitive_topology
void set_view_transform(const Kinesis::ViewTransform &vt)
Set static view transform (evaluated once)
RenderProcessor(const ShaderConfig &config)
void set_fragment_shader(const std::string &fragment_path)
Portal::Graphics::PolygonMode m_polygon_mode
void execute_shader(const std::shared_ptr< VKBuffer > &buffer) override
void set_target_window(const std::shared_ptr< Core::Window > &window, const std::shared_ptr< VKBuffer > &buffer)
void set_alpha_blending(bool enabled)
Toggle standard alpha blending.
Portal::Graphics::CullMode m_cull_mode
const Kakshya::VertexLayout * get_or_cache_vertex_layout(std::unordered_map< std::shared_ptr< VKBuffer >, VertexInfo > &buffer_info, const std::shared_ptr< VKBuffer > &buffer)
std::shared_ptr< Core::Window > m_target_window
Portal::Graphics::ShaderID m_tess_eval_shader_id
std::shared_ptr< VKBuffer > m_view_transform_ubo
void set_view_transform_source(std::function< Kinesis::ViewTransform()> fn)
Set dynamic view transform source (evaluated every frame)
std::optional< uint32_t > resolve_ds_index(uint32_t set) const
Resolve logical descriptor set index to actual index.
Portal::Graphics::ShaderID m_shader_id
std::vector< uint8_t > m_push_constant_data
virtual void on_descriptors_created()
Called after descriptor sets are created.
virtual void update_descriptors(const std::shared_ptr< VKBuffer > &buffer)
virtual void on_pipeline_created(Portal::Graphics::ComputePipelineID pipeline_id)
Called after pipeline is created.
virtual void on_before_descriptors_create()
Called before descriptor sets are created.
bool m_engine_owns_set_zero
Whether the engine reserves set=0 for global resources.
std::vector< Portal::Graphics::DescriptorSetID > m_descriptor_set_ids
Abstract base class for shader-based buffer processing.
void ensure_initialized(const std::shared_ptr< VKBuffer > &buffer)
Definition VKBuffer.cpp:471
@ UNIFORM
Uniform buffer (host-visible)
void register_window_for_rendering(const std::shared_ptr< Core::Window > &window)
Register a window for dynamic rendering.
ShaderID load_shader(const std::string &content, std::optional< ShaderStage > stage=std::nullopt, const std::string &entry_point="main")
Universal shader loader - auto-detects source type.
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
@ UNKNOWN
Unknown or undefined modality.
constexpr RenderPipelineID INVALID_RENDER_PIPELINE
MAYAFLUX_API TextureLoom & get_texture_manager()
Get the global texture manager instance.
constexpr ShaderID INVALID_SHADER
MAYAFLUX_API RenderFlow & get_render_flow()
Get the global render flow instance.
MAYAFLUX_API ShaderFoundry & get_shader_foundry()
Get the global shader compiler instance.
CompareOp
Depth/stencil comparison operation.
constexpr DescriptorSetID INVALID_DESCRIPTOR_SET
std::string shader_path
Path to shader file.
std::unordered_map< std::string, ShaderBinding > bindings
Complete description of vertex data layout in a buffer.
View and projection matrices as a named push constant slot.
static BlendAttachmentConfig alpha_blend()
Create standard alpha blending configuration.
Per-attachment blend configuration.
std::vector< std::vector< DescriptorBindingInfo > > descriptor_sets
std::optional< Kakshya::VertexLayout > semantic_vertex_layout
std::vector< BlendAttachmentConfig > blend_attachments
Complete render pipeline configuration.
std::function< int(const std::shared_ptr< void > &)> get_swapchain_format
Get actual swapchain format for a window.
std::function< void(const std::shared_ptr< void > &, uint32_t &, uint32_t &)> get_swapchain_extent
Get swapchain extent for a window.
Backend display and presentation service interface.