Skip to content

Commit 80acc16

Browse files
jn-jairoOndra Voves
authored andcommitted
1 parent 70b27dc commit 80acc16

8 files changed

Lines changed: 159 additions & 26 deletions

File tree

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ GitHub commit log for a list of recent contributors. We would like to thank
1414
everyone who has contributed to the project in any way.
1515

1616
* __[Sam Loeschen](https://github.com/samloeschen)__
17+
* __[Jairo Correa](https://github.com/jn-jairo)__

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ When [zig](https://codeberg.org/ziglang/zig) meets [bgfx](https://github.com/bka
1414
- [x] Binding for [DebugDraw API](https://github.com/bkaradzic/bgfx/tree/master/examples/common/debugdraw)
1515
- [x] `imgui` render backend. Use build option `imgui_include` to enable. ex. for
1616
zgui: `.imgui_include = zgui.path("libs").getPath(b),`
17-
- [ ] Zig based allocator.
17+
- [x] Zig based allocator.
1818

1919
> [!IMPORTANT]
2020
>

examples/debugdraw/src/main.zig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var last_d = zglfw.Action.release;
2525
var old_flags = bgfx.ResetFlags_None;
2626
var old_size = [2]i32{ WIDTH, HEIGHT };
2727

28-
pub fn main() anyerror!u8 {
28+
pub fn main(init: std.process.Init) anyerror!u8 {
2929
//
3030
// Init zglfw
3131
//
@@ -55,9 +55,8 @@ pub fn main() anyerror!u8 {
5555
bgfx_init.swapChain.ndt = null;
5656
bgfx_init.debug = true;
5757

58-
// TODO: read note in zbgfx.callbacks.ZigAllocator
59-
//bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&_allocator);
60-
//bgfx_init.allocator = &bgfx_alloc;
58+
bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&init.gpa);
59+
bgfx_init.allocator = &bgfx_alloc;
6160

6261
bgfx_init.callback = &bgfx_clbs;
6362

examples/minimal-glfw/src/main.zig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ var last_d = zglfw.Action.release;
8383
var old_flags = bgfx.ResetFlags_None;
8484
var old_size = [2]i32{ WIDTH, HEIGHT };
8585

86-
pub fn main() anyerror!u8 {
86+
pub fn main(init: std.process.Init) anyerror!u8 {
8787
//
8888
// Init zglfw
8989
//
@@ -114,9 +114,8 @@ pub fn main() anyerror!u8 {
114114
bgfx_init.swapChain.ndt = null;
115115
bgfx_init.debug = true;
116116

117-
// TODO: read note in zbgfx.callbacks.ZigAllocator
118-
//bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&_allocator);
119-
//bgfx_init.allocator = &bgfx_alloc;
117+
bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&init.gpa);
118+
bgfx_init.allocator = &bgfx_alloc;
120119

121120
bgfx_init.callback = &bgfx_clbs;
122121

examples/shader-embed/src/main.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,8 @@ pub fn main(init: std.process.Init) anyerror!u8 {
116116
bgfx_init.swapChain.ndt = null;
117117
bgfx_init.debug = true;
118118

119-
// TODO: read note in zbgfx.callbacks.ZigAllocator
120-
//bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&_allocator);
121-
//bgfx_init.allocator = &bgfx_alloc;
119+
bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&init.gpa);
120+
bgfx_init.allocator = &bgfx_alloc;
122121

123122
bgfx_init.callback = &bgfx_clbs;
124123

examples/shader-runtime/src/main.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,8 @@ pub fn main(init: std.process.Init) anyerror!u8 {
166166
bgfx_init.swapChain.ndt = null;
167167
bgfx_init.debug = true;
168168

169-
// TODO: read note in zbgfx.callbacks.ZigAllocator
170-
//bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&_allocator);
171-
//bgfx_init.allocator = &bgfx_alloc;
169+
bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&init.gpa);
170+
bgfx_init.allocator = &bgfx_alloc;
172171

173172
bgfx_init.callback = &bgfx_clbs;
174173

examples/zgui/src/main.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,8 @@ pub fn main(init: std.process.Init) anyerror!u8 {
5959
bgfx_init.swapChain.ndt = null;
6060
bgfx_init.debug = true;
6161

62-
// TODO: read note in zbgfx.callbacks.ZigAllocator
63-
//bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&_allocator);
64-
//bgfx_init.allocator = &bgfx_alloc;
62+
bgfx_alloc = zbgfx.callbacks.ZigAllocator.init(&init.gpa);
63+
bgfx_init.allocator = &bgfx_alloc;
6564

6665
bgfx_init.callback = &bgfx_clbs;
6766

src/callbacks.zig

Lines changed: 145 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const std = @import("std");
2+
const testing = std.testing;
23
const bgfx = @import("bgfx");
34
const builtin = @import("builtin");
45

@@ -8,24 +9,87 @@ const Self = @This();
89

910
//
1011
// Allocator
11-
// FIXME: Does not work because `panic: integer cast truncated bits` from true zig allocator.
1212
//
1313

1414
pub const CAllocInterfaceT = extern struct { vtable: *const CAllocVtblT };
1515
pub const CAllocVtblT = extern struct {
16-
realloc: *const fn (_this: *CAllocInterfaceT, _ptr: [*c]u8, _size: usize, _align: usize, _file: [*:0]const u8, _line: u32) callconv(.c) ?*anyopaque,
16+
realloc: *const fn (_this: *CAllocInterfaceT, _ptr: [*c]u8, _size: usize, _align: usize, _file: [*:0]const u8, _line: u32) callconv(.c) [*c]u8,
1717
};
1818

1919
pub const ZigAllocatorVtbl = extern struct {
20-
fn realloc(_this: *CAllocInterfaceT, _ptr: [*c]u8, _size: usize, _align: usize, _file: [*:0]const u8, _line: u32) callconv(.c) ?*anyopaque {
20+
fn realloc(_this: *CAllocInterfaceT, _ptr: [*c]u8, _size: usize, _align: usize, _file: [*:0]const u8, _line: u32) callconv(.c) [*c]u8 {
2121
var self: *ZigAllocator = @ptrCast(_this);
2222
_ = _file; // autofix
2323
_ = _line; // autofix
2424

25+
const alloc_align = ZigAllocator.getAllocationAlignment(_align);
26+
const alignment = std.mem.Alignment.fromByteUnits(alloc_align);
27+
2528
if (_size != 0) {
26-
return self.allocator.rawAlloc(_size, @truncate(_align), 0);
29+
const alloc_size = ZigAllocator.getAllocationSize(_size, alloc_align);
30+
31+
if (_ptr) |ptr| {
32+
// realloc
33+
34+
const base_ptr = ZigAllocator.getBasePointer(ptr, alloc_align);
35+
var header_ptr = ZigAllocator.getHeaderPointer(base_ptr);
36+
37+
const old_size = header_ptr.size;
38+
const old_mem = base_ptr[0..header_ptr.size];
39+
40+
const new_mem = blk: {
41+
if (self.allocator.rawRemap(old_mem, alignment, alloc_size, @returnAddress())) |mem| {
42+
break :blk mem[0..alloc_size];
43+
}
44+
45+
if (self.allocator.rawAlloc(alloc_size, alignment, @returnAddress())) |mem| {
46+
const copy_size = @min(old_size, alloc_size);
47+
@memcpy(mem[0..copy_size], old_mem[0..copy_size]);
48+
49+
self.allocator.rawFree(old_mem, alignment, @returnAddress());
50+
51+
break :blk mem[0..alloc_size];
52+
}
53+
54+
break :blk null;
55+
};
56+
57+
if (new_mem) |mem| {
58+
header_ptr = ZigAllocator.getHeaderPointer(mem.ptr);
59+
header_ptr.size = alloc_size;
60+
61+
return ZigAllocator.getPayloadPointer(mem.ptr, alloc_align);
62+
}
63+
64+
return null;
65+
} else {
66+
// alloc
67+
68+
const new_mem = if (self.allocator.rawAlloc(alloc_size, alignment, @returnAddress())) |mem| mem[0..alloc_size] else null;
69+
70+
if (new_mem) |mem| {
71+
var header_ptr = ZigAllocator.getHeaderPointer(mem.ptr);
72+
header_ptr.size = alloc_size;
73+
74+
return ZigAllocator.getPayloadPointer(mem.ptr, alloc_align);
75+
}
76+
77+
return null;
78+
}
79+
} else if (_ptr) |ptr| {
80+
// free
81+
82+
const base_ptr = ZigAllocator.getBasePointer(ptr, alloc_align);
83+
const header_ptr = ZigAllocator.getHeaderPointer(base_ptr);
84+
85+
const old_size = header_ptr.size;
86+
const old_mem = base_ptr[0..old_size];
87+
88+
self.allocator.rawFree(old_mem, alignment, @returnAddress());
89+
90+
return null;
2791
}
28-
self.allocator.free(_ptr[0.._size]);
92+
2993
return null;
3094
}
3195
pub fn toVtbl() Self.CAllocVtblT {
@@ -36,13 +100,86 @@ pub const ZigAllocatorVtbl = extern struct {
36100
pub const ZigAllocator = extern struct {
37101
const _alloc_vtable = ZigAllocatorVtbl.toVtbl();
38102
vtable: ?*const CAllocVtblT = null,
39-
allocator: *std.mem.Allocator,
103+
allocator: *const std.mem.Allocator,
40104

41-
pub fn init(alloc: *std.mem.Allocator) ZigAllocator {
42-
return .{ .vtable = &_alloc_vtable, .allocator = alloc };
105+
pub fn init(alloc: *const std.mem.Allocator) ZigAllocator {
106+
return .{
107+
.vtable = &_alloc_vtable,
108+
.allocator = alloc,
109+
};
110+
}
111+
112+
const AllocationHeader = struct {
113+
size: usize,
114+
};
115+
116+
pub fn getAllocationAlignment(_align: usize) usize {
117+
return @max(_align, @alignOf(AllocationHeader));
118+
}
119+
120+
pub fn getAllocationSize(_size: usize, _align: usize) usize {
121+
return _size + @sizeOf(AllocationHeader) + _align - 1;
122+
}
123+
124+
pub fn getPayloadPointer(_ptr: [*c]u8, _align: usize) [*c]u8 {
125+
return std.mem.alignForward(usize, @intFromPtr(_ptr) + @sizeOf(AllocationHeader), _align);
126+
}
127+
128+
pub fn getBasePointer(payload_ptr: [*c]u8, _align: usize) [*c]u8 {
129+
return std.mem.alignBackward(usize, @intFromPtr(payload_ptr) - @sizeOf(AllocationHeader), _align);
130+
}
131+
132+
pub fn getHeaderPointer(_ptr: [*c]u8) *AllocationHeader {
133+
return @ptrCast(@alignCast(_ptr));
43134
}
44135
};
45136

137+
test "zig allocator" {
138+
var zig_alloc = ZigAllocator.init(&testing.allocator);
139+
140+
const realloc = zig_alloc.vtable.?.realloc;
141+
142+
var _align: usize = 64;
143+
144+
var ptr = realloc(@ptrCast(&zig_alloc), null, 100 * 1024, _align, "", 0);
145+
try testing.expect(ptr != null);
146+
ptr[10] = 5;
147+
148+
ptr = realloc(@ptrCast(&zig_alloc), ptr, 200 * 1024, _align, "", 0);
149+
try testing.expect(ptr != null);
150+
try testing.expectEqual(5, ptr[10]);
151+
152+
ptr = realloc(@ptrCast(&zig_alloc), ptr, 50, _align, "", 0);
153+
try testing.expect(ptr != null);
154+
try testing.expectEqual(5, ptr[10]);
155+
156+
ptr = realloc(@ptrCast(&zig_alloc), ptr, 0, _align, "", 0);
157+
try testing.expect(ptr == null);
158+
159+
ptr = realloc(@ptrCast(&zig_alloc), null, 0, _align, "", 0);
160+
try testing.expect(ptr == null);
161+
162+
_align = 0;
163+
164+
ptr = realloc(@ptrCast(&zig_alloc), null, 100 * 1024, _align, "", 0);
165+
try testing.expect(ptr != null);
166+
ptr[10] = 5;
167+
168+
ptr = realloc(@ptrCast(&zig_alloc), ptr, 200 * 1024, _align, "", 0);
169+
try testing.expect(ptr != null);
170+
try testing.expectEqual(5, ptr[10]);
171+
172+
ptr = realloc(@ptrCast(&zig_alloc), ptr, 50, _align, "", 0);
173+
try testing.expect(ptr != null);
174+
try testing.expectEqual(5, ptr[10]);
175+
176+
ptr = realloc(@ptrCast(&zig_alloc), ptr, 0, _align, "", 0);
177+
try testing.expect(ptr == null);
178+
179+
ptr = realloc(@ptrCast(&zig_alloc), null, 0, _align, "", 0);
180+
try testing.expect(ptr == null);
181+
}
182+
46183
//
47184
// Callbacks
48185
//

0 commit comments

Comments
 (0)