khora_core/renderer/api/
common.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//! Provides common, backend-agnostic enums and data structures for the rendering API.
16
17use crate::{
18    math::{Mat4, Vec3},
19    renderer::{BufferId, RenderPipelineId},
20};
21
22/// Specifies the data type of indices in an index buffer.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub enum IndexFormat {
25    /// Indices are 16-bit unsigned integers.
26    Uint16,
27    /// Indices are 32-bit unsigned integers.
28    Uint32,
29}
30
31/// A backend-agnostic representation of a graphics API.
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
33pub enum GraphicsBackendType {
34    /// Vulkan API.
35    Vulkan,
36    /// Apple's Metal API.
37    Metal,
38    /// Microsoft's DirectX 12 API.
39    Dx12,
40    /// Microsoft's DirectX 11 API.
41    Dx11,
42    /// OpenGL API.
43    OpenGL,
44    /// WebGPU API (for web builds).
45    WebGpu,
46    /// An unknown or unsupported backend.
47    #[default]
48    Unknown,
49}
50
51/// The physical type of a graphics device (GPU).
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
53pub enum RendererDeviceType {
54    /// A GPU integrated into the CPU.
55    IntegratedGpu,
56    /// A discrete, dedicated GPU.
57    DiscreteGpu,
58    /// A virtualized or software-based GPU.
59    VirtualGpu,
60    /// A software renderer running on the CPU.
61    Cpu,
62    /// An unknown or unsupported device type.
63    #[default]
64    Unknown,
65}
66
67/// Defines a high-level rendering strategy.
68/// This will be used by the `RenderAgent` to select the appropriate `RenderLane`.
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub enum RenderStrategy {
71    /// A forward rendering pipeline.
72    Forward,
73    /// A deferred shading pipeline.
74    Deferred,
75    /// A custom, user-defined strategy identified by a number.
76    Custom(u32),
77}
78
79/// The number of samples per pixel for Multisample Anti-Aliasing (MSAA).
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
81pub enum SampleCount {
82    /// 1 sample per pixel (MSAA disabled).
83    #[default]
84    X1,
85    /// 2 samples per pixel.
86    X2,
87    /// 4 samples per pixel.
88    X4,
89    /// 8 samples per pixel.
90    X8,
91    /// 16 samples per pixel.
92    X16,
93    /// 32 samples per pixel.
94    X32,
95    /// 64 samples per pixel.
96    X64,
97}
98
99/// Defines the programmable stage in the graphics pipeline a shader module is for.
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
101pub enum ShaderStage {
102    /// The vertex shader stage.
103    Vertex,
104    /// The fragment (or pixel) shader stage.
105    Fragment,
106    /// The compute shader stage.
107    Compute,
108}
109
110/// Defines the memory format of pixels in a texture.
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
112pub enum TextureFormat {
113    // 8-bit formats
114    /// One 8-bit unsigned normalized component.
115    R8Unorm,
116    /// Two 8-bit unsigned normalized components.
117    Rg8Unorm,
118    /// Four 8-bit unsigned normalized components (RGBA).
119    Rgba8Unorm,
120    /// Four 8-bit unsigned normalized components (RGBA) in the sRGB color space.
121    Rgba8UnormSrgb,
122    /// Four 8-bit unsigned normalized components (BGRA) in the sRGB color space. This is a common swapchain format.
123    Bgra8UnormSrgb,
124    // 16-bit float formats
125    /// One 16-bit float component.
126    R16Float,
127    /// Two 16-bit float components.
128    Rg16Float,
129    /// Four 16-bit float components.
130    Rgba16Float,
131    // 32-bit float formats
132    /// One 32-bit float component.
133    R32Float,
134    /// Two 32-bit float components.
135    Rg32Float,
136    /// Four 32-bit float components.
137    Rgba32Float,
138    // Depth/stencil formats
139    /// A 16-bit unsigned normalized depth format.
140    Depth16Unorm,
141    /// A 24-bit unsigned normalized depth format.
142    Depth24Plus,
143    /// A 24-bit unsigned normalized depth format with an 8-bit stencil component.
144    Depth24PlusStencil8,
145    /// A 32-bit float depth format.
146    Depth32Float,
147    /// A 32-bit float depth format with an 8-bit stencil component.
148    Depth32FloatStencil8,
149}
150
151impl TextureFormat {
152    /// Returns the size in bytes of a single pixel for this format.
153    /// Note: This can be an approximation for packed or complex formats.
154    pub fn bytes_per_pixel(&self) -> u32 {
155        match self {
156            TextureFormat::R8Unorm => 1,
157            TextureFormat::Rg8Unorm => 2,
158            TextureFormat::Rgba8Unorm => 4,
159            TextureFormat::Rgba8UnormSrgb => 4,
160            TextureFormat::Bgra8UnormSrgb => 4,
161            TextureFormat::R16Float => 2,
162            TextureFormat::Rg16Float => 4,
163            TextureFormat::Rgba16Float => 8,
164            TextureFormat::R32Float => 4,
165            TextureFormat::Rg32Float => 8,
166            TextureFormat::Rgba32Float => 16,
167            TextureFormat::Depth16Unorm => 2,
168            TextureFormat::Depth24Plus => 4,
169            TextureFormat::Depth24PlusStencil8 => 4,
170            TextureFormat::Depth32Float => 4,
171            TextureFormat::Depth32FloatStencil8 => 5,
172        }
173    }
174}
175
176// --- Structs ---
177
178/// Provides standardized, backend-agnostic information about the graphics adapter.
179#[derive(Debug, Clone, Default)]
180pub struct RendererAdapterInfo {
181    /// The name of the adapter (e.g., "NVIDIA GeForce RTX 4090").
182    pub name: String,
183    /// The graphics API backend this adapter is associated with.
184    pub backend_type: GraphicsBackendType,
185    /// The physical type of the adapter.
186    pub device_type: RendererDeviceType,
187}
188
189/// Provides standardized, backend-agnostic information about a graphics adapter.
190#[derive(Debug, Clone, Default)]
191pub struct GraphicsAdapterInfo {
192    /// The name of the adapter (e.g., "NVIDIA GeForce RTX 4090").
193    pub name: String,
194    /// The graphics API backend this adapter is associated with.
195    pub backend_type: GraphicsBackendType,
196    /// The physical type of the adapter.
197    pub device_type: RendererDeviceType,
198}
199
200/// A simple representation of a single object to be rendered in a pass.
201/// TODO: evolve this structure to a more high level abstraction for real 3D objects.
202#[derive(Debug, Clone)]
203pub struct RenderObject {
204    /// The [`RenderPipelineId`] to bind for this object.
205    pub pipeline: RenderPipelineId,
206    /// The vertex buffer to bind.
207    pub vertex_buffer: BufferId,
208    /// The index buffer to bind.
209    pub index_buffer: BufferId,
210    /// The number of indices to draw from the index buffer.
211    pub index_count: u32,
212}
213
214/// A collection of global settings that can affect the rendering process.
215#[derive(Debug, Clone)]
216pub struct RenderSettings {
217    /// The desired high-level rendering strategy.
218    pub strategy: RenderStrategy,
219    /// A generic quality level (e.g., 1=Low, 2=Medium, 3=High).
220    pub quality_level: u32,
221    /// If `true`, objects should be rendered in wireframe mode.
222    pub show_wireframe: bool,
223    /// The quiet period in milliseconds after a resize event before the surface is reconfigured.
224    pub resize_debounce_ms: u64,
225    /// A fallback number of frames after which a pending resize is forced, even if events are still incoming.
226    pub resize_max_pending_frames: u32,
227    /// A runtime toggle to enable/disable GPU timestamp instrumentation for profiling.
228    pub enable_gpu_timestamps: bool,
229}
230
231impl Default for RenderSettings {
232    fn default() -> Self {
233        Self {
234            strategy: RenderStrategy::Forward,
235            quality_level: 1,
236            show_wireframe: false,
237            resize_debounce_ms: 120,
238            resize_max_pending_frames: 10,
239            enable_gpu_timestamps: true,
240        }
241    }
242}
243
244/// A collection of performance statistics for a single rendered frame.
245#[derive(Debug, Clone)]
246pub struct RenderStats {
247    /// A sequential counter for rendered frames.
248    pub frame_number: u64,
249    /// The CPU time spent in pre-render preparation (resource updates, culling, etc.).
250    pub cpu_preparation_time_ms: f32,
251    /// The CPU time spent submitting encoded command buffers to the GPU.
252    pub cpu_render_submission_time_ms: f32,
253    /// The GPU execution time of the main render pass, as measured by timestamp queries.
254    pub gpu_main_pass_time_ms: f32,
255    /// The total GPU execution time for the entire frame, as measured by timestamp queries.
256    pub gpu_frame_total_time_ms: f32,
257    /// The number of draw calls encoded for the frame.
258    pub draw_calls: u32,
259    /// The total number of triangles submitted for the frame.
260    pub triangles_rendered: u32,
261    /// An estimate of the VRAM usage in megabytes.
262    pub vram_usage_estimate_mb: f32,
263}
264
265/// Represents a specific point in a frame's GPU execution for timestamping.
266///
267/// These are used by a [`GpuProfiler`] to record timestamps and measure performance.
268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
269pub enum GpuHook {
270    /// Marks the absolute beginning of GPU work for a frame.
271    FrameStart,
272    /// Marks the beginning of the main render pass.
273    MainPassBegin,
274    /// Marks the end of the main render pass.
275    MainPassEnd,
276    /// Marks the absolute end of GPU work for a frame.
277    FrameEnd,
278}
279
280impl GpuHook {
281    /// An array containing all `GpuHook` variants.
282    pub const ALL: [GpuHook; 4] = [
283        GpuHook::FrameStart,
284        GpuHook::MainPassBegin,
285        GpuHook::MainPassEnd,
286        GpuHook::FrameEnd,
287    ];
288}
289
290impl Default for RenderStats {
291    fn default() -> Self {
292        Self {
293            frame_number: 0,
294            cpu_preparation_time_ms: 0.0,
295            cpu_render_submission_time_ms: 0.0,
296            gpu_main_pass_time_ms: 0.0,
297            gpu_frame_total_time_ms: 0.0,
298            draw_calls: 0,
299            triangles_rendered: 0,
300            vram_usage_estimate_mb: 0.0,
301        }
302    }
303}
304
305/// Contains camera and projection information needed to render a specific view.
306/// This data is typically uploaded to a uniform buffer for shader access.
307#[derive(Debug, Clone)]
308pub struct ViewInfo {
309    /// The camera's view matrix (world to view space).
310    pub view_matrix: Mat4,
311    /// The camera's projection matrix (view to clip space).
312    pub projection_matrix: Mat4,
313    /// The camera's position in world space.
314    pub camera_position: Vec3,
315}
316
317impl Default for ViewInfo {
318    fn default() -> Self {
319        Self {
320            view_matrix: Mat4::IDENTITY,
321            projection_matrix: Mat4::IDENTITY,
322            camera_position: Vec3::ZERO,
323        }
324    }
325}