Skip to content

Commit 48cf53b

Browse files
committed
Fixing up leaks in the passes and sprite animation example
1 parent 2bece9c commit 48cf53b

6 files changed

Lines changed: 61 additions & 13 deletions

File tree

src/examples/lua.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ pub fn main() !void {
1717
// See https://github.com/ziglang/zig/issues/19072
1818
try delve.init(std.heap.c_allocator);
1919
} else {
20-
try delve.init(gpa.allocator());
20+
// Using the default allocator will let us detect memory leaks
21+
try delve.init(delve.mem.createDefaultAllocator());
2122
}
2223

2324
try lua_module.registerModule();

src/examples/meshbuilder.zig

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ pub fn main() !void {
2525
// See https://github.com/ziglang/zig/issues/19072
2626
try delve.init(std.heap.c_allocator);
2727
} else {
28-
try delve.init(gpa.allocator());
28+
// Using the default allocator will let us detect memory leaks
29+
try delve.init(delve.mem.createDefaultAllocator());
2930
}
3031

3132
const example = delve.modules.Module{
3233
.name = "meshbuilder_example",
3334
.init_fn = on_init,
3435
.tick_fn = on_tick,
3536
.draw_fn = on_draw,
37+
.cleanup_fn = on_cleanup,
3638
};
3739

3840
try delve.modules.registerModule(example);
@@ -53,7 +55,8 @@ pub fn on_init() !void {
5355

5456
// Create a material out of the texture
5557
material = try graphics.Material.init(.{
56-
.shader = shader,
58+
.shader = shader.?,
59+
.own_shader = true,
5760
.texture_0 = tex,
5861
.samplers = &[_]graphics.FilterMode{.NEAREST},
5962
});
@@ -108,3 +111,7 @@ pub fn on_draw() void {
108111
cube2.draw(view_mats, model);
109112
cube3.draw(view_mats, model);
110113
}
114+
115+
pub fn on_cleanup() !void {
116+
material.deinit();
117+
}

src/examples/passes.zig

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
1616
var camera: delve.graphics.camera.Camera = undefined;
1717
var camera_offscreen: delve.graphics.camera.Camera = undefined;
1818

19+
var shader: delve.platform.graphics.Shader = undefined;
1920
var material1: graphics.Material = undefined;
2021
var material2: graphics.Material = undefined;
2122
var material3: graphics.Material = undefined;
@@ -36,6 +37,7 @@ pub fn main() !void {
3637
.tick_fn = on_tick,
3738
.pre_draw_fn = pre_draw,
3839
.draw_fn = on_draw,
40+
.cleanup_fn = on_cleanup,
3941
};
4042

4143
// Pick the allocator to use depending on platform
@@ -45,7 +47,8 @@ pub fn main() !void {
4547
// See https://github.com/ziglang/zig/issues/19072
4648
try delve.init(std.heap.c_allocator);
4749
} else {
48-
try delve.init(gpa.allocator());
50+
// Using the default allocator will let us detect memory leaks
51+
try delve.init(delve.mem.createDefaultAllocator());
4952
}
5053

5154
try delve.modules.registerModule(example);
@@ -66,24 +69,24 @@ pub fn on_init() !void {
6669
offscreen_pass = graphics.RenderPass.init(.{ .width = 1024, .height = 768 });
6770
offscreen_pass_2 = graphics.RenderPass.init(.{ .width = 640, .height = 480 });
6871

69-
const shader = delve.platform.graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh);
72+
shader = delve.platform.graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh).?;
7073

7174
// Create a material out of the texture
72-
material1 = graphics.Material.init(.{
75+
material1 = try graphics.Material.init(.{
7376
.shader = shader,
7477
.texture_0 = tex,
7578
.samplers = &[_]graphics.FilterMode{.NEAREST},
7679
});
7780

7881
// Create a material that uses our main offscreen render texture
79-
material2 = graphics.Material.init(.{
82+
material2 = try graphics.Material.init(.{
8083
.shader = shader,
8184
.texture_0 = offscreen_pass.render_texture_color,
8285
.samplers = &[_]graphics.FilterMode{.NEAREST},
8386
});
8487

8588
// Create a material that uses our secondary offscreen render texture
86-
material3 = graphics.Material.init(.{
89+
material3 = try graphics.Material.init(.{
8790
.shader = shader,
8891
.texture_0 = offscreen_pass_2.render_texture_color,
8992
.samplers = &[_]graphics.FilterMode{.NEAREST},
@@ -100,19 +103,19 @@ pub fn on_init() !void {
100103
const flip_mod: math.Vec3 = if (!is_opengl) math.Vec3.new(1, 1, 1) else math.Vec3.new(1, -1, 1);
101104

102105
// make a cube
103-
cube1 = delve.graphics.mesh.createCube(math.Vec3.new(0, 0, 0), math.Vec3.new(2, 3, 1), delve.colors.white, &material1) catch {
106+
cube1 = delve.graphics.mesh.createCube(math.Vec3.new(0, 0, 0), math.Vec3.new(2, 3, 1), delve.colors.white, material1) catch {
104107
delve.debug.log("Could not create cube!", .{});
105108
return;
106109
};
107110

108111
// and another
109-
cube2 = delve.graphics.mesh.createCube(math.Vec3.new(3, 0, -1), math.Vec3.new(1, 1, 2).mul(flip_mod), delve.colors.white, &material3) catch {
112+
cube2 = delve.graphics.mesh.createCube(math.Vec3.new(3, 0, -1), math.Vec3.new(1, 1, 2).mul(flip_mod), delve.colors.white, material3) catch {
110113
delve.debug.log("Could not create cube!", .{});
111114
return;
112115
};
113116

114117
// and then a screen
115-
cube3 = delve.graphics.mesh.createCube(math.Vec3.new(0, 0, 0), math.Vec3.new(20, 12.0, 0.25).mul(flip_mod), delve.colors.white, &material2) catch {
118+
cube3 = delve.graphics.mesh.createCube(math.Vec3.new(0, 0, 0), math.Vec3.new(20, 12.0, 0.25).mul(flip_mod), delve.colors.white, material2) catch {
116119
delve.debug.log("Could not create cube!", .{});
117120
return;
118121
};
@@ -183,3 +186,17 @@ pub fn on_draw() void {
183186
// reset the clear color back to ours
184187
graphics.setClearColor(delve.colors.examples_bg_dark);
185188
}
189+
190+
pub fn on_cleanup() !void {
191+
shader.destroy();
192+
material1.deinit();
193+
material2.deinit();
194+
material3.deinit();
195+
cube1.deinit();
196+
cube2.deinit();
197+
cube3.deinit();
198+
199+
// cleanup the nested examples too
200+
if (nested_example_1.cleanup_fn) |cleanup_fn| try cleanup_fn();
201+
if (nested_example_2.cleanup_fn) |cleanup_fn| try cleanup_fn();
202+
}

src/examples/sprite-animation.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ pub fn main() !void {
3434
// See https://github.com/ziglang/zig/issues/19072
3535
try delve.init(std.heap.c_allocator);
3636
} else {
37-
try delve.init(gpa.allocator());
37+
// Using the default allocator will let us detect memory leaks
38+
try delve.init(delve.mem.createDefaultAllocator());
3839
}
3940

4041
try registerModule();
@@ -136,6 +137,7 @@ fn on_cleanup() !void {
136137
delve.debug.log("Sprite animation example module cleaning up", .{});
137138
sprite_texture.destroy();
138139
sprite_batch.deinit();
140+
sprite_sheet.deinit();
139141
test_material.deinit();
140142
shader_default.destroy();
141143
}

src/framework/graphics/sprites.zig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ pub const AnimatedSpriteSheet = struct {
7171
};
7272
}
7373

74+
pub fn deinit(self: *AnimatedSpriteSheet) void {
75+
// Cleanup SpriteAnimation entries
76+
var it = self.entries.valueIterator();
77+
while (it.next()) |sprite_anim_ptr| {
78+
self.allocator.free(sprite_anim_ptr.frames);
79+
}
80+
81+
// Also cleanup the key names that we allocated
82+
var key_it = self.entries.keyIterator();
83+
while (key_it.next()) |key_ptr| {
84+
self.allocator.free(key_ptr.*);
85+
}
86+
87+
self.entries.deinit();
88+
}
89+
7490
/// Play the animation under the given animation name
7591
pub fn playAnimation(self: *AnimatedSpriteSheet, animation_name: [:0]const u8) ?PlayingAnimation {
7692
const entry = self.getAnimation(animation_name);

src/framework/platform/graphics.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ pub const MaterialConfig = struct {
631631

632632
// The parent shader to base us on
633633
shader: ?Shader = null,
634+
own_shader: bool = false, // whether to own our shader, or to make a new instance of it
634635

635636
// The layouts of the default (0th) vertex and fragment shaders
636637
default_vs_uniform_layout: []const MaterialUniformDefaults = default_vs_uniforms,
@@ -880,7 +881,11 @@ pub const Material = struct {
880881
shader_config.depth_write_enabled = cfg.depth_write_enabled;
881882
shader_config.depth_compare = cfg.depth_compare;
882883

883-
material.state.shader = Shader.makeNewInstance(shader_config, cfg.shader);
884+
if (cfg.shader != null and cfg.own_shader) {
885+
material.state.shader = cfg.shader.?;
886+
} else {
887+
material.state.shader = Shader.makeNewInstance(shader_config, cfg.shader);
888+
}
884889

885890
return material;
886891
}

0 commit comments

Comments
 (0)