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}