#pragma once #include #include #include #include #include #include #include #include #include #include #include #include using ::lt::test::Case; using ::lt::test::expect_eq; using ::lt::test::expect_false; using ::lt::test::expect_not_nullptr; using ::lt::test::expect_throw; using ::lt::test::expect_true; using ::lt::test::Suite; using ::std::ignore; namespace constants { constexpr auto api = lt::renderer::Api::vulkan; constexpr auto resolution = lt::math::uvec2 { 800u, 600u }; constexpr auto frames_in_flight = uint32_t { 3u }; } // namespace constants inline void noop_messenger_callback( lt::renderer::IMessenger::MessageSeverity severity, lt::renderer::IMessenger::MessageType type, const lt::renderer::IMessenger::MessageData &data, std::any &user_data ) { } class Fixture_SurfaceSystem { public: Fixture_SurfaceSystem() { m_system.create_surface_component( m_entity.id(), lt::surface::SurfaceComponent::CreateInfo { .title = "", .resolution = constants::resolution, } ); } [[nodiscard]] auto renderer_system_create_info() -> lt::renderer::System::CreateInfo { return lt::renderer::System::CreateInfo{ .config = lt::renderer::System::Configuration{ .target_api = constants::api, .max_frames_in_flight = constants::frames_in_flight, }, .registry = registry(), .surface_entity = surface_entity(), .debug_callback_info = { .severities = lt::renderer::IMessenger::MessageSeverity::all, .types= lt::renderer::IMessenger::MessageType::all, .callback = noop_messenger_callback, .user_data = {}, } } ; } [[nodiscard]] auto registry() -> lt::memory::Ref & { return m_registry; } [[nodiscard]] auto surface_entity() -> lt::ecs::Entity & { return m_entity; } [[nodiscard]] auto surface_system() -> lt::surface::System & { return m_system; } private: lt::memory::Ref m_registry = lt::memory::create_ref(); lt::ecs::Entity m_entity { m_registry, m_registry->create_entity() }; lt::surface::System m_system = lt::surface::System(m_registry); }; class Fixture_SurfaceGpu: public Fixture_SurfaceSystem { public: Fixture_SurfaceGpu() = default; [[nodiscard]] auto surface() -> lt::renderer::ISurface * { return m_surface.get(); } [[nodiscard]] auto gpu() -> lt::renderer::IGpu * { return m_gpu.get(); } private: lt::memory::Scope m_surface { lt::renderer::ISurface::create( constants::api, lt::renderer::IInstance::get(constants::api), surface_entity() ) }; lt::memory::Scope m_gpu { lt::renderer::IGpu::create(constants::api, lt::renderer::IInstance::get(constants::api)) }; }; class FixtureDeviceSwapchain: public Fixture_SurfaceGpu { public: FixtureDeviceSwapchain() = default; [[nodiscard]] auto device() -> lt::renderer::IDevice * { return m_device.get(); } [[nodiscard]] auto swapchain() -> lt::renderer::ISwapchain * { return m_swapchain.get(); } void recreate_swapchain() { m_swapchain.reset(); m_swapchain = lt::renderer::ISwapchain::create( constants::api, surface(), gpu(), m_device.get() ); } [[nodiscard]] auto has_any_messages() const -> bool { return m_user_data->m_has_any_messages; } [[nodiscard]] auto has_any_messages_of( lt::renderer::IMessenger ::MessageSeverity severity ) const -> uint32_t { return m_user_data->m_severity_counter.contains(severity); } private: static void messenger_callback( lt::renderer::IMessenger::MessageSeverity severity, lt::renderer::IMessenger::MessageType type, const lt::renderer::IMessenger::MessageData &data, std::any &user_data ) { std::cout << "VULKAN MESSAGE: " << data.message << std::endl; // NOLINT std::ignore = data; std::ignore = type; auto *fixture = std::any_cast(user_data); fixture->m_has_any_messages = true; ++fixture->m_severity_counter[severity]; } struct UserData { std::unordered_map m_severity_counter; bool m_has_any_messages {}; }; lt::memory::Scope m_user_data = lt::memory::create_scope(); lt::memory::Scope m_messenger = lt::renderer::IMessenger::create( constants::api, lt::renderer::IInstance::get(constants::api), lt::renderer::IMessenger ::CreateInfo { .severities = lt::renderer::IMessenger ::MessageSeverity::all, .types = lt::renderer::IMessenger ::MessageType::all, .callback = &messenger_callback, .user_data = m_user_data.get(), } ); lt::memory::Scope m_device { lt::renderer::IDevice::create(constants::api, gpu(), surface()) }; lt::memory::Scope m_swapchain { lt::renderer::ISwapchain::create(constants::api, surface(), gpu(), m_device.get()) }; }; class Fixture_RendererSystem: public Fixture_SurfaceSystem { public: Fixture_RendererSystem() = default; [[nodiscard]] auto renderer_system() -> lt::renderer::System & { return m_system; } [[nodiscard]] auto has_any_messages() const -> bool { return m_user_data->m_has_any_messages; } [[nodiscard]] auto has_any_messages_of( lt::renderer::IMessenger ::MessageSeverity severity ) const -> uint32_t { return m_user_data->m_severity_counter.contains(severity); } private: static void messenger_callback( lt::renderer::IMessenger::MessageSeverity severity, lt::renderer::IMessenger::MessageType type, const lt::renderer::IMessenger::MessageData &data, std::any &user_data ) { // I know this makes the tests too verbose... // but makes it easier to figure out what the problem is when things fail on ci log_trc("vulkan: {}", data.message); std::ignore = data; std::ignore = type; auto *fixture = std::any_cast(user_data); fixture->m_has_any_messages = true; ++fixture->m_severity_counter[severity]; } struct UserData { std::unordered_map m_severity_counter; bool m_has_any_messages {}; }; lt::memory::Scope m_user_data = lt::memory::create_scope(); lt::renderer::System m_system = lt::renderer::System::CreateInfo { .config = { .target_api = constants::api, .max_frames_in_flight = constants::frames_in_flight, }, .registry = registry(), .surface_entity = surface_entity(), .debug_callback_info = lt::renderer::IMessenger ::CreateInfo { .severities = lt::renderer::IMessenger ::MessageSeverity::all, .types = lt::renderer::IMessenger ::MessageType::all, .callback = &messenger_callback, .user_data = m_user_data.get(), } }; };