mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-11 13:31:07 -04:00
Settings: add FPS cap (#532)
* settings: add fpsCap * fpsCap: convert to nanos correctly * main.zig: use specific names for lastBeginRendering and frameTime * physics/fps window: use real time between frames * graphics menu: add fps slider * fpsCap: round slider + fix formatter * fpsCap: prevent overflow * fpsCap: remove debug spam * fpsCap setting: add 'Limit' * debug menu: note fps limit * fpsCap formatter: dupe constant string to prevent free failure * debug menu: remove contradictory (vsync) (unlimited) * debug menu: fix mem leak in fps format * debug manu: simplify fps limit text allocation
This commit is contained in:
parent
3956f07556
commit
ad9cad6270
@ -25,7 +25,14 @@ pub var window = GuiWindow {
|
|||||||
pub fn render() void {
|
pub fn render() void {
|
||||||
draw.setColor(0xffffffff);
|
draw.setColor(0xffffffff);
|
||||||
var y: f32 = 0;
|
var y: f32 = 0;
|
||||||
draw.print("fps: {d:.0} Hz{s}", .{1.0/main.lastFrameTime.load(.monotonic), if(main.settings.vsync) @as([]const u8, " (vsync)") else ""}, 0, y, 8, .left);
|
const fpsCapText = if(main.settings.fpsCap) |fpsCap| std.fmt.allocPrint(main.stackAllocator.allocator, " (limit: {d:.0} Hz)", .{fpsCap}) catch unreachable else "";
|
||||||
|
defer main.stackAllocator.allocator.free(fpsCapText);
|
||||||
|
const fpsLimit = std.fmt.allocPrint(main.stackAllocator.allocator, "{s}{s}", .{
|
||||||
|
fpsCapText,
|
||||||
|
if(main.settings.vsync) " (vsync)" else "",
|
||||||
|
}) catch unreachable;
|
||||||
|
defer main.stackAllocator.allocator.free(fpsLimit);
|
||||||
|
draw.print("fps: {d:.0} Hz{s}", .{1.0/main.lastDeltaTime.load(.monotonic), fpsLimit}, 0, y, 8, .left);
|
||||||
y += 8;
|
y += 8;
|
||||||
draw.print("frameTime: {d:.1} ms", .{main.lastFrameTime.load(.monotonic)*1000.0}, 0, y, 8, .left);
|
draw.print("frameTime: {d:.1} ms", .{main.lastFrameTime.load(.monotonic)*1000.0}, 0, y, 8, .left);
|
||||||
y += 8;
|
y += 8;
|
||||||
|
@ -24,6 +24,27 @@ const anisotropy = [_]u8{1, 2, 4, 8, 16};
|
|||||||
|
|
||||||
const resolutions = [_]u16{25, 50, 100};
|
const resolutions = [_]u16{25, 50, 100};
|
||||||
|
|
||||||
|
fn fpsCapRound(newValue: f32) ?u32 {
|
||||||
|
if(newValue < 144.0) {
|
||||||
|
return @as(u32, @intFromFloat(newValue/5.0))*5;
|
||||||
|
} else if (newValue < 149.0) {
|
||||||
|
return 144;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fpsCapFormatter(allocator: main.utils.NeverFailingAllocator, value: f32) []const u8 {
|
||||||
|
const cap = fpsCapRound(value);
|
||||||
|
if(cap == null)
|
||||||
|
return allocator.dupe(u8, "#ffffffFPS: Unlimited");
|
||||||
|
return std.fmt.allocPrint(allocator.allocator, "#ffffffFPS Limit: {d:.0}", .{cap.?}) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fpsCapCallback(newValue: f32) void {
|
||||||
|
settings.fpsCap = fpsCapRound(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
fn renderDistanceCallback(newValue: u16) void {
|
fn renderDistanceCallback(newValue: u16) void {
|
||||||
settings.renderDistance = newValue + renderDistances[0];
|
settings.renderDistance = newValue + renderDistances[0];
|
||||||
}
|
}
|
||||||
@ -64,6 +85,7 @@ fn resolutionScaleCallback(newValue: u16) void {
|
|||||||
|
|
||||||
pub fn onOpen() void {
|
pub fn onOpen() void {
|
||||||
const list = VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
const list = VerticalList.init(.{padding, 16 + padding}, 300, 16);
|
||||||
|
list.add(ContinuousSlider.init(.{0, 0}, 128, 10.0, 154.0, @floatFromInt(settings.fpsCap orelse 144), &fpsCapCallback, &fpsCapFormatter));
|
||||||
list.add(DiscreteSlider.init(.{0, 0}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - renderDistances[0], &renderDistanceCallback));
|
list.add(DiscreteSlider.init(.{0, 0}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - renderDistances[0], &renderDistanceCallback));
|
||||||
list.add(ContinuousSlider.init(.{0, 0}, 128, 40.0, 120.0, settings.fov, &fovCallback, &fovFormatter));
|
list.add(ContinuousSlider.init(.{0, 0}, 128, 40.0, 120.0, settings.fov, &fovCallback, &fovFormatter));
|
||||||
list.add(CheckBox.init(.{0, 0}, 128, "Bloom", settings.bloom, &bloomCallback));
|
list.add(CheckBox.init(.{0, 0}, 128, "Bloom", settings.bloom, &bloomCallback));
|
||||||
|
31
src/main.zig
31
src/main.zig
@ -347,7 +347,10 @@ pub const KeyBoard = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Records gpu time per frame.
|
||||||
pub var lastFrameTime = std.atomic.Value(f64).init(0);
|
pub var lastFrameTime = std.atomic.Value(f64).init(0);
|
||||||
|
/// Measures time between different frames' beginnings.
|
||||||
|
pub var lastDeltaTime = std.atomic.Value(f64).init(0);
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
seed = @bitCast(std.time.milliTimestamp());
|
seed = @bitCast(std.time.milliTimestamp());
|
||||||
@ -428,7 +431,7 @@ pub fn main() void {
|
|||||||
c.glDepthFunc(c.GL_LESS);
|
c.glDepthFunc(c.GL_LESS);
|
||||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
Window.GLFWCallbacks.framebufferSize(undefined, Window.width, Window.height);
|
Window.GLFWCallbacks.framebufferSize(undefined, Window.width, Window.height);
|
||||||
var lastTime = std.time.nanoTimestamp();
|
var lastBeginRendering = std.time.nanoTimestamp();
|
||||||
|
|
||||||
if(settings.developerAutoEnterWorld.len != 0) {
|
if(settings.developerAutoEnterWorld.len != 0) {
|
||||||
// Speed up the dev process by entering the world directly.
|
// Speed up the dev process by entering the world directly.
|
||||||
@ -448,17 +451,27 @@ pub fn main() void {
|
|||||||
std.time.sleep(16_000_000);
|
std.time.sleep(16_000_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const endRendering = std.time.nanoTimestamp();
|
||||||
|
const frameTime = @as(f64, @floatFromInt(endRendering -% lastBeginRendering))/1e9;
|
||||||
|
if(settings.developerGPUInfiniteLoopDetection and frameTime > 5) { // On linux a process that runs 10 seconds or longer on the GPU will get stopped. This allows detecting an infinite loop on the GPU.
|
||||||
|
std.log.err("Frame got too long with {} seconds. Infinite loop on GPU?", .{frameTime});
|
||||||
|
std.posix.exit(1);
|
||||||
|
}
|
||||||
|
lastFrameTime.store(frameTime, .monotonic);
|
||||||
|
|
||||||
|
if(settings.fpsCap) |fpsCap| {
|
||||||
|
const minFrameTime = @divFloor(1000*1000*1000, fpsCap);
|
||||||
|
const sleep = @min(minFrameTime, @max(0, minFrameTime - (endRendering -% lastBeginRendering)));
|
||||||
|
std.time.sleep(sleep);
|
||||||
|
}
|
||||||
|
const begin = std.time.nanoTimestamp();
|
||||||
|
const deltaTime = @as(f64, @floatFromInt(begin -% lastBeginRendering))/1e9;
|
||||||
|
lastDeltaTime.store(deltaTime, .monotonic);
|
||||||
|
lastBeginRendering = begin;
|
||||||
|
|
||||||
Window.handleEvents();
|
Window.handleEvents();
|
||||||
file_monitor.handleEvents();
|
file_monitor.handleEvents();
|
||||||
|
|
||||||
const newTime = std.time.nanoTimestamp();
|
|
||||||
const deltaTime = @as(f64, @floatFromInt(newTime -% lastTime))/1e9;
|
|
||||||
if(settings.developerGPUInfiniteLoopDetection and deltaTime > 5) { // On linux a process that runs 10 seconds or longer on the GPU will get stopped. This allows detecting an infinite loop on the GPU.
|
|
||||||
std.log.err("Frame got too long with {} seconds. Infinite loop on GPU?", .{deltaTime});
|
|
||||||
std.posix.exit(1);
|
|
||||||
}
|
|
||||||
lastFrameTime.store(deltaTime, .monotonic);
|
|
||||||
lastTime = newTime;
|
|
||||||
if(game.world != null) { // Update the game
|
if(game.world != null) { // Update the game
|
||||||
game.update(deltaTime);
|
game.update(deltaTime);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ pub var cpuThreads: ?u64 = null;
|
|||||||
pub var anisotropicFiltering: u8 = 4.0;
|
pub var anisotropicFiltering: u8 = 4.0;
|
||||||
|
|
||||||
|
|
||||||
|
pub var fpsCap: ?u32 = null;
|
||||||
|
|
||||||
pub var fov: f32 = 70;
|
pub var fov: f32 = 70;
|
||||||
|
|
||||||
pub var mouseSensitivity: f32 = 1;
|
pub var mouseSensitivity: f32 = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user