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}