#include #include #include #include #include #include #include #include #include #include #include namespace lt::renderer { System::System(CreateInfo info) : m_surface_entity(info.surface_entity) , m_api(info.config.target_api) , m_registry(std::move(info.registry)) , m_instance(IInstance::get(m_api)) , m_max_frames_in_flight(info.config.max_frames_in_flight) { ensure(m_registry, "Failed to initialize renderer::System: null registry"); ensure( std::clamp( info.config.max_frames_in_flight, frames_in_flight_lower_limit, frames_in_flight_upper_limit ) == info.config.max_frames_in_flight, "Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> " "{}) ", info.config.max_frames_in_flight, frames_in_flight_lower_limit, frames_in_flight_upper_limit ); if (info.messenger_info.has_value()) { ensure( create_messenger_component(m_registry->create_entity(), info.messenger_info.value()), "Failed to initialize renderer::System: failed to create messenger component" ); } else { log_wrn( "Creating renderer::System without a default messenger component, this is not " "recommended" ); } m_surface = ISurface::create(m_api, m_instance, m_surface_entity); m_gpu = IGpu::create(m_api, m_instance); m_device = IDevice::create(m_api, m_gpu.get(), m_surface.get()); m_swapchain = ISwapchain::create(m_api, m_surface.get(), m_gpu.get(), m_device.get()); m_renderer = { IRenderer::create( m_api, m_device.get(), m_swapchain.get(), info.config.max_frames_in_flight ) }; } System::~System() { auto entities_to_remove = std::vector {}; for (auto &[entity, surface] : m_registry->view()) { entities_to_remove.emplace_back(entity); } for (auto entity : entities_to_remove) { m_registry->remove(entity); } } void System::on_register() { } void System::on_unregister() { } void System::tick(app::TickInfo tick) { std::ignore = tick; for (const auto &event : m_surface_entity.get().peek_events()) { if (std::holds_alternative(event)) { m_swapchain.reset(); m_swapchain = ISwapchain::create(m_api, m_surface.get(), m_gpu.get(), m_device.get()); m_renderer->replace_swapchain(m_swapchain.get()); } } if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success) { m_swapchain.reset(); m_swapchain = ISwapchain::create(m_api, m_surface.get(), m_gpu.get(), m_device.get()); m_renderer->replace_swapchain(m_swapchain.get()); std::ignore = m_renderer->draw(m_frame_idx); // drop the frame if failed twice } m_frame_idx = (m_frame_idx + 1) % m_max_frames_in_flight; } [[nodiscard]] auto System::create_messenger_component( ecs::EntityId entity, MessengerComponent::CreateInfo info ) -> bool try { auto &component = m_registry->add(entity, std::move(info)); component.m_implementation = IMessenger::create(m_api, m_instance, { m_registry, entity }); // component.m_user_data = info.user_data; return true; } catch (const std::exception &exp) { log_err("Failed to create renderer::MessengerComponent:"); log_err("\twhat: {}", exp.what()); m_registry->remove(entity); return false; } } // namespace lt::renderer