Internal rendering logic for a window.
379{
382
383 size_t frame_index = context.current_frame;
384 auto& in_flight = context.in_flight[frame_index];
385
386 if (device.waitForFences(1, &in_flight, VK_TRUE, UINT64_MAX) == vk::Result::eTimeout) {
388 "Skipping frame rendering for window '{}' due to in-flight fence timeout",
389 context.window->get_create_info().title);
390 return;
391 }
392 if (device.resetFences(1, &in_flight) != vk::Result::eSuccess) {
394 "Failed to reset in-flight fence for window '{}'",
395 context.window->get_create_info().title);
396 return;
397 }
398
399 auto image_index_opt = context.swapchain->acquire_next_image(context.image_available[frame_index]);
400 if (!image_index_opt.has_value()) {
401 context.needs_recreation = true;
402 return;
403 }
404 uint32_t image_index = image_index_opt.value();
405
406 auto& image_available = context.image_available[frame_index];
407 auto& render_finished = context.render_finished[frame_index];
408
410 vk::CommandBufferBeginInfo begin_info {};
411 begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
412 cmd.begin(begin_info);
413
414 vk::RenderPassBeginInfo render_pass_info {};
415 render_pass_info.renderPass = context.render_pass->get();
416 render_pass_info.framebuffer = context.framebuffers[image_index]->get();
417 render_pass_info.renderArea.offset = vk::Offset2D { 0, 0 };
418 render_pass_info.renderArea.extent = context.swapchain->get_extent();
419
420 vk::ClearValue clear_color {};
421 clear_color.color = vk::ClearColorValue(std::array<float, 4> { 0.0F, 0.1F, 0.2F, 1.0F });
422 render_pass_info.clearValueCount = 1;
423 render_pass_info.pClearValues = &clear_color;
424
425 cmd.beginRenderPass(render_pass_info, vk::SubpassContents::eInline);
426 cmd.endRenderPass();
427
428 cmd.end();
429
430 vk::SubmitInfo submit_info {};
431 vk::PipelineStageFlags wait_stages[] = { vk::PipelineStageFlagBits::eColorAttachmentOutput };
432 submit_info.waitSemaphoreCount = 1;
433 submit_info.pWaitSemaphores = &image_available;
434 submit_info.pWaitDstStageMask = wait_stages;
435 submit_info.commandBufferCount = 1;
436 submit_info.pCommandBuffers = &cmd;
437 submit_info.signalSemaphoreCount = 1;
438 submit_info.pSignalSemaphores = &render_finished;
439
440 try {
441 auto result = graphics_queue.submit(1, &submit_info, in_flight);
442 } catch (const vk::SystemError& e) {
444 "Failed to submit draw command buffer: {}", e.what());
446 return;
447 }
448
449 bool present_success = context.swapchain->present(image_index, render_finished, graphics_queue);
450 if (!present_success) {
451 context.needs_recreation = true;
452 }
453
454 context.current_frame = (frame_index + 1) % context.in_flight.size();
455}
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
VKCommandManager & m_command_manager
void free_command_buffer(vk::CommandBuffer command_buffer)
Free a command buffer back to the pool.
vk::CommandBuffer allocate_command_buffer()
Allocate a command buffer from the pool.
vk::Device get_device() const
Get logical device.
vk::Queue get_graphics_queue() const
Get graphics queue.
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.