khora_lanes/render_lane/
mod.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
15//! Rendering lane - hot path for graphics operations
16
17use khora_core::{
18    asset::{AssetUUID, Material},
19    renderer::{
20        api::{GpuMesh, RenderContext},
21        traits::CommandEncoder,
22        RenderPipelineId,
23    },
24};
25use khora_data::assets::Assets;
26use std::sync::RwLock;
27
28mod extract_lane;
29mod forward_plus_lane;
30mod lit_forward_lane;
31pub mod shaders;
32mod simple_unlit_lane;
33mod world;
34
35pub use extract_lane::*;
36pub use forward_plus_lane::*;
37pub use lit_forward_lane::*;
38pub use simple_unlit_lane::*;
39pub use world::*;
40
41/// A trait defining the behavior of a rendering lane.
42///
43/// Rendering lanes are responsible for encoding GPU commands to render the scene
44/// represented in the `RenderWorld`. Different implementations provide different
45/// rendering strategies (e.g., forward rendering, deferred rendering, unlit rendering).
46///
47/// This trait enables the `RenderAgent` to work with multiple rendering strategies
48/// without being coupled to any specific implementation, following the CLAD
49/// architecture's separation of concerns.
50///
51/// The lane uses abstractions from `khora-core` (CommandEncoder, TextureViewId, etc.)
52/// and does not depend on infrastructure-specific types.
53pub trait RenderLane: Send + Sync {
54    /// Returns a human-readable identifier for this rendering strategy.
55    ///
56    /// This can be used by the `RenderAgent` for logging, debugging, and
57    /// strategy selection purposes.
58    ///
59    /// # Returns
60    ///
61    /// A static string identifying the rendering strategy (e.g., "SimpleUnlit", "ForwardPlus").
62    fn strategy_name(&self) -> &'static str;
63
64    /// Gets the appropriate render pipeline for a given material.
65    ///
66    /// This method determines which pipeline to use based on the material's properties.
67    /// Different rendering strategies may select different pipelines based on material
68    /// characteristics (e.g., alpha blending, two-sided rendering, texturing).
69    ///
70    /// # Arguments
71    ///
72    /// * `material_uuid`: The UUID of the material, if any
73    /// * `materials`: The cache of Material assets
74    ///
75    /// # Returns
76    ///
77    /// The `RenderPipelineId` to use for rendering with this material.
78    fn get_pipeline_for_material(
79        &self,
80        material_uuid: Option<AssetUUID>,
81        materials: &Assets<Box<dyn Material>>,
82    ) -> RenderPipelineId;
83
84    /// Encodes GPU commands to render the scene into the provided command encoder.
85    ///
86    /// This is the main rendering method that translates the `RenderWorld` into
87    /// actual GPU drawing commands using the abstractions from `khora-core`.
88    ///
89    /// # Arguments
90    ///
91    /// * `render_world`: The intermediate world containing extracted mesh data.
92    /// * `encoder`: The command encoder to record GPU commands into (from core traits).
93    /// * `render_ctx`: The rendering context containing the color target and clear color.
94    /// * `gpu_meshes`: The cache of GPU-resident meshes.
95    /// * `materials`: The cache of materials for pipeline selection.
96    fn render(
97        &self,
98        render_world: &RenderWorld,
99        encoder: &mut dyn CommandEncoder,
100        render_ctx: &RenderContext,
101        gpu_meshes: &RwLock<Assets<GpuMesh>>,
102        materials: &RwLock<Assets<Box<dyn Material>>>,
103    );
104
105    /// Estimates the GPU cost of rendering the given `RenderWorld` with this strategy.
106    ///
107    /// This method is used by the `RenderAgent` to negotiate with GORNA (Goal-Oriented
108    /// Resource Negotiation & Allocation) and determine which rendering strategy to use
109    /// based on available budget and scene complexity.
110    ///
111    /// The cost is measured in abstract units representing GPU workload (e.g., number
112    /// of triangles, draw calls, shader complexity).
113    ///
114    /// # Arguments
115    ///
116    /// * `render_world`: The world to estimate the cost for.
117    /// * `gpu_meshes`: The GPU mesh cache to look up mesh complexity.
118    ///
119    /// # Returns
120    ///
121    /// An estimated cost value. Higher values indicate more expensive rendering.
122    fn estimate_cost(
123        &self,
124        render_world: &RenderWorld,
125        gpu_meshes: &RwLock<Assets<GpuMesh>>,
126    ) -> f32;
127}