Skip to main content

khora_core/renderer/traits/
render_system.rs

1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use crate::platform::window::KhoraWindow;
18use crate::renderer::api::{
19    core::{GraphicsAdapterInfo, RenderSettings, RenderStats},
20    resource::{TextureViewId, ViewInfo},
21    scene::RenderObject,
22};
23use crate::renderer::error::RenderError;
24use crate::renderer::GraphicsDevice;
25use crate::telemetry::ResourceMonitor;
26
27/// Targets acquired by [`RenderSystem::begin_frame`] for the current frame.
28///
29/// The engine inserts these into the per-frame `FrameContext` (as
30/// `ColorTarget` / `DepthTarget`) so agents can read them when recording
31/// passes into the frame graph.
32#[derive(Debug, Clone, Copy)]
33pub struct FrameTargets {
34    /// Color attachment: swapchain texture or offscreen viewport.
35    pub color: TextureViewId,
36    /// Depth attachment, when depth buffering is enabled.
37    pub depth: Option<TextureViewId>,
38}
39
40/// A high-level trait representing the entire rendering subsystem.
41///
42/// This trait defines the primary interface for the engine to interact with the renderer.
43/// A concrete implementation of `RenderSystem` (likely in `khora-infra`) encapsulates
44/// all the state and logic needed to render a frame, including device management,
45/// swapchain handling, and the execution of render pipelines.
46pub trait RenderSystem: std::fmt::Debug + Send + Sync {
47    /// Initializes the rendering system with a given window.
48    ///
49    /// This method sets up the graphics device, swapchain, and any other necessary
50    /// backend resources. It should be called once at application startup.
51    ///
52    /// # Returns
53    ///
54    /// On success, it returns a `Vec` of `ResourceMonitor` trait objects that the
55    /// telemetry system can use to track GPU-specific resources like VRAM.
56    fn init(
57        &mut self,
58        window: &dyn KhoraWindow,
59    ) -> Result<Vec<Arc<dyn ResourceMonitor>>, RenderError>;
60
61    /// Notifies the rendering system that the output window has been resized.
62    fn resize(&mut self, new_width: u32, new_height: u32);
63
64    /// Prepares for a new frame.
65    ///
66    /// Updates per-frame uniforms (camera view-projection, etc.) before any
67    /// pass is recorded.
68    fn prepare_frame(&mut self, view_info: &ViewInfo);
69
70    /// Renders a single frame from a flat list of render objects.
71    ///
72    /// Legacy entry point retained for non-agent code paths (tests, demos).
73    /// Production rendering goes through the frame graph.
74    fn render(
75        &mut self,
76        renderables: &[RenderObject],
77        view_info: &ViewInfo,
78        settings: &RenderSettings,
79    ) -> Result<RenderStats, RenderError>;
80
81    /// Returns a reference to the statistics of the last successfully rendered frame.
82    fn get_last_frame_stats(&self) -> &RenderStats;
83
84    /// Checks if a specific, optional rendering feature is supported by the backend.
85    fn supports_feature(&self, feature_name: &str) -> bool;
86
87    /// Returns information about the active graphics adapter (GPU).
88    fn get_adapter_info(&self) -> Option<GraphicsAdapterInfo>;
89
90    /// Returns a shared, thread-safe reference to the underlying `GraphicsDevice`.
91    fn graphics_device(&self) -> Arc<dyn GraphicsDevice>;
92
93    /// Begins a new visual frame by acquiring the swapchain (or viewport) texture.
94    ///
95    /// Called exactly once per frame by the engine, **before** any agent runs.
96    /// The returned [`FrameTargets`] are inserted into the per-frame
97    /// `FrameContext` so agents can address the same color/depth attachments.
98    /// The matching [`end_frame`](Self::end_frame) presents the result.
99    fn begin_frame(&mut self) -> Result<FrameTargets, RenderError>;
100
101    /// Ends the current visual frame by presenting the swapchain texture.
102    ///
103    /// Called exactly once per frame by the engine, **after** the frame graph
104    /// has been compiled and submitted.
105    fn end_frame(&mut self) -> Result<RenderStats, RenderError>;
106
107    /// Renders an editor overlay on top of the current frame.
108    ///
109    /// Called between the frame graph submission and [`end_frame`](Self::end_frame).
110    /// The default implementation is a no-op (no overlay).
111    fn render_overlay(
112        &mut self,
113        _overlay: &mut dyn crate::ui::EditorOverlay,
114        _screen: crate::ui::OverlayScreenDescriptor,
115    ) -> Result<(), RenderError> {
116        Ok(())
117    }
118
119    /// Cleans up and releases all graphics resources.
120    fn shutdown(&mut self);
121
122    /// Allows downcasting to a concrete `RenderSystem` type.
123    fn as_any(&self) -> &dyn std::any::Any;
124
125    /// Allows mutable downcasting to a concrete `RenderSystem` type.
126    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
127
128    /// Whether [`begin_frame`](Self::begin_frame) targets an offscreen viewport
129    /// instead of the swapchain.
130    ///
131    /// When `true`, the engine skips its own [`end_frame`](Self::end_frame) call
132    /// — the caller managing the viewport is responsible for presenting.
133    fn render_to_viewport(&self) -> bool {
134        false
135    }
136
137    /// Toggles whether [`begin_frame`](Self::begin_frame) targets the offscreen
138    /// viewport texture instead of the swapchain.
139    fn set_render_to_viewport(&mut self, _enabled: bool) {}
140}