From 6f6f2e6ab2290df1a82a6a980797d29736b9c18e Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 4 Apr 2026 03:59:54 +0200 Subject: [PATCH] switching to smp_allocator --- .gitignore | 1 + build.zig | 79 ++++++++++++++++++++++++++++------ build.zig.zon | 4 +- src/soft/SoftDevice.zig | 13 ++++-- src/soft/SoftPipeline.zig | 2 +- src/vulkan/VulkanAllocator.zig | 10 ++++- 6 files changed, 86 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 5ae5879..1a6bdd3 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ scripts/__pycache__/ *.pyc *.spv *_table_dump.txt +vgcore.* diff --git a/build.zig b/build.zig index ac39cc1..6bd77e2 100644 --- a/build.zig +++ b/build.zig @@ -19,6 +19,12 @@ const implementations = [_]ImplementationDesc{ }, }; +const RunningMode = enum { + normal, + gdb, + valgrind, +}; + pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); @@ -104,11 +110,13 @@ pub fn build(b: *std.Build) !void { try targets.append(b.allocator, lib); _ = zcc.createStep(b, "cdb", try targets.toOwnedSlice(b.allocator)); - (try addCTestRunner(b, &impl, c_test, false)).dependOn(&lib_install.step); - (try addCTestRunner(b, &impl, c_test, true)).dependOn(&lib_install.step); + (try addCTestRunner(b, &impl, c_test, .normal)).dependOn(&lib_install.step); + (try addCTestRunner(b, &impl, c_test, .gdb)).dependOn(&lib_install.step); + (try addCTestRunner(b, &impl, c_test, .valgrind)).dependOn(&lib_install.step); - (try addCTS(b, target, &impl, lib, false)).dependOn(&lib_install.step); - (try addCTS(b, target, &impl, lib, true)).dependOn(&lib_install.step); + (try addCTS(b, target, &impl, lib, .normal)).dependOn(&lib_install.step); + (try addCTS(b, target, &impl, lib, .gdb)).dependOn(&lib_install.step); + (try addCTS(b, target, &impl, lib, .valgrind)).dependOn(&lib_install.step); (try addMultithreadedCTS(b, target, &impl, lib)).dependOn(&lib_install.step); } @@ -180,20 +188,37 @@ fn addCTest(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.built return exe; } -fn addCTestRunner(b: *std.Build, impl: *const ImplementationDesc, exe: *std.Build.Step.Compile, comptime gdb: bool) !*std.Build.Step { +fn addCTestRunner(b: *std.Build, impl: *const ImplementationDesc, exe: *std.Build.Step.Compile, comptime mode: RunningMode) !*std.Build.Step { const run = b.addRunArtifact(exe); - if (gdb) { - try run.argv.insert(b.allocator, 0, .{ .bytes = b.fmt("gdb", .{}) }); // Hacky + switch (mode) { + .gdb => try run.argv.insert(b.allocator, 0, .{ .bytes = b.fmt("gdb", .{}) }), // Hacky + .valgrind => try run.argv.insert(b.allocator, 0, .{ .bytes = b.fmt("valgrind", .{}) }), + else => {}, } run.step.dependOn(&exe.step); - const run_step = b.step(b.fmt("test-c-{s}{s}", .{ impl.name, if (gdb) "-gdb" else "" }), b.fmt("Run libvulkan_{s} C test{s}", .{ impl.name, if (gdb) " within GDB" else "" })); + const run_step = b.step( + b.fmt("test-c-{s}{s}", .{ + impl.name, switch (mode) { + .normal => "", + .gdb => "-gdb", + .valgrind => "-valgrind", + }, + }), + b.fmt("Run libvulkan_{s} C tests{s}", .{ + impl.name, switch (mode) { + .normal => "", + .gdb => " within GDB", + .valgrind => " within Valgrind", + }, + }), + ); run_step.dependOn(&run.step); return &run.step; } -fn addCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *const ImplementationDesc, impl_lib: *std.Build.Step.Compile, comptime gdb: bool) !*std.Build.Step { +fn addCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *const ImplementationDesc, impl_lib: *std.Build.Step.Compile, comptime mode: RunningMode) !*std.Build.Step { const cts = b.dependency("cts_bin", .{}); const cts_exe_name = cts.path(b.fmt("deqp-vk-{s}", .{ @@ -212,12 +237,23 @@ fn addCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *const Implemen const cts_exe_path = try cts_exe_name.getPath3(b, null).toString(b.allocator); - const run = b.addSystemCommand(&[_][]const u8{if (gdb) "gdb" else cts_exe_path}); + const run = b.addSystemCommand(&[_][]const u8{switch (mode) { + .normal => cts_exe_path, + .gdb => "gdb", + .valgrind => "valgrind", + }}); run.step.dependOn(&impl_lib.step); - if (gdb) { - run.addArg("--args"); - run.addArg(cts_exe_path); + switch (mode) { + .gdb => { + run.addArg("--args"); + run.addArg(cts_exe_path); + }, + .valgrind => { + run.addArg("--track-origins=yes"); + run.addArg(cts_exe_path); + }, + else => {}, } run.addArg(b.fmt("--deqp-archive-dir={s}", .{try cts.path("").getPath3(b, null).toString(b.allocator)})); @@ -237,7 +273,22 @@ fn addCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *const Implemen run.addArg(b.fmt("--deqp-caselist-file={s}", .{mustpass})); } - const run_step = b.step(b.fmt("raw-cts-{s}{s}", .{ impl.name, if (gdb) "-gdb" else "" }), b.fmt("Run Vulkan conformance tests for libvulkan_{s}{s}", .{ impl.name, if (gdb) " within GDB" else "" })); + const run_step = b.step( + b.fmt("raw-cts-{s}{s}", .{ + impl.name, switch (mode) { + .normal => "", + .gdb => "-gdb", + .valgrind => "-valgrind", + }, + }), + b.fmt("Run Vulkan conformance tests for libvulkan_{s}{s}", .{ + impl.name, switch (mode) { + .normal => "", + .gdb => " within GDB", + .valgrind => " within Valgrind", + }, + }), + ); run_step.dependOn(&run.step); return &run.step; diff --git a/build.zig.zon b/build.zig.zon index a5ed5a0..ca45753 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -59,8 +59,8 @@ .lazy = true, }, .SPIRV_Interpreter = .{ - .url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#15eb36ea4d8bd6b2944dfe7a3f0781ef8b0f6d7c", - .hash = "SPIRV_Interpreter-0.0.1-ajmpn0F2BAAGymxUfLiA_X91J1-7NxiGTIudLSE8XQXH", + .url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#a83a761afa45d8223c20110b8aee68c98271f531", + .hash = "SPIRV_Interpreter-0.0.1-ajmpn3p4BADxJRmBtTxMRKcAWxGLNgSNrwZ8yeybEOjW", }, }, diff --git a/src/soft/SoftDevice.zig b/src/soft/SoftDevice.zig index f06a924..f2ad973 100644 --- a/src/soft/SoftDevice.zig +++ b/src/soft/SoftDevice.zig @@ -35,8 +35,14 @@ pub const Interface = base.Device; const SpawnError = std.Thread.SpawnError; +const DeviceAllocator = struct { + pub inline fn allocator(_: @This()) std.mem.Allocator { + return std.heap.smp_allocator; + } +}; + interface: Interface, -device_allocator: if (config.debug_allocator) std.heap.DebugAllocator(.{}) else std.heap.ThreadSafeAllocator, +device_allocator: if (config.debug_allocator) std.heap.DebugAllocator(.{}) else DeviceAllocator, workers: std.Thread.Pool, blitter: Blitter, @@ -77,7 +83,7 @@ pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocato self.* = .{ .interface = interface, - .device_allocator = if (config.debug_allocator) .init else .{ .child_allocator = std.heap.c_allocator }, // TODO: better device allocator + .device_allocator = if (config.debug_allocator) .init else .{}, .workers = undefined, .blitter = .init, }; @@ -100,9 +106,8 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void if (!self.device_allocator.detectLeaks()) { std.log.scoped(.vkDestroyDevice).debug("No device memory leaks detected", .{}); } + allocator.destroy(self); } - - allocator.destroy(self); } pub fn allocateMemory(interface: *Interface, allocator: std.mem.Allocator, info: *const vk.MemoryAllocateInfo) VkError!*base.DeviceMemory { diff --git a/src/soft/SoftPipeline.zig b/src/soft/SoftPipeline.zig index 309d824..71ab6d6 100644 --- a/src/soft/SoftPipeline.zig +++ b/src/soft/SoftPipeline.zig @@ -129,12 +129,12 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void { var it = self.stages.iterator(); while (it.next()) |stage| { - stage.value.module.unref(allocator); for (stage.value.runtimes) |*runtime| { runtime.deinit(device_allocator); } device_allocator.free(stage.value.runtimes); device_allocator.free(stage.value.entry); + stage.value.module.unref(allocator); } allocator.destroy(self); } diff --git a/src/vulkan/VulkanAllocator.zig b/src/vulkan/VulkanAllocator.zig index b7c9bc1..11e3ebe 100644 --- a/src/vulkan/VulkanAllocator.zig +++ b/src/vulkan/VulkanAllocator.zig @@ -9,16 +9,22 @@ const Alignment = std.mem.Alignment; const Self = @This(); +const FallbackAllocator = struct { + pub inline fn allocator(_: @This()) std.mem.Allocator { + return std.heap.smp_allocator; + } +}; + callbacks: ?vk.AllocationCallbacks, scope: vk.SystemAllocationScope, -fallback_allocator: std.heap.ThreadSafeAllocator, +fallback_allocator: FallbackAllocator, pub fn init(callbacks: ?*const vk.AllocationCallbacks, scope: vk.SystemAllocationScope) Self { const deref_callbacks = if (callbacks) |c| c.* else null; return .{ .callbacks = deref_callbacks, .scope = scope, - .fallback_allocator = .{ .child_allocator = std.heap.c_allocator }, + .fallback_allocator = .{}, }; }