20 return std::make_unique<VulkanBackend>();
31 , m_frame_clock(
std::make_shared<Vruta::FrameClock>(60))
32 , m_subsystem_tokens {
33 .Buffer = Buffers::ProcessingToken::GRAPHICS_BACKEND,
34 .Node = Nodes::ProcessingToken::VISUAL_RATE,
35 .Task = Vruta::ProcessingToken::FRAME_ACCURATE
37 , m_graphics_config(graphics_config)
49 "Initializing Graphics Subsystem...");
54 error<std::runtime_error>(
57 std::source_location::current(),
58 "No graphics backend available");
72 "Graphics Subsystem initialized (Target FPS: {})",
82 }
catch (std::exception& e) {
86 std::source_location::current(),
87 "Failed to initialize Portal::Graphics subsystem: {}",
95 error<std::runtime_error>(
98 std::source_location::current(),
99 "Cannot register frame processor: no processing handle");
103 if (!scheduler.is_valid()) {
104 error<std::runtime_error>(
107 std::source_location::current(),
108 "Cannot register frame processor: no scheduler available");
111 scheduler.register_token_processor(
112 [
this](
const std::vector<std::shared_ptr<Vruta::Routine>>& tasks, uint64_t processing_units) {
117 "Registered custom FRAME_ACCURATE processor");
123 error<std::runtime_error>(
126 std::source_location::current(),
127 "Subsystem is not initialized. Please initialize before registering callbacks.");
133 "Graphics callbacks registered (self-driven mode)");
137 const std::vector<std::shared_ptr<Vruta::Routine>>& tasks,
138 uint64_t processing_units)
146 if (processing_units == 0) {
147 processing_units = 1;
150 for (uint64_t i = 0; i < processing_units; ++i) {
151 uint64_t frame_to_process = current_frame + i;
153 for (
auto& routine : tasks) {
154 if (!routine || !routine->is_active()) {
158 if (routine->requires_clock_sync()) {
159 if (frame_to_process >= routine->next_execution()) {
160 routine->try_resume(frame_to_process);
163 routine->try_resume(frame_to_process);
171 if (
m_running.load(std::memory_order_acquire)) {
173 "Graphics thread already running!");
178 m_paused.store(
false, std::memory_order_release);
186 "Graphics thread started (ID: {}, Target FPS: {})",
192 }
catch (
const std::exception& e) {
196 std::source_location::current(),
197 "Graphics thread error");
201 "Graphics thread stopped.");
207 if (!
m_running.load(std::memory_order_acquire)) {
212 "Stopping Graphics Subsystem...");
214 m_running.store(
false, std::memory_order_release);
227 window->set_graphics_registered(
false);
231 "Graphics Subsystem stopped.");
236 if (!
m_running.load(std::memory_order_acquire)) {
238 "Cannot pause - graphics thread not running");
242 m_paused.store(
true, std::memory_order_release);
245 "Graphics processing paused");
250 if (!
m_running.load(std::memory_order_acquire)) {
252 "Cannot resume - graphics thread not running");
256 m_paused.store(
false, std::memory_order_release);
259 "Graphics processing resumed");
277 "Target FPS updated to {}", fps);
312 if (window->is_graphics_registered()) {
316 if (
m_backend->register_window(window)) {
320 "Failed to register window '{}' for graphics processing",
321 window->get_create_info().title);
330 if (window->should_close() && window->is_graphics_registered()) {
332 window->set_graphics_registered(
false);
339 [](
const std::shared_ptr<Window>& win) { return win->should_close(); }),
347 window->set_graphics_registered(
false);
362 while (
m_running.load(std::memory_order_acquire)) {
363 if (
m_paused.load(std::memory_order_acquire)) {
364 std::this_thread::sleep_for(std::chrono::milliseconds(16));
378 "Frame lag detected: {} frames behind (Measured FPS: {:.1f})",
400 "Graphics Subsystem shutdown complete.");
#define MF_INFO(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
void process(uint32_t processing_units)
Process all channels in token domain.
void initialize(SubsystemProcessingHandle &handle) override
Initialize with graphics configuration.
void register_frame_processor()
Register custom frame processor with scheduler.
void initialize_graphics_portal()
Initialize Portal::Graphics subsystem.
void cleanup_closed_windows()
Cleanup resources for windows that have been closed.
std::atomic< bool > m_running
void start() override
Start the subsystem's processing/event loops.
void pause() override
Pause the subsystem's processing/event loops.
std::vector< std::shared_ptr< Window > > m_registered_windows
std::thread m_graphics_thread
void register_windows_for_processing()
Register markend windows from window manager for swapchain processing.
void graphics_thread_loop()
Graphics thread main loop.
std::thread::id m_graphics_thread_id
uint32_t get_target_fps() const
Get target frame rate.
void process_frame_coroutines_impl(const std::vector< std::shared_ptr< Vruta::Routine > > &tasks, uint64_t processing_units)
Process all FRAME_ACCURATE coroutines for given frames.
void render_all_windows()
Render all registered windows.
std::atomic< bool > m_paused
SubsystemProcessingHandle * m_handle
Reference to processing handle.
~GraphicsSubsystem() override
std::shared_ptr< Vruta::FrameClock > m_frame_clock
double get_measured_fps() const
Get actual measured FPS.
void set_target_fps(uint32_t fps)
Set target frame rate (can be changed at runtime)
std::unique_ptr< IGraphicsBackend > m_backend
void stop() override
Stop the subsystem's processing/event loops.
void register_callbacks() override
Register callback hooks for this domain.
GraphicsSubsystem(const GlobalGraphicsConfig &graphics_config)
GraphicsSubsystem constructor.
void teardown_windows()
Teardown all window resources during shutdown.
void resume() override
Resume the subsystem's processing/event loops.
void shutdown() override
Shutdown and cleanup subsystem resources.
GlobalGraphicsConfig m_graphics_config
Graphics/windowing configuration.
void process()
Unified processing callback (alternative to separate methods)
void process(uint32_t num_samples)
Process all nodes in token domain.
std::map< std::string, ProcessHook > post_process_hooks
TaskSchedulerHandle tasks
NodeProcessingHandle nodes
Node processing interface.
WindowManagerHandle windows
std::map< std::string, ProcessHook > pre_process_hooks
BufferProcessingHandle buffers
Buffer processing interface.
Unified interface combining buffer and node processing for subsystems.
void process(uint64_t processing_units)
Process all tasks in token domain.
Vulkan implementation of the IGraphicsBackend interface.
void process()
Process window events and frame hooks.
std::vector< std::shared_ptr< Core::Window > > get_processing_windows() const
Get list of windows that are open and not minimized.
std::unique_ptr< IGraphicsBackend > create_graphics_backend(GlobalGraphicsConfig::GraphicsApi api)
@ GraphicsSubsystem
Graphics subsystem operations (Vulkan, rendering pipeline)
@ Core
Core engine, backend, subsystems.
void stop()
Stop all Portal::Graphics operations.
void shutdown()
Shutdown Portal::Graphics subsystem.
bool is_initialized()
Check if Portal::Graphics is initialized.
bool initialize(const std::shared_ptr< Core::VulkanBackend > &backend)
Initialize Portal::Graphics Glue Layer.
void shutdown()
Shutdown Portal::Text.
bool initialize(std::optional< Core::TextConfig > config)
Initialize Portal::Text.
TextConfig text_config
Default font for Portal::Text.
uint32_t target_frame_rate
Target frame rate for visual processing (Hz)