///|
/// Frame profiler data for lightweight in-game overlays.
pub(all) struct FrameProfile {
fps : Double
frame_time_ms : Double
update_ms : Double
draw_ms : Double
gpu_frame_ms : Double
draw_calls : Int
vertex_count : Int
asset_inflight : Int
} derive(Debug)
///|
pub impl Show for FrameProfile with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub fn default_frame_profile() -> FrameProfile {
{
fps: 0.0,
frame_time_ms: 0.0,
update_ms: 0.0,
draw_ms: 0.0,
gpu_frame_ms: 0.0,
draw_calls: 0,
vertex_count: 0,
asset_inflight: 0,
}
}
///|
fn profiler_frame(
dst : @gfx.ImageHandle,
shader : @gfx.ShaderHandle,
screen_w : Double,
screen_h : Double,
) -> @renderer2d.RenderFrame2D {
@renderer2d.RenderFrame2D::new(
dst~,
shader~,
screen_w=screen_w.to_int(),
screen_h=screen_h.to_int(),
)
}
///|
fn append_profiler_text(
cmds : Array[@gfx.DrawTrianglesCommand],
frame : @renderer2d.RenderFrame2D,
chars : Array[Int],
cx : Double,
cy : Double,
color : @gfx.Color,
scale : Double,
) -> Unit {
@renderer2d.append_dot_text(
cmds,
frame,
@renderer2d.DotText2D::new(chars~, cx~, cy~, color~, scale~),
)
}
///|
fn append_profiler_number(
cmds : Array[@gfx.DrawTrianglesCommand],
frame : @renderer2d.RenderFrame2D,
number : Int,
cx : Double,
cy : Double,
color : @gfx.Color,
scale : Double,
) -> Unit {
@renderer2d.append_number(
cmds,
frame,
@renderer2d.Number2D::new(number~, cx~, cy~, color~, scale~),
)
}
///|
pub fn build_profiler_hud(
cmds : Array[@gfx.DrawTrianglesCommand],
dst : @gfx.ImageHandle,
shader : @gfx.ShaderHandle,
profile : FrameProfile,
screen_w : Double,
screen_h : Double,
) -> Unit {
let frame = profiler_frame(dst, shader, screen_w, screen_h)
let scale = 1.0
let line_h = 20.0
let margin = 8.0
let x = screen_w - 80.0
let mut y = margin + 10.0
let bg_color = @renderer2d.color_from_hex_alpha(0x000000, 0.5)
let text_color = @renderer2d.color_from_hex_alpha(0x00FF00, 0.9)
let warn_color = @renderer2d.color_from_hex_alpha(0xFFFF00, 0.9)
@renderer2d.append_rect_fill(
cmds,
frame,
@renderer2d.RectFill2D::new(
x=screen_w - 160.0,
y=0.0,
w=160.0,
h=margin + line_h * 8.0 + margin,
color=bg_color,
),
)
let fps_int = profile.fps.to_int()
let fps_color = if fps_int < 30 { warn_color } else { text_color }
append_profiler_text(
cmds,
frame,
[70, 80, 83],
x - 30.0,
y,
text_color,
scale,
)
append_profiler_number(cmds, frame, fps_int, x + 20.0, y, fps_color, scale)
y = y + line_h
append_profiler_text(cmds, frame, [70, 84], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.frame_time_ms.to_int(),
x + 20.0,
y,
text_color,
scale,
)
y = y + line_h
append_profiler_text(cmds, frame, [85, 80], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.update_ms.to_int(),
x + 20.0,
y,
text_color,
scale,
)
y = y + line_h
append_profiler_text(cmds, frame, [68, 82], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.draw_ms.to_int(),
x + 20.0,
y,
text_color,
scale,
)
y = y + line_h
append_profiler_text(cmds, frame, [71, 80], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.gpu_frame_ms.to_int(),
x + 20.0,
y,
text_color,
scale,
)
y = y + line_h
append_profiler_text(cmds, frame, [68, 67], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.draw_calls,
x + 20.0,
y,
text_color,
scale,
)
y = y + line_h
append_profiler_text(cmds, frame, [86, 84], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.vertex_count,
x + 20.0,
y,
text_color,
scale,
)
y = y + line_h
append_profiler_text(cmds, frame, [65, 83], x - 30.0, y, text_color, scale)
append_profiler_number(
cmds,
frame,
profile.asset_inflight,
x + 20.0,
y,
text_color,
scale,
)
}