Add debug overlay and performance graph.

This commit is contained in:
IntegratedQuantum 2023-04-04 19:22:02 +02:00
parent 9dee31ccbe
commit 914be9cf63
7 changed files with 184 additions and 4 deletions

View File

@ -7,7 +7,7 @@ uniform vec2 screen;
uniform int points;
uniform int offset;
layout(std430, binding = 4) buffer _data
layout(std430, binding = 5) buffer _data
{
float data[];
};

View File

@ -380,6 +380,12 @@ pub const draw = struct {
pub fn text(_text: []const u8, x: f32, y: f32, fontSize: f32, alignment: TextBuffer.Alignment) !void {
try TextRendering.renderText(_text, x, y, fontSize, .{.color = @truncate(u24, @bitCast(u32, color))}, alignment);
}
pub fn print(comptime format: []const u8, args: anytype, x: f32, y: f32, fontSize: f32, alignment: TextBuffer.Alignment) !void {
const string = try std.fmt.allocPrint(main.threadAllocator, format, args);
defer main.threadAllocator.free(string);
try text(string, x, y ,fontSize, alignment);
}
};
pub const TextBuffer = struct {

View File

@ -241,6 +241,26 @@ pub fn openWindow(id: []const u8) Allocator.Error!void {
std.log.warn("Could not find window with id {s}.", .{id});
}
pub fn toggleWindow(id: []const u8) Allocator.Error!void {
defer updateWindowPositions();
for(windowList.items) |window| {
if(std.mem.eql(u8, window.id, id)) {
for(openWindows.items, 0..) |_openWindow, i| {
if(_openWindow == window) {
_ = openWindows.swapRemove(i);
selectedWindow = null;
return;
}
}
try openWindows.append(window);
try window.onOpenFn();
selectedWindow = null;
return;
}
}
std.log.warn("Could not find window with id {s}.", .{id});
}
pub fn openHud() Allocator.Error!void {
for(windowList.items) |window| {
if(window.isHud) {

View File

@ -4,6 +4,7 @@ pub const chat = @import("chat.zig");
pub const controls = @import("controls.zig");
pub const creative = @import("creative.zig");
pub const crosshair = @import("crosshair.zig");
pub const debug = @import("debug.zig");
pub const graphics = @import("graphics.zig");
pub const healthbar = @import("healthbar.zig");
pub const hotbar = @import("hotbar.zig");
@ -11,6 +12,7 @@ pub const inventory = @import("inventory.zig");
pub const inventory_crafting = @import("inventory_crafting.zig");
pub const main = @import("main.zig");
pub const multiplayer = @import("multiplayer.zig");
pub const performance_graph = @import("performance_graph.zig");
pub const settings = @import("settings.zig");
pub const sound = @import("sound.zig");
pub const workbench = @import("workbench.zig");

51
src/gui/windows/debug.zig Normal file
View File

@ -0,0 +1,51 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const main = @import("root");
const graphics = main.graphics;
const draw = graphics.draw;
const Texture = graphics.Texture;
const Vec2f = main.vec.Vec2f;
const gui = @import("../gui.zig");
const GuiWindow = gui.GuiWindow;
const GuiComponent = gui.GuiComponent;
pub var window = GuiWindow {
.contentSize = Vec2f{128, 16},
.title = "Debug",
.id = "cubyz:debug",
.isHud = false,
.showTitleBar = false,
.hasBackground = false,
};
fn flawedRender() !void {
draw.setColor(0xffffffff);
var y: f32 = 0;
try 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);
y += 8;
try draw.print(" frameTime: {d:.1} ms", .{main.lastFrameTime.load(.Monotonic)*1000.0}, 0, y, 8, .left);
y += 8;
try draw.print("window size: {}×{}", .{main.Window.width, main.Window.height}, 0, y, 8, .left);
y += 8;
if (main.game.world != null) {
try draw.print("Pos: {d:.1}", .{main.game.Player.getPosBlocking()}, 0, y, 8, .left);
y += 8;
try draw.print("Game Time: {}", .{main.game.world.?.gameTime.load(.Monotonic)}, 0, y, 8, .left);
y += 8;
try draw.print("Queue size: {}", .{main.threadPool.loadList.size}, 0, y, 8, .left);
y += 8;
// TODO: biome
y += 8;
// TODO: packet loss
y += 8;
// TODO: Protocl statistics(maybe?)
}
}
pub fn render() Allocator.Error!void {
flawedRender() catch |err| {
std.log.err("Encountered error while drawing debug window: {s}", .{@errorName(err)});
};
}

View File

@ -0,0 +1,84 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const main = @import("root");
const graphics = main.graphics;
const draw = graphics.draw;
const Texture = graphics.Texture;
const Vec2f = main.vec.Vec2f;
const gui = @import("../gui.zig");
const GuiWindow = gui.GuiWindow;
const GuiComponent = gui.GuiComponent;
pub var window = GuiWindow {
.contentSize = Vec2f{128, 64},
.title = "Performance Graph",
.id = "cubyz:performance_graph",
.isHud = false,
.showTitleBar = false,
.hasBackground = false,
};
var lastFrameTime: [2048]f32 = undefined;
var index: u31 = 0;
var ssbo: graphics.SSBO = undefined;
var shader: graphics.Shader = undefined;
const border: f32 = 8;
var uniforms: struct {
start: c_int,
dimension: c_int,
screen: c_int,
points: c_int,
offset: c_int,
lineColor: c_int,
} = undefined;
pub fn init() !void {
ssbo = graphics.SSBO.init();
shader = try graphics.Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/graph.vs", "assets/cubyz/shaders/graphics/graph.fs", &uniforms);
}
pub fn deinit() void {
ssbo.deinit();
}
fn flawedRender() !void {
lastFrameTime[index] = @floatCast(f32, main.lastFrameTime.load(.Monotonic)*1000.0);
index = (index + 1)%@intCast(u31, lastFrameTime.len);
draw.setColor(0xffffffff);
try draw.text("32 ms", 0, 16, 8, .left);
try draw.text("16 ms", 0, 32, 8, .left);
try draw.text("00 ms", 0, 48, 8, .left);
draw.setColor(0x80ffffff);
draw.line(.{border, 24}, .{window.contentSize[0] - border, 24});
draw.line(.{border, 40}, .{window.contentSize[0] - border, 40});
draw.line(.{border, 56}, .{window.contentSize[0] - border, 56});
draw.setColor(0xffffffff);
shader.bind();
graphics.c.glUniform1i(uniforms.points, lastFrameTime.len);
graphics.c.glUniform1i(uniforms.offset, index);
graphics.c.glUniform3f(uniforms.lineColor, 1, 1, 1);
var pos = Vec2f{border, border};
var dim = window.contentSize - @splat(2, 2*border);
pos *= @splat(2, draw.setScale(1));
pos += draw.setTranslation(.{0, 0});
dim *= @splat(2, draw.setScale(1));
pos = @floor(pos);
dim = @ceil(dim);
pos[1] += dim[1];
graphics.c.glUniform2f(uniforms.screen, @intToFloat(f32, main.Window.width), @intToFloat(f32, main.Window.height));
graphics.c.glUniform2f(uniforms.start, pos[0], pos[1]);
graphics.c.glUniform2f(uniforms.dimension, dim[0], draw.setScale(1));
ssbo.bufferData(f32, &lastFrameTime);
ssbo.bind(5);
graphics.c.glDrawArrays(graphics.c.GL_LINE_STRIP, 0, lastFrameTime.len);
}
pub fn render() Allocator.Error!void {
flawedRender() catch |err| {
std.log.err("Encountered error while drawing debug window: {s}", .{@errorName(err)});
};
}

View File

@ -188,6 +188,16 @@ fn takeBackgroundImageFn() void {
std.log.err("Got error while recording the background image: {s}", .{@errorName(err)});
};
}
fn toggleDebugOverlay() void {
gui.toggleWindow("cubyz:debug") catch |err| {
std.log.err("Got error while opening the debug overlay: {s}", .{@errorName(err)});
};
}
fn togglePerformanceOverlay() void {
gui.toggleWindow("cubyz:performance_graph") catch |err| {
std.log.err("Got error while opening the performance_graph overlay: {s}", .{@errorName(err)});
};
}
pub var keyboard: struct {
// Gameplay:
forward: Key = Key{.key = c.GLFW_KEY_W},
@ -221,6 +231,10 @@ pub var keyboard: struct {
textPaste: Key = Key{.key = c.GLFW_KEY_V, .repeatAction = &gui.textCallbacks.paste},
textCut: Key = Key{.key = c.GLFW_KEY_X, .repeatAction = &gui.textCallbacks.cut},
textNewline: Key = Key{.key = c.GLFW_KEY_ENTER, .repeatAction = &gui.textCallbacks.newline},
// debug:
debugOverlay: Key = Key{.key = c.GLFW_KEY_F3, .releaseAction = &toggleDebugOverlay},
performanceOverlay: Key = Key{.key = c.GLFW_KEY_F4, .releaseAction = &togglePerformanceOverlay},
} = .{};
pub const Window = struct {
@ -464,6 +478,8 @@ pub const Window = struct {
}
};
pub var lastFrameTime = std.atomic.Atomic(f64).init(0);
pub fn main() !void {
seed = @bitCast(u64, std.time.milliTimestamp());
var gpa = std.heap.GeneralPurposeAllocator(.{.thread_safe=false}){};
@ -539,7 +555,7 @@ pub fn main() !void {
c.glEnable(c.GL_BLEND);
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
Window.GLFWCallbacks.framebufferSize(undefined, Window.width, Window.height);
var lastTime = std.time.milliTimestamp();
var lastTime = std.time.nanoTimestamp();
while(c.glfwWindowShouldClose(Window.window) == 0) {
{ // Check opengl errors:
@ -552,8 +568,9 @@ pub fn main() !void {
Window.handleEvents();
c.glClearColor(0.5, 1, 1, 1);
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT);
var newTime = std.time.milliTimestamp();
var deltaTime = @intToFloat(f64, newTime -% lastTime)/1000.0;
var newTime = std.time.nanoTimestamp();
var deltaTime = @intToFloat(f64, newTime -% lastTime)/1e9;
lastFrameTime.store(deltaTime, .Monotonic);
lastTime = newTime;
if(game.world != null) { // Update the game
try game.update(deltaTime);