19 return std::make_unique<VulkanBackend>();
30 , m_frame_clock(
std::make_shared<Vruta::FrameClock>(60))
31 , m_subsystem_tokens {
32 .Buffer = Buffers::ProcessingToken::GRAPHICS_BACKEND,
33 .Node = Nodes::ProcessingToken::VISUAL_RATE,
34 .Task = Vruta::ProcessingToken::FRAME_ACCURATE
36 , m_graphics_config(graphics_config)
48 "Initializing Graphics Subsystem...");
53 error<std::runtime_error>(
56 std::source_location::current(),
57 "No graphics backend available");
69 "Graphics Subsystem initialized (Target FPS: {})",
79 }
catch (std::exception& e) {
83 std::source_location::current(),
84 "Failed to initialize Portal::Graphics subsystem: {}",
92 error<std::runtime_error>(
95 std::source_location::current(),
96 "Cannot register frame processor: no processing handle");
100 if (!scheduler.is_valid()) {
101 error<std::runtime_error>(
104 std::source_location::current(),
105 "Cannot register frame processor: no scheduler available");
108 scheduler.register_token_processor(
109 [
this](
const std::vector<std::shared_ptr<Vruta::Routine>>& tasks, uint64_t processing_units) {
114 "Registered custom FRAME_ACCURATE processor");
120 error<std::runtime_error>(
123 std::source_location::current(),
124 "Subsystem is not initialized. Please initialize before registering callbacks.");
130 "Graphics callbacks registered (self-driven mode)");
134 const std::vector<std::shared_ptr<Vruta::Routine>>& tasks,
135 uint64_t processing_units)
143 if (processing_units == 0) {
144 processing_units = 1;
147 for (uint64_t i = 0; i < processing_units; ++i) {
148 uint64_t frame_to_process = current_frame + i;
150 for (
auto& routine : tasks) {
151 if (!routine || !routine->is_active()) {
155 if (routine->requires_clock_sync()) {
156 if (frame_to_process >= routine->next_execution()) {
157 routine->try_resume(frame_to_process);
160 routine->try_resume(frame_to_process);
168 if (
m_running.load(std::memory_order_acquire)) {
170 "Graphics thread already running!");
175 m_paused.store(
false, std::memory_order_release);
183 "Graphics thread started (ID: {}, Target FPS: {})",
189 }
catch (
const std::exception& e) {
193 std::source_location::current(),
194 "Graphics thread error");
198 "Graphics thread stopped.");
204 if (!
m_running.load(std::memory_order_acquire)) {
209 "Stopping Graphics Subsystem...");
211 m_running.store(
false, std::memory_order_release);
222 window->set_graphics_registered(
false);
227 "Graphics Subsystem stopped.");
232 if (!
m_running.load(std::memory_order_acquire)) {
234 "Cannot pause - graphics thread not running");
238 m_paused.store(
true, std::memory_order_release);
241 "Graphics processing paused");
246 if (!
m_running.load(std::memory_order_acquire)) {
248 "Cannot resume - graphics thread not running");
252 m_paused.store(
false, std::memory_order_release);
255 "Graphics processing resumed");
273 "Target FPS updated to {}", fps);
308 if (window->is_graphics_registered()) {
312 if (
m_backend->register_window(window)) {
316 "Failed to register window '{}' for graphics processing",
317 window->get_create_info().title);
326 if (window->should_close() && window->is_graphics_registered()) {
328 window->set_graphics_registered(
false);
335 [](
const std::shared_ptr<Window>& win) { return win->should_close(); }),
348 while (
m_running.load(std::memory_order_acquire)) {
349 if (
m_paused.load(std::memory_order_acquire)) {
350 std::this_thread::sleep_for(std::chrono::milliseconds(16));
364 "Frame lag detected: {} frames behind (Measured FPS: {:.1f})",
#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 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 shutdown()
Shutdown Portal::Graphics subsystem.
bool initialize(const std::shared_ptr< Core::VulkanBackend > &backend)
Initialize Portal::Graphics Glue Layer.
uint32_t target_frame_rate
Target frame rate for visual processing (Hz)