статистика времени кадра

This commit is contained in:
2026-03-01 17:19:52 +03:00
parent 8ca31bf479
commit 9fa13fa913
8 changed files with 98 additions and 29 deletions

View File

@@ -24,17 +24,20 @@ scroll: dvui.ScrollInfo = .{
.horizontal = .auto,
},
native_scaling: bool = true,
redraw_throttle_ms: u32 = 50,
_visible_rect: ?Rect_i = null,
_zoom: f32 = 1,
_redraw_pending: bool = false,
_last_redraw_time_ms: i64 = 0,
cursor_document_point: ?Point2_f = null,
draw_document: bool = true,
show_render_stats: bool = true,
/// Rect тулбара (из предыдущего кадра) для исключения кликов по нему из handleCanvasMouse.
toolbar_rect_scale: ?dvui.RectScale = null,
/// Rect панели свойств (из предыдущего кадра) для исключения кликов по нему из handleCanvasMouse.
properties_rect_scale: ?dvui.RectScale = null,
redraw_throttle_ms: u32 = 50,
frame_index: u64 = 0,
_zoom: f32 = 1,
_last_redraw_time_ms: i64 = 0, // Метка последней перерисовки чтобы ограничить частоту
_visible_rect: ?Rect_i = null,
_redraw_pending: bool = false,
pub fn init(allocator: std.mem.Allocator, document: *Document, engine: RenderEngine) Canvas {
return .{
@@ -80,6 +83,7 @@ fn redraw(self: *Canvas) !void {
self.texture = tex;
}
self._last_redraw_time_ms = std.time.milliTimestamp();
self.frame_index += 1;
}
pub fn exampleReset(self: *Canvas) !void {

View File

@@ -45,17 +45,14 @@ pub const OpenDocument = struct {
};
allocator: std.mem.Allocator,
frame_index: u64,
documents: std.ArrayList(*OpenDocument),
active_document_index: ?usize,
pub fn init(allocator: std.mem.Allocator) !WindowContext {
const frame_index: u64 = 0;
const documents = std.ArrayList(*OpenDocument).empty;
const active_document_index: ?usize = null;
return .{
.allocator = allocator,
.frame_index = frame_index,
.documents = documents,
.active_document_index = active_document_index,
};

View File

@@ -5,6 +5,7 @@ const RenderEngine = @import("RenderEngine.zig").RenderEngine;
const Document = @import("../models/Document.zig");
const basic_models = @import("../models/basic_models.zig");
const cpu_draw = @import("cpu/draw.zig");
const RenderStats = @import("RenderStats.zig");
const Size_i = basic_models.Size_i;
const Rect_i = basic_models.Rect_i;
const Allocator = std.mem.Allocator;
@@ -17,14 +18,18 @@ const Type = enum {
};
type: Type,
_allocator: Allocator,
gradient_start: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 },
gradient_end: Color.PMA = .{ .r = 255, .g = 255, .b = 255, .a = 255 },
_allocator: Allocator,
_renderStats: RenderStats,
pub fn init(allocator: Allocator, render_type: Type) CpuRenderEngine {
return .{
._allocator = allocator,
.type = render_type,
._renderStats = .{
.render_time_ns = 0,
},
};
}
@@ -182,7 +187,13 @@ pub fn renderDocument(self: *CpuRenderEngine, document: *const Document, canvas_
defer self._allocator.free(pixels);
for (pixels) |*p| p.* = .{ .r = 255, .g = 255, .b = 255, .a = 255 };
var t = try std.time.Timer.start();
try cpu_draw.drawDocument(pixels, width, height, visible_rect, document, canvas_size, self._allocator);
self._renderStats.render_time_ns = t.read();
return try dvui.textureCreate(pixels, width, height, .nearest);
}
pub fn getStats(self: CpuRenderEngine) RenderStats {
return self._renderStats;
}

View File

@@ -2,6 +2,7 @@ const dvui = @import("dvui");
const CpuRenderEngine = @import("CpuRenderEngine.zig");
const Document = @import("../models/Document.zig");
const basic_models = @import("../models/basic_models.zig");
const RenderStats = @import("RenderStats.zig");
pub const RenderEngine = union(enum) {
cpu: *CpuRenderEngine,
@@ -18,6 +19,12 @@ pub const RenderEngine = union(enum) {
};
}
pub fn getStats(self: RenderEngine) RenderStats {
return switch (self) {
.cpu => |cpu_r| cpu_r.getStats(),
};
}
/// Растеризует документ в текстуру.
pub fn render(self: RenderEngine, document: *const Document, canvas_size: basic_models.Size_i, visible_rect: basic_models.Rect_i) !?dvui.Texture {
return switch (self) {

View File

@@ -0,0 +1,3 @@
const RenderStats = @This();
render_time_ns: u64, // Время рендера кадра в микросекундах

View File

@@ -7,6 +7,7 @@ const Property = @import("../models/Property.zig").Property;
const PropertyData = @import("../models/Property.zig").Data;
const Rect_i = @import("../models/basic_models.zig").Rect_i;
const Tool = @import("../toolbar/Tool.zig");
const RenderStats = @import("../render/RenderStats.zig");
pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale: dvui.RectScale) void {
var textured = dvui_ext.texturedBox(content_rect_scale, dvui.Rect.all(20));
@@ -36,23 +37,27 @@ pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale:
const scroll_parent = dvui.parentGet();
dvui.parentSet(overlay_parent);
const vbar = scroll.vbar;
const hbar = scroll.hbar;
if (vbar != null) {
// std.debug.print("{any}", .{vbar.?.data()});
}
if (hbar != null) {
// std.debug.print("{any}", .{hbar.?.data()});
}
// Тулбар поверх scroll
var toolbar_box = dvui.box(
@src(),
.{ .dir = .horizontal },
.{
.expand = .none,
.background = false,
.gravity_x = 0.0,
.gravity_y = 0.0,
.margin = dvui.Rect{ .x = 16, .y = 16 },
},
.{},
);
{
drawToolbar(canvas);
// Сохраняем rect тулбара для следующего кадра — в handleCanvasMouse исключаем из него клики
canvas.toolbar_rect_scale = toolbar_box.data().contentRectScale();
}
// Сохраняем rect тулбара для следующего кадра — в handleCanvasMouse исключаем из него клики
canvas.toolbar_rect_scale = toolbar_box.data().contentRectScale();
toolbar_box.deinit();
// Панель свойств поверх scroll (правый верхний угол)
@@ -61,24 +66,20 @@ pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale:
var properties_box = dvui.box(
@src(),
.{ .dir = .horizontal },
.{
.expand = .none,
.background = false,
.gravity_x = 1.0,
.gravity_y = 0.0,
.margin = dvui.Rect{ .w = 32, .y = 16, .h = 100 },
},
.{},
);
{
drawPropertiesPanel(canvas, obj);
// Сохраняем rect панели свойств для следующего кадра — в handleCanvasMouse исключаем из него клики
canvas.properties_rect_scale = properties_box.data().contentRectScale();
}
// Сохраняем rect панели свойств для следующего кадра — в handleCanvasMouse исключаем из него клики
canvas.properties_rect_scale = properties_box.data().contentRectScale();
properties_box.deinit();
}
}
dvui.label(@src(), "Canvas", .{}, .{ .gravity_x = 0.5, .gravity_y = 0.0 });
drawCanvasLabelPanel();
if (canvas.show_render_stats)
drawStatsPanel(canvas.render_engine.getStats(), canvas.frame_index);
if (canvas.properties_rect_scale) |prs| {
for (dvui.events()) |*e| {
@@ -278,6 +279,7 @@ fn drawToolbar(canvas: *Canvas) void {
.corner_radius = dvui.Rect.all(8),
.background = true,
.color_fill = dvui.Color.black.opacity(0.2),
.margin = dvui.Rect{ .x = 16, .y = 16 },
},
);
{
@@ -312,6 +314,7 @@ fn drawPropertiesPanel(canvas: *Canvas, selected_object: *Document.Object) void
.background = true,
.color_fill = dvui.Color.black.opacity(0.2),
.min_size_content = .{ .w = 220 },
.margin = dvui.Rect{ .w = 32, .y = 16, .h = 100 },
},
);
{
@@ -332,6 +335,47 @@ fn drawPropertiesPanel(canvas: *Canvas, selected_object: *Document.Object) void
panel.deinit();
}
fn drawCanvasLabelPanel() void {
var panel = dvui.box(
@src(),
.{ .dir = .vertical },
.{
.gravity_x = 0.5,
.gravity_y = 0.0,
.padding = dvui.Rect.all(8),
.corner_radius = dvui.Rect.all(8),
.background = true,
.color_fill = dvui.Color.black.opacity(0.2),
.margin = dvui.Rect{ .x = 16, .y = 16 },
},
);
{
dvui.label(@src(), "Canvas", .{}, .{});
}
panel.deinit();
}
fn drawStatsPanel(stats: RenderStats, frame_index: u64) void {
var panel = dvui.box(
@src(),
.{ .dir = .vertical },
.{
.gravity_x = 0.0,
.gravity_y = 1.0,
.padding = dvui.Rect.all(8),
.corner_radius = dvui.Rect.all(8),
.background = true,
.color_fill = dvui.Color.black.opacity(0.2),
.margin = dvui.Rect{ .x = 16, .h = 16 },
},
);
{
dvui.label(@src(), "Frame time: {}ms", .{stats.render_time_ns / std.time.ns_per_ms}, .{});
dvui.label(@src(), "Frame index: {}", .{frame_index}, .{});
}
panel.deinit();
}
fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Property, row_index: usize) void {
const row_id: usize = row_index * 16;
var row = dvui.box(

View File

@@ -30,6 +30,5 @@ pub fn guiFrame(ctx: *WindowContext) bool {
}
root.deinit();
ctx.frame_index += 1;
return true;
}

View File

@@ -175,6 +175,7 @@ pub fn leftPanel(ctx: *WindowContext) void {
if (dvui.checkbox(@src(), &canvas.draw_document, "Draw document", .{})) {
canvas.requestRedraw();
}
if (dvui.checkbox(@src(), &canvas.show_render_stats, "Show stats", .{})) {}
if (!canvas.draw_document) {
if (dvui.button(@src(), if (doc.cpu_render.type == .Gradient) "Gradient" else "Squares", .{}, .{})) {
if (doc.cpu_render.type == .Gradient) {
@@ -188,6 +189,9 @@ pub fn leftPanel(ctx: *WindowContext) void {
if (dvui.button(@src(), "Add random shapes", .{}, .{})) {
canvas.addRandomShapes() catch {};
}
if (dvui.button(@src(), "Request redraw", .{}, .{})) {
canvas.requestRedraw();
}
} else {
dvui.label(@src(), "No document", .{}, .{});
}