mirror of
https://github.com/touchHLE/touchHLE.git
synced 2026-01-31 01:25:24 +01:00
Add FPS counter option (--print-fps)
This commit is contained in:
@@ -47,6 +47,7 @@ Usability:
|
||||
- The new `--fullscreen` option lets you display an app in fullscreen rather than in a window. This is independent of the internal resolution/scale hack and supports both upscaling and downscaling. (@hikari-no-yume)
|
||||
- touchHLE now has a built-in app picker with a pretty icon grid. Specifying an app on the command-line bypasses it. (@hikari-no-yume)
|
||||
- The new `--button-to-touch=` option lets you map a button on your game controller to a point on the touch screen. touchHLE also now includes default button mappings for some games. (@hikari-no-yume)
|
||||
- The new `--print-fps` option lets you monitor an touchHLE's framerate from the console. (@hikari-no-yume)
|
||||
|
||||
Other:
|
||||
|
||||
|
||||
@@ -124,3 +124,6 @@ Other options:
|
||||
--headless
|
||||
Run in headless mode. touchHLE will not create a window, so there will
|
||||
be no graphical output and no input. Only useful for command-line apps.
|
||||
|
||||
--print-fps
|
||||
Logs the current framerate (FPS) to the console once per second.
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::frameworks::core_graphics::{
|
||||
use crate::frameworks::uikit::ui_color;
|
||||
use crate::gles::gles11_raw as gles11; // constants only
|
||||
use crate::gles::gles11_raw::types::*;
|
||||
use crate::gles::present::present_frame;
|
||||
use crate::gles::present::{present_frame, FpsCounter};
|
||||
use crate::gles::GLES;
|
||||
use crate::mem::Mem;
|
||||
use crate::objc::{id, msg, msg_class, nil, ObjC};
|
||||
@@ -28,6 +28,7 @@ use std::time::{Duration, Instant};
|
||||
pub(super) struct State {
|
||||
texture_framebuffer: Option<(GLuint, GLuint)>,
|
||||
recomposite_next: Option<Instant>,
|
||||
fps_counter: Option<FpsCounter>,
|
||||
}
|
||||
|
||||
/// For use by `NSRunLoop`: call this 60 times per second. Composites the app's
|
||||
@@ -51,6 +52,15 @@ pub fn recomposite_if_necessary(env: &mut Environment) -> Option<Instant> {
|
||||
return None;
|
||||
}
|
||||
|
||||
if env.options.print_fps {
|
||||
env.framework_state
|
||||
.core_animation
|
||||
.composition
|
||||
.fps_counter
|
||||
.get_or_insert_with(FpsCounter::start)
|
||||
.count_frame(format_args!("Core Animation compositor"));
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
let interval = 1.0 / 60.0; // 60Hz
|
||||
let new_recomposite_next = if let Some(recomposite_next) = env
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::frameworks::foundation::ns_string::get_static_str;
|
||||
use crate::frameworks::foundation::NSUInteger;
|
||||
use crate::gles::gles11_raw as gles11; // constants only
|
||||
use crate::gles::gles11_raw::types::*;
|
||||
use crate::gles::present::present_frame;
|
||||
use crate::gles::present::{present_frame, FpsCounter};
|
||||
use crate::gles::{create_gles1_ctx, gles1_on_gl2, GLES};
|
||||
use crate::objc::{id, msg, nil, objc_classes, release, retain, ClassExports, HostObject};
|
||||
use crate::window::Window;
|
||||
@@ -59,6 +59,7 @@ pub(super) struct EAGLContextHostObject {
|
||||
/// Mapping of OpenGL ES renderbuffer names to `EAGLDrawable` instances
|
||||
/// (always `CAEAGLLayer*`). Retains the instance so it won't dangle.
|
||||
renderbuffer_drawable_bindings: HashMap<GLuint, id>,
|
||||
fps_counter: Option<FpsCounter>,
|
||||
}
|
||||
impl HostObject for EAGLContextHostObject {}
|
||||
|
||||
@@ -72,6 +73,7 @@ pub const CLASSES: ClassExports = objc_classes! {
|
||||
let host_object = Box::new(EAGLContextHostObject {
|
||||
gles_ctx: None,
|
||||
renderbuffer_drawable_bindings: HashMap::new(),
|
||||
fps_counter: None,
|
||||
});
|
||||
env.objc.alloc_object(this, host_object, &mut env.mem)
|
||||
}
|
||||
@@ -190,6 +192,15 @@ pub const CLASSES: ClassExports = objc_classes! {
|
||||
- (bool)presentRenderbuffer:(NSUInteger)target {
|
||||
assert!(target == gles11::RENDERBUFFER_OES);
|
||||
|
||||
if env.options.print_fps {
|
||||
env
|
||||
.objc
|
||||
.borrow_mut::<EAGLContextHostObject>(this)
|
||||
.fps_counter
|
||||
.get_or_insert_with(FpsCounter::start)
|
||||
.count_frame(format_args!("EAGLContext {:?}", this));
|
||||
}
|
||||
|
||||
let fullscreen_layer = find_fullscreen_eagl_layer(env);
|
||||
|
||||
// Unclear from documentation if this method requires the context to be
|
||||
|
||||
@@ -9,6 +9,34 @@
|
||||
use super::gles11_raw as gles11; // constants and types only
|
||||
use super::GLES;
|
||||
use crate::matrix::Matrix;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub struct FpsCounter {
|
||||
time: std::time::Instant,
|
||||
frames: u32,
|
||||
}
|
||||
impl FpsCounter {
|
||||
pub fn start() -> Self {
|
||||
FpsCounter {
|
||||
time: Instant::now(),
|
||||
frames: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count_frame(&mut self, label: std::fmt::Arguments<'_>) {
|
||||
self.frames += 1;
|
||||
let now = Instant::now();
|
||||
let duration = now - self.time;
|
||||
if duration >= Duration::from_secs(1) {
|
||||
self.time = now;
|
||||
echo!(
|
||||
"touchHLE: {} FPS: {:.2}",
|
||||
label,
|
||||
std::mem::take(&mut self.frames) as f32 / duration.as_secs_f32()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Present the the latest frame (e.g. the app's splash screen or rendering
|
||||
/// output), provided as a texture bound to `GL_TEXTURE_2D`, by drawing it on
|
||||
|
||||
@@ -39,6 +39,7 @@ pub struct Options {
|
||||
pub direct_memory_access: bool,
|
||||
pub gdb_listen_addrs: Option<Vec<SocketAddr>>,
|
||||
pub headless: bool,
|
||||
pub print_fps: bool,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
@@ -57,6 +58,7 @@ impl Default for Options {
|
||||
direct_memory_access: true,
|
||||
gdb_listen_addrs: None,
|
||||
headless: false,
|
||||
print_fps: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,6 +134,8 @@ impl Options {
|
||||
self.gdb_listen_addrs = Some(addrs);
|
||||
} else if arg == "--headless" {
|
||||
self.headless = true;
|
||||
} else if arg == "--print-fps" {
|
||||
self.print_fps = true;
|
||||
} else {
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user