light/modules/renderer/private/system.cpp
light7734 61473c2758
Some checks failed
continuous-integration/drone/push Build is failing
test(renderer): overhaul tests & fix many bugs
2025-10-07 16:09:50 +03:30

131 lines
3.7 KiB
C++

#include <renderer/components/messenger.hpp>
#include <renderer/frontend/context/device.hpp>
#include <renderer/frontend/context/gpu.hpp>
#include <renderer/frontend/context/instance.hpp>
#include <renderer/frontend/context/surface.hpp>
#include <renderer/frontend/context/swapchain.hpp>
#include <renderer/frontend/messenger.hpp>
#include <renderer/frontend/renderer/pass.hpp>
#include <renderer/frontend/renderer/renderer.hpp>
#include <renderer/system.hpp>
#include <surface/components.hpp>
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<ecs::EntityId> {};
for (auto &[entity, surface] : m_registry->view<MessengerComponent>())
{
entities_to_remove.emplace_back(entity);
}
for (auto entity : entities_to_remove)
{
m_registry->remove<MessengerComponent>(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<surface::SurfaceComponent>().peek_events())
{
if (std::holds_alternative<surface::ResizedEvent>(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<MessengerComponent>(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<MessengerComponent>(entity);
return false;
}
} // namespace lt::renderer