fix memory leaks :)
This commit is contained in:
parent
f42d2be83a
commit
8c7e341832
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ zig-cache
|
|||||||
zig-out
|
zig-out
|
||||||
*.blend1
|
*.blend1
|
||||||
src/assets/models/emulator.glb
|
src/assets/models/emulator.glb
|
||||||
|
valgrind-log.txt
|
||||||
|
9
run-valgrind.sh
Executable file
9
run-valgrind.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
zig build
|
||||||
|
valgrind --leak-check=full --num-callers=30 --log-file=valgrind-log.txt \
|
||||||
|
--suppressions=valgrind-suppresions/opengl_nvidia2.supp \
|
||||||
|
--suppressions=valgrind-suppresions/opengl_nvidia1.supp \
|
||||||
|
--suppressions=valgrind-suppresions/raylib_InitWindow.supp \
|
||||||
|
./zig-out/bin/chip8-zig
|
@ -12,8 +12,9 @@ allocator: Allocator,
|
|||||||
materials: []rl.Material,
|
materials: []rl.Material,
|
||||||
|
|
||||||
models: std.ArrayList(rl.Model),
|
models: std.ArrayList(rl.Model),
|
||||||
buttons: [16]rl.Model,
|
static_models: std.ArrayList(*rl.Model),
|
||||||
power_switch: rl.Model,
|
buttons: [16]*rl.Model,
|
||||||
|
power_switch: *rl.Model,
|
||||||
|
|
||||||
bbox: rl.BoundingBox,
|
bbox: rl.BoundingBox,
|
||||||
position: rl.Vector3,
|
position: rl.Vector3,
|
||||||
@ -31,7 +32,7 @@ fn getExtensionByMimeType(mime_type: []const u8) ?[:0]const u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadGltfImage(image: Gltf.Image) rl.Image {
|
fn loadGltfImage(image: Gltf.Image) !rl.Image {
|
||||||
assert(image.uri == null);
|
assert(image.uri == null);
|
||||||
assert(image.data != null);
|
assert(image.data != null);
|
||||||
assert(image.mime_type != null);
|
assert(image.mime_type != null);
|
||||||
@ -42,18 +43,23 @@ fn loadGltfImage(image: Gltf.Image) rl.Image {
|
|||||||
const file_type = getExtensionByMimeType(mime_type);
|
const file_type = getExtensionByMimeType(mime_type);
|
||||||
assert(file_type != null);
|
assert(file_type != null);
|
||||||
|
|
||||||
return rl.LoadImageFromMemory(file_type.?, @ptrCast(image_data.ptr), @intCast(image_data.len));
|
const rl_image = rl.LoadImageFromMemory(file_type.?, @ptrCast(image_data.ptr), @intCast(image_data.len));
|
||||||
|
if (@as(?*anyopaque, @ptrCast(rl_image.data)) == null) {
|
||||||
|
return error.Failed;
|
||||||
|
}
|
||||||
|
return rl_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadGltfMaterial(data: Gltf.Data, material: Gltf.Material) !rl.Material {
|
fn loadGltfMaterial(data: Gltf.Data, material: Gltf.Material) !rl.Material {
|
||||||
var rl_material = rl.LoadMaterialDefault();
|
var rl_material = rl.LoadMaterialDefault();
|
||||||
var albedo_map: *rl.MaterialMap = &rl_material.maps.?[@intFromEnum(rl.MaterialMapIndex.MATERIAL_MAP_ALBEDO)];
|
errdefer rl.UnloadMaterial(rl_material);
|
||||||
|
|
||||||
|
var albedo_map: *rl.MaterialMap = &rl_material.maps.?[@intFromEnum(rl.MaterialMapIndex.MATERIAL_MAP_ALBEDO)];
|
||||||
if (material.metallic_roughness.base_color_texture) |base_color_texture| {
|
if (material.metallic_roughness.base_color_texture) |base_color_texture| {
|
||||||
const texture = data.textures.items[base_color_texture.index];
|
const texture = data.textures.items[base_color_texture.index];
|
||||||
const image = data.images.items[texture.source.?];
|
const image = data.images.items[texture.source.?];
|
||||||
|
|
||||||
const rl_image = loadGltfImage(image);
|
const rl_image = try loadGltfImage(image);
|
||||||
defer rl.UnloadImage(rl_image);
|
defer rl.UnloadImage(rl_image);
|
||||||
albedo_map.texture = rl.LoadTextureFromImage(rl_image);
|
albedo_map.texture = rl.LoadTextureFromImage(rl_image);
|
||||||
}
|
}
|
||||||
@ -66,9 +72,12 @@ fn loadGltfMaterial(data: Gltf.Data, material: Gltf.Material) !rl.Material {
|
|||||||
return rl_material;
|
return rl_material;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadGltfPrimitive(allocator: Allocator, gltf: Gltf, primitive: Gltf.Primitive) !rl.Mesh {
|
fn loadGltfPrimitive(gltf: Gltf, primitive: Gltf.Primitive) !rl.Mesh {
|
||||||
|
var allocator = std.heap.c_allocator;
|
||||||
|
|
||||||
assert(primitive.mode == .triangles);
|
assert(primitive.mode == .triangles);
|
||||||
var rl_mesh = std.mem.zeroes(rl.Mesh);
|
var rl_mesh = std.mem.zeroes(rl.Mesh);
|
||||||
|
errdefer rl.UnloadMesh(rl_mesh);
|
||||||
|
|
||||||
var bin = gltf.glb_binary.?;
|
var bin = gltf.glb_binary.?;
|
||||||
var f32_buffer = std.ArrayList(f32).init(allocator);
|
var f32_buffer = std.ArrayList(f32).init(allocator);
|
||||||
@ -155,6 +164,85 @@ fn loadGltfPrimitive(allocator: Allocator, gltf: Gltf, primitive: Gltf.Primitive
|
|||||||
return rl_mesh;
|
return rl_mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn loadGltfMesh(materials: []rl.Material, gltf: Gltf, node: Gltf.Node) !rl.Model {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
const transform = Gltf.getGlobalTransform(&gltf.data, node);
|
||||||
|
|
||||||
|
var model = std.mem.zeroes(rl.Model);
|
||||||
|
errdefer rl.UnloadModel(model);
|
||||||
|
|
||||||
|
model.transform = rl.Matrix{
|
||||||
|
.m0 = transform[0][0],
|
||||||
|
.m4 = transform[1][0],
|
||||||
|
.m8 = transform[2][0],
|
||||||
|
.m12 = transform[3][0],
|
||||||
|
|
||||||
|
.m1 = transform[0][1],
|
||||||
|
.m5 = transform[1][1],
|
||||||
|
.m9 = transform[2][1],
|
||||||
|
.m13 = transform[3][1],
|
||||||
|
|
||||||
|
.m2 = transform[0][2],
|
||||||
|
.m6 = transform[1][2],
|
||||||
|
.m10 = transform[2][2],
|
||||||
|
.m14 = transform[3][2],
|
||||||
|
|
||||||
|
.m3 = transform[0][3],
|
||||||
|
.m7 = transform[1][3],
|
||||||
|
.m11 = transform[2][3],
|
||||||
|
.m15 = transform[3][3]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (node.mesh) |mesh_idx| {
|
||||||
|
const mesh = gltf.data.meshes.items[mesh_idx];
|
||||||
|
const primitives: []Gltf.Primitive = mesh.primitives.items;
|
||||||
|
|
||||||
|
var meshes = try allocator.alloc(rl.Mesh, primitives.len);
|
||||||
|
model.meshCount = @intCast(primitives.len);
|
||||||
|
model.meshes = @ptrCast(meshes.ptr);
|
||||||
|
|
||||||
|
var mesh_material = try allocator.alloc(i32, primitives.len);
|
||||||
|
model.meshMaterial = @ptrCast(mesh_material.ptr);
|
||||||
|
@memset(mesh_material, 0);
|
||||||
|
|
||||||
|
var used_material_ids = try allocator.alloc(usize, materials.len);
|
||||||
|
var used_materials_count: usize = 0;
|
||||||
|
defer allocator.free(used_material_ids);
|
||||||
|
|
||||||
|
for (0.., primitives) |j, primitive| {
|
||||||
|
meshes[j] = try loadGltfPrimitive(gltf, primitive);
|
||||||
|
|
||||||
|
var mtl: usize = 0;
|
||||||
|
if (primitive.material) |material| {
|
||||||
|
mtl = material + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mtl_index = std.mem.indexOfScalar(usize, used_material_ids[0..used_materials_count], mtl);
|
||||||
|
if (mtl_index == null) {
|
||||||
|
mtl_index = used_materials_count;
|
||||||
|
used_material_ids[used_materials_count] = mtl;
|
||||||
|
used_materials_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh_material[j] = @intCast(mtl_index.?);
|
||||||
|
}
|
||||||
|
|
||||||
|
var used_materials = try allocator.alloc(rl.Material, used_materials_count+1);
|
||||||
|
model.materials = @ptrCast(used_materials);
|
||||||
|
model.materialCount = 0;
|
||||||
|
for (0..used_materials_count) |i| {
|
||||||
|
used_materials[i] = materials[used_material_ids[i]];
|
||||||
|
|
||||||
|
const max_material_maps = 12;
|
||||||
|
const maps = try allocator.dupe(rl.MaterialMap, used_materials[i].maps.?[0..max_material_maps]);
|
||||||
|
used_materials[i].maps = @ptrCast(maps);
|
||||||
|
model.materialCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, rl_chip: *const RaylibChip) !Self {
|
pub fn init(allocator: Allocator, rl_chip: *const RaylibChip) !Self {
|
||||||
var gltf = Gltf.init(allocator);
|
var gltf = Gltf.init(allocator);
|
||||||
defer gltf.deinit();
|
defer gltf.deinit();
|
||||||
@ -164,68 +252,41 @@ pub fn init(allocator: Allocator, rl_chip: *const RaylibChip) !Self {
|
|||||||
const scene_nodes: std.ArrayList(Gltf.Index) = scene.nodes.?;
|
const scene_nodes: std.ArrayList(Gltf.Index) = scene.nodes.?;
|
||||||
|
|
||||||
const material_count: usize = @intCast(gltf.data.materials.items.len);
|
const material_count: usize = @intCast(gltf.data.materials.items.len);
|
||||||
var materials = try allocator.alloc(rl.Material, material_count + 1);
|
var materials = try allocator.alloc(rl.Material, material_count+1);
|
||||||
|
@memset(materials, std.mem.zeroes(rl.Material));
|
||||||
|
errdefer allocator.free(materials);
|
||||||
|
|
||||||
materials[0] = rl.LoadMaterialDefault();
|
materials[0] = rl.LoadMaterialDefault();
|
||||||
|
errdefer {
|
||||||
|
for (materials) |mtl| {
|
||||||
|
rl.UnloadMaterial(mtl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (0..material_count, gltf.data.materials.items) |i, material| {
|
for (0..material_count, gltf.data.materials.items) |i, material| {
|
||||||
materials[i+1] = try loadGltfMaterial(gltf.data, material);
|
materials[i+1] = try loadGltfMaterial(gltf.data, material);
|
||||||
}
|
}
|
||||||
|
|
||||||
const screen_texture = rl.LoadRenderTexture(rl_chip.chip.display_width, rl_chip.chip.display_height);
|
|
||||||
|
|
||||||
var models = try std.ArrayList(rl.Model).initCapacity(allocator, scene_nodes.items.len);
|
var models = try std.ArrayList(rl.Model).initCapacity(allocator, scene_nodes.items.len);
|
||||||
errdefer models.deinit();
|
errdefer models.deinit();
|
||||||
|
errdefer {
|
||||||
|
for (models.items) |model| {
|
||||||
|
rl.UnloadModel(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var buttons: [16]rl.Model = undefined;
|
var static_models = std.ArrayList(*rl.Model).init(allocator);
|
||||||
var power_switch: rl.Model = undefined;
|
errdefer static_models.deinit();
|
||||||
|
|
||||||
|
var buttons: [16]*rl.Model = undefined;
|
||||||
|
var power_switch: *rl.Model = undefined;
|
||||||
|
|
||||||
for (scene_nodes.items) |node_index| {
|
for (scene_nodes.items) |node_index| {
|
||||||
const node = gltf.data.nodes.items[node_index];
|
const node = gltf.data.nodes.items[node_index];
|
||||||
if (node.mesh == null) continue;
|
if (node.mesh == null) continue;
|
||||||
|
|
||||||
const transform = Gltf.getGlobalTransform(&gltf.data, node);
|
models.appendAssumeCapacity(try loadGltfMesh(materials, gltf, node));
|
||||||
|
const model = &models.items[models.items.len-1];
|
||||||
var model = std.mem.zeroes(rl.Model);
|
|
||||||
model.transform = rl.Matrix{
|
|
||||||
.m0 = transform[0][0],
|
|
||||||
.m4 = transform[1][0],
|
|
||||||
.m8 = transform[2][0],
|
|
||||||
.m12 = transform[3][0],
|
|
||||||
|
|
||||||
.m1 = transform[0][1],
|
|
||||||
.m5 = transform[1][1],
|
|
||||||
.m9 = transform[2][1],
|
|
||||||
.m13 = transform[3][1],
|
|
||||||
|
|
||||||
.m2 = transform[0][2],
|
|
||||||
.m6 = transform[1][2],
|
|
||||||
.m10 = transform[2][2],
|
|
||||||
.m14 = transform[3][2],
|
|
||||||
|
|
||||||
.m3 = transform[0][3],
|
|
||||||
.m7 = transform[1][3],
|
|
||||||
.m11 = transform[2][3],
|
|
||||||
.m15 = transform[3][3]
|
|
||||||
};
|
|
||||||
model.materials = @ptrCast(materials.ptr);
|
|
||||||
model.materialCount = @intCast(materials.len);
|
|
||||||
|
|
||||||
const mesh = gltf.data.meshes.items[node.mesh.?];
|
|
||||||
const primitives: []Gltf.Primitive = mesh.primitives.items;
|
|
||||||
|
|
||||||
var meshes = try allocator.alloc(rl.Mesh, primitives.len);
|
|
||||||
var mesh_material = try allocator.alloc(i32, primitives.len);
|
|
||||||
model.meshes = @ptrCast(meshes.ptr);
|
|
||||||
model.meshCount = @intCast(primitives.len);
|
|
||||||
model.meshMaterial = @ptrCast(mesh_material.ptr);
|
|
||||||
@memset(mesh_material, 0);
|
|
||||||
|
|
||||||
for (0.., primitives) |j, primitive| {
|
|
||||||
meshes[j] = try loadGltfPrimitive(allocator, gltf, primitive);
|
|
||||||
|
|
||||||
if (primitive.material) |mtl| {
|
|
||||||
mesh_material[j] = @intCast(mtl+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std.mem.eql(u8, node.name, "Power switch")) {
|
if (std.mem.eql(u8, node.name, "Power switch")) {
|
||||||
power_switch = model;
|
power_switch = model;
|
||||||
@ -234,10 +295,13 @@ pub fn init(allocator: Allocator, rl_chip: *const RaylibChip) !Self {
|
|||||||
const button_idx = try std.fmt.parseInt(usize, node.name[space+1..], 16);
|
const button_idx = try std.fmt.parseInt(usize, node.name[space+1..], 16);
|
||||||
buttons[button_idx] = model;
|
buttons[button_idx] = model;
|
||||||
} else {
|
} else {
|
||||||
models.appendAssumeCapacity(model);
|
try static_models.append(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const screen_texture = rl.LoadRenderTexture(rl_chip.chip.display_width, rl_chip.chip.display_height);
|
||||||
|
errdefer rl.UnloadRenderTexture(screen_texture);
|
||||||
|
|
||||||
{ // Link screen render target to shader
|
{ // Link screen render target to shader
|
||||||
var screen_mtl_idx: ?usize = null;
|
var screen_mtl_idx: ?usize = null;
|
||||||
for (1.., gltf.data.materials.items) |idx, mtl| {
|
for (1.., gltf.data.materials.items) |idx, mtl| {
|
||||||
@ -251,13 +315,15 @@ pub fn init(allocator: Allocator, rl_chip: *const RaylibChip) !Self {
|
|||||||
|
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
|
|
||||||
.materials = materials,
|
.materials = materials,
|
||||||
|
|
||||||
|
.static_models = static_models,
|
||||||
.models = models,
|
.models = models,
|
||||||
.buttons = buttons,
|
.buttons = buttons,
|
||||||
.power_switch = power_switch,
|
.power_switch = power_switch,
|
||||||
|
|
||||||
.bbox = rl.GetModelBoundingBox(models.items[0]),
|
.bbox = rl.GetModelBoundingBox(static_models.items[0].*),
|
||||||
.screen_texture = screen_texture,
|
.screen_texture = screen_texture,
|
||||||
.position = rl.Vector3{ .x = 0, .y = 0, .z = 0 },
|
.position = rl.Vector3{ .x = 0, .y = 0, .z = 0 },
|
||||||
.rl_chip = rl_chip,
|
.rl_chip = rl_chip,
|
||||||
@ -265,18 +331,25 @@ pub fn init(allocator: Allocator, rl_chip: *const RaylibChip) !Self {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn setShader(self: *Self, shader: rl.Shader) void {
|
pub fn setShader(self: *Self, shader: rl.Shader) void {
|
||||||
for (self.materials) |*mtl| {
|
for (self.models.items) |*model| {
|
||||||
mtl.shader = shader;
|
if (model.materials == null) continue;
|
||||||
|
|
||||||
|
for (0..@intCast(model.materialCount)) |i| {
|
||||||
|
model.materials.?[i].shader = shader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
|
for (self.models.items) |model| {
|
||||||
|
rl.UnloadModel(model);
|
||||||
|
}
|
||||||
|
for (self.materials) |mtl| {
|
||||||
|
rl.UnloadMaterial(mtl);
|
||||||
|
}
|
||||||
self.allocator.free(self.materials);
|
self.allocator.free(self.materials);
|
||||||
|
self.static_models.deinit();
|
||||||
// rl.UnloadModel(self.static_model);
|
self.models.deinit();
|
||||||
// for (self.button_models) |btn_model| {
|
|
||||||
// rl.UnloadModel(btn_model);
|
|
||||||
// }
|
|
||||||
rl.UnloadRenderTexture(self.screen_texture);
|
rl.UnloadRenderTexture(self.screen_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,12 +381,12 @@ pub fn draw(self: *Self) void {
|
|||||||
if (self.rl_chip.chip.is_input_pressed(@intCast(i))) {
|
if (self.rl_chip.chip.is_input_pressed(@intCast(i))) {
|
||||||
position.z += 0.035;
|
position.z += 0.035;
|
||||||
}
|
}
|
||||||
rl.DrawModel(button, position, 1.0, rl.WHITE);
|
rl.DrawModel(button.*, position, 1.0, rl.WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (self.models.items) |model| {
|
for (self.static_models.items) |model| {
|
||||||
rl.DrawModel(model, self.position, 1.0, rl.WHITE);
|
rl.DrawModel(model.*, self.position, 1.0, rl.WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.DrawModel(self.power_switch, self.position, 1.0, rl.WHITE);
|
rl.DrawModel(self.power_switch.*, self.position, 1.0, rl.WHITE);
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,7 @@ pub fn init(allocator: Allocator, ctx: *GlobalContext) !Self {
|
|||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
self.emulator.deinit();
|
self.emulator.deinit();
|
||||||
|
rl.UnloadShader(self.shader);
|
||||||
rl.UnloadSound(self.chip_sound);
|
rl.UnloadSound(self.chip_sound);
|
||||||
self.chip.deinit();
|
self.chip.deinit();
|
||||||
self.allocator.destroy(self.raylib_chip);
|
self.allocator.destroy(self.raylib_chip);
|
||||||
|
@ -22,7 +22,7 @@ pub fn main() anyerror!void {
|
|||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
defer {
|
defer {
|
||||||
// if (gpa.deinit() == .leak) @panic("Leaked memory");
|
if (gpa.deinit() == .leak) @panic("Leaked memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.SetConfigFlags(rl.ConfigFlags{ .FLAG_WINDOW_RESIZABLE = true });
|
rl.SetConfigFlags(rl.ConfigFlags{ .FLAG_WINDOW_RESIZABLE = true });
|
||||||
@ -73,6 +73,5 @@ pub fn main() anyerror!void {
|
|||||||
rl.EndMode3D();
|
rl.EndMode3D();
|
||||||
}
|
}
|
||||||
rl.EndDrawing();
|
rl.EndDrawing();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
valgrind-suppresions/opengl_nvidia1.supp
Normal file
7
valgrind-suppresions/opengl_nvidia1.supp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
nvidia_realloc_zero
|
||||||
|
Memcheck:ReallocZero
|
||||||
|
fun:realloc
|
||||||
|
...
|
||||||
|
obj:/usr/lib/libGLX_nvidia.so.*
|
||||||
|
}
|
7
valgrind-suppresions/opengl_nvidia2.supp
Normal file
7
valgrind-suppresions/opengl_nvidia2.supp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
nvidia_bad_size
|
||||||
|
Memcheck:BadSize
|
||||||
|
fun:posix_memalign
|
||||||
|
...
|
||||||
|
obj:/usr/lib/libGLX_nvidia.so.*
|
||||||
|
}
|
8
valgrind-suppresions/raylib_InitWindow.supp
Normal file
8
valgrind-suppresions/raylib_InitWindow.supp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
raylib_InitWindow
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:InitWindow
|
||||||
|
...
|
||||||
|
fun:main
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user