khora_core/renderer/traits/profiler.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 super::command_recorder::CommandEncoder;
16use std::any::Any;
17
18/// A trait for GPU performance profilers that use timestamp queries.
19///
20/// This trait defines the interface for a system that can measure the execution time
21/// of GPU operations within a frame. It is designed to be stateful and operate
22/// across multiple frames due to the inherent latency of reading back data from the GPU.
23///
24/// An implementation of this trait will typically manage a set of timestamp query sets
25/// and staging buffers to transfer timing data from the GPU to the CPU without stalling
26/// the rendering pipeline.
27///
28/// The `Any` supertrait is required to allow for downcasting to a concrete profiler
29/// type within backend-specific `CommandEncoder` implementations.
30pub trait GpuProfiler: Any + Send + Sync {
31 /// Attempts to read the results from a frame that finished rendering a few frames ago.
32 ///
33 /// This should be called once per frame, typically at the beginning, before any new
34 /// commands are recorded. It checks for completed buffer mappings from previous frames
35 /// and updates the internal timing statistics.
36 fn try_read_previous_frame(&mut self);
37
38 /// Encodes the commands necessary to resolve the current frame's timestamp queries.
39 ///
40 /// This should be called at the end of a `RenderPass` or command buffer where
41 /// profiling queries were written. It converts the raw timestamp data into a
42 /// format that can be read by the CPU.
43 fn resolve_and_copy(&self, encoder: &mut dyn CommandEncoder);
44
45 /// Encodes commands to copy the resolved query data into a CPU-readable staging buffer.
46 ///
47 /// This is typically called at the very end of the frame's command recording.
48 fn copy_to_staging(&self, encoder: &mut dyn CommandEncoder, frame_index: u64);
49
50 /// Schedules the asynchronous mapping of a staging buffer for CPU readback.
51 ///
52 /// This operation is non-blocking. It tells the GPU driver that we intend to
53 /// read this buffer on the CPU in a future frame, once all commands for the
54 /// current frame have been executed.
55 fn schedule_map_after_submit(&mut self, frame_index: u64);
56
57 /// Returns the smoothed duration of the main rendering pass in milliseconds.
58 ///
59 /// This value is typically averaged over several frames to provide a stable reading.
60 fn last_main_pass_ms(&self) -> f32;
61
62 /// Returns the smoothed total duration of the frame on the GPU in milliseconds.
63 ///
64 /// This value is typically averaged over several frames to provide a stable reading.
65 fn last_frame_total_ms(&self) -> f32;
66
67 /// Returns a reference to `self` as a `&dyn Any` trait object.
68 fn as_any(&self) -> &dyn Any;
69
70 /// Returns a mutable reference to `self` as a `&mut dyn Any` trait object.
71 fn as_any_mut(&mut self) -> &mut dyn Any;
72}