From 1f23d290cb0a0f02eab9deb11a95d8c0abb59be9 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Fri, 8 May 2026 16:12:34 +0200 Subject: [PATCH] improving device allocator --- .gitea/workflows/Test.yml | 10 +--- build.zig | 1 + src/soft/SoftDevice.zig | 2 +- src/vulkan/VulkanAllocator.zig | 23 +++------ src/vulkan/fallback_host_allocator.zig | 66 ++++++++++++++++++++++++++ src/vulkan/lib.zig | 1 + 6 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 src/vulkan/fallback_host_allocator.zig diff --git a/.gitea/workflows/Test.yml b/.gitea/workflows/Test.yml index c913f50..8a27b06 100644 --- a/.gitea/workflows/Test.yml +++ b/.gitea/workflows/Test.yml @@ -61,17 +61,9 @@ jobs: which deqp-runner && deqp-runner --version || echo "deqp-runner not found" - name: Run Vulkan CTS - run: zig build cts-soft --release=fast -Ddebug-allocator=true -- -j1 + run: zig build cts-soft --release=fast -- -j3 continue-on-error: true - - name: Upload CTS runner logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: cts-runner-logs - path: | - cts/results.csv - - name: Verify tests run: ls cts | grep "results.csv"; diff --git a/build.zig b/build.zig index 1a076b0..eaddb92 100644 --- a/build.zig +++ b/build.zig @@ -325,6 +325,7 @@ fn addMultithreadedCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *c run.step.dependOn(&impl_lib.step); run.addArg("run"); + run.addArg("--verbose"); run.addArg("--deqp"); run.addArg(cts_exe_path); run.addArg("--caselist"); diff --git a/src/soft/SoftDevice.zig b/src/soft/SoftDevice.zig index 0f7dabb..bef1fa6 100644 --- a/src/soft/SoftDevice.zig +++ b/src/soft/SoftDevice.zig @@ -37,7 +37,7 @@ const SpawnError = std.Thread.SpawnError; const DeviceAllocator = struct { pub inline fn allocator(_: @This()) std.mem.Allocator { - return std.heap.smp_allocator; + return base.fallback_host_allocator; } }; diff --git a/src/vulkan/VulkanAllocator.zig b/src/vulkan/VulkanAllocator.zig index 2a8c1da..2e520df 100644 --- a/src/vulkan/VulkanAllocator.zig +++ b/src/vulkan/VulkanAllocator.zig @@ -4,27 +4,21 @@ const std = @import("std"); const vk = @import("vulkan"); +const fallback_host_allocator = @import("fallback_host_allocator.zig").fallback_host_allocator; + const Allocator = std.mem.Allocator; 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: 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 = .{}, }; } @@ -53,7 +47,6 @@ pub fn cloneWithScope(self: *Self, scope: vk.SystemAllocationScope) Self { return .{ .callbacks = self.callbacks, .scope = scope, - .fallback_allocator = self.fallback_allocator, }; } @@ -69,7 +62,7 @@ fn alloc(context: *anyopaque, len: usize, alignment: Alignment, ret_addr: usize) } } - return self.getFallbackAllocator().rawAlloc(len, alignment, ret_addr); + return fallback_host_allocator.rawAlloc(len, alignment, ret_addr); } fn resize(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool { @@ -77,7 +70,7 @@ fn resize(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, return if (self.callbacks != null) new_len <= ptr.len else - self.getFallbackAllocator().rawResize(ptr, alignment, new_len, ret_addr); + fallback_host_allocator.rawResize(ptr, alignment, new_len, ret_addr); } fn remap(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { @@ -87,7 +80,7 @@ fn remap(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, r return @ptrCast(pfn_reallocation(self.callbacks.?.p_user_data, ptr.ptr, new_len, alignment.toByteUnits(), self.scope)); } } - return self.getFallbackAllocator().rawRemap(ptr, alignment, new_len, ret_addr); + return fallback_host_allocator.rawRemap(ptr, alignment, new_len, ret_addr); } fn free(context: *anyopaque, ptr: []u8, alignment: Alignment, ret_addr: usize) void { @@ -98,9 +91,5 @@ fn free(context: *anyopaque, ptr: []u8, alignment: Alignment, ret_addr: usize) v return; } } - self.getFallbackAllocator().rawFree(ptr, alignment, ret_addr); -} - -inline fn getFallbackAllocator(self: *Self) std.mem.Allocator { - return self.fallback_allocator.allocator(); + fallback_host_allocator.rawFree(ptr, alignment, ret_addr); } diff --git a/src/vulkan/fallback_host_allocator.zig b/src/vulkan/fallback_host_allocator.zig new file mode 100644 index 0000000..deb7df5 --- /dev/null +++ b/src/vulkan/fallback_host_allocator.zig @@ -0,0 +1,66 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +const Allocator = std.mem.Allocator; +const Alignment = std.mem.Alignment; + +/// Atomic based spin mutex +const AtomicMutex = struct { + mutex: std.atomic.Mutex = .unlocked, + + fn lock(self: *@This()) void { + if (self.mutex.tryLock()) { + @branchHint(.likely); + return; + } + + while (true) { + if (self.mutex.tryLock()) { + return; + } + } + } + + fn unlock(self: *@This()) void { + self.mutex.unlock(); + } +}; + +var mutex: AtomicMutex = .{}; +var child_allocator: std.mem.Allocator = if (builtin.link_libc) std.heap.c_allocator else std.heap.smp_allocator; + +pub const fallback_host_allocator: Allocator = .{ + .ptr = undefined, + .vtable = &vtable, +}; + +const vtable: Allocator.VTable = .{ + .alloc = alloc, + .resize = resize, + .remap = remap, + .free = free, +}; + +fn alloc(_: *anyopaque, len: usize, alignment: Alignment, ret_addr: usize) ?[*]u8 { + mutex.lock(); + defer mutex.unlock(); + return child_allocator.rawAlloc(len, alignment, ret_addr); +} + +fn resize(_: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool { + mutex.lock(); + defer mutex.unlock(); + return child_allocator.rawResize(ptr, alignment, new_len, ret_addr); +} + +fn remap(_: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { + mutex.lock(); + defer mutex.unlock(); + return child_allocator.rawRemap(ptr, alignment, new_len, ret_addr); +} + +fn free(_: *anyopaque, ptr: []u8, alignment: Alignment, ret_addr: usize) void { + mutex.lock(); + defer mutex.unlock(); + return child_allocator.rawFree(ptr, alignment, ret_addr); +} diff --git a/src/vulkan/lib.zig b/src/vulkan/lib.zig index 51f4434..f03dc84 100644 --- a/src/vulkan/lib.zig +++ b/src/vulkan/lib.zig @@ -14,6 +14,7 @@ pub const format = @import("format.zig"); pub const config = @import("config"); pub const Dispatchable = @import("Dispatchable.zig").Dispatchable; +pub const fallback_host_allocator = @import("fallback_host_allocator.zig").fallback_host_allocator; pub const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable; pub const VkError = errors.VkError; pub const VulkanAllocator = @import("VulkanAllocator.zig");