diff --git a/assets/bistro.glb b/assets/bistro.glb new file mode 100644 index 0000000..f49154f --- /dev/null +++ b/assets/bistro.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4cc5e42450cd88527529ba80fc6fd60ceb26b93adb71eb8a6a2adba20ced2f5e +size 1306880024 diff --git a/assets/shaders/mesh.glsl b/assets/shaders/mesh.glsl index a636f97..7a6bb9b 100644 --- a/assets/shaders/mesh.glsl +++ b/assets/shaders/mesh.glsl @@ -154,7 +154,7 @@ EvalMaterial evalMaterial() { result.albedo = textureSize(materials[materialIdx].albedo_map, 0) == ivec2(0) ? vec4(pow(materials[materialIdx].albedo.rgb, vec3(2.2)), materials[materialIdx].albedo.a) : texture(materials[materialIdx].albedo_map, VertexOut.uv * materials[materialIdx].albedo_map_uv_scale); float fMetallic = textureSize(materials[materialIdx].metallic_map, 0) == ivec2(0) ? materials[materialIdx].metallic : texture(materials[materialIdx].metallic_map, VertexOut.uv * materials[materialIdx].metallic_map_uv_scale).b; result.metallic = fMetallic > 0.1; - result.roughness = max(1.0, textureSize(materials[materialIdx].roughness_map, 0) == ivec2(0) ? materials[materialIdx].roughness : texture(materials[materialIdx].roughness_map, VertexOut.uv * materials[materialIdx].roughness_map_uv_scale).g); + result.roughness = max(0.01, textureSize(materials[materialIdx].roughness_map, 0) == ivec2(0) ? materials[materialIdx].roughness : texture(materials[materialIdx].roughness_map, VertexOut.uv * materials[materialIdx].roughness_map_uv_scale).g); result.emission = textureSize(materials[materialIdx].emission_map, 0) == ivec2(0) ? materials[materialIdx].emission : texture(materials[materialIdx].emission_map, VertexOut.uv * materials[materialIdx].emission_map_uv_scale).rgb; return result; @@ -169,7 +169,7 @@ vec3 schlickFresnel(EvalMaterial mat, float LDotH) { return f0 + (1 - f0) * pow(1.0 - LDotH, 5); } -const float eps = 0.0000001; +const float eps = 0.0001; float geomSmith(EvalMaterial mat, float DotVal) { float k = (mat.roughness + 1.0) * (mat.roughness + 1.0) / 8.0; @@ -299,7 +299,7 @@ vec3 microfacetModel(EvalMaterial mat, int light_idx, vec3 P, vec3 N) { shadow_mult = sum / 16.0; } - shadow_mult = clamp(shadow_mult, 0.2, 1.0); + shadow_mult = clamp(shadow_mult, 0.3, 1.0); vec3 specBrdf = 0.25 * ggxDistribution(mat, NDotH) * schlickFresnel(mat, LDotH) * geomSmith(mat, NDotL) * geomSmith(mat, NDotV); @@ -311,6 +311,7 @@ void main() { sampler2D normal_map = materials[materialIdx].normal_map; vec2 normal_map_uv_scale = materials[materialIdx].normal_map_uv_scale; EvalMaterial material = evalMaterial(); + material.roughness = material.albedo.a < 1.0 ? 1.0 : material.roughness; vec3 N = textureSize(normal_map, 0) == ivec2(0) ? vec3(0.5) : vec3(texture(normal_map, VertexOut.uv * normal_map_uv_scale).xy, 0); N = N * 2.0 - 1.0; diff --git a/assets/shaders/shadow.glsl b/assets/shaders/shadow.glsl index 96cbb21..93ea659 100644 --- a/assets/shaders/shadow.glsl +++ b/assets/shaders/shadow.glsl @@ -4,8 +4,10 @@ layout(std140, binding = 0) uniform Matrices { mat4 view; }; -// Uniforms -layout(location = 1) uniform mat4 model; +layout(std430, binding = 3) readonly buffer DrawCmdDatas { + // Access by gl_DrawID + mat4 transforms[]; +}; // Input, output blocks @@ -14,6 +16,7 @@ layout(location = 1) uniform mat4 model; layout(location = 0) in vec3 aPos; void main() { + mat4 model = transforms[gl_DrawID]; gl_Position = projection * view * model * vec4(aPos.xyz, 1.0); } #endif // VERTEX_SHADER diff --git a/build.zig b/build.zig index f6b1a79..b79b8da 100644 --- a/build.zig +++ b/build.zig @@ -23,6 +23,10 @@ pub fn build(b: *Build) void { "Prioritize performance, safety, or binary size for build time tools", ) orelse .Debug; + const tracy = b.dependency("zig-tracy", .{ + .target = target, + .optimize = optimize, + }); const zalgebra_dep = b.dependency("zalgebra", .{}); const assets_mod = b.addModule("assets", .{ .root_source_file = .{ .src_path = .{ .owner = b, .sub_path = "src/assets/root.zig" } } }); @@ -62,6 +66,8 @@ pub fn build(b: *Build) void { l.root_module.addImport("zalgebra", zalgebra_dep.module("zalgebra")); l.root_module.addImport("assets", assets_mod); l.root_module.addImport("asset_manifest", asset_manifest_mod); + l.root_module.addImport("tracy", tracy.module("tracy")); + l.linkLibrary(tracy.artifact("tracy")); } const install_lib = b.addInstallArtifact(lib, .{ .dest_dir = .{ .override = .prefix } }); @@ -150,6 +156,8 @@ const asset_extensions = [_][]const u8{ "glsl", "prog", "png", + "dds", + "tga", "jpg", "exr", "fbx", diff --git a/build.zig.zon b/build.zig.zon index 5ed6208..7cb673f 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -27,6 +27,10 @@ .url = "https://github.com/sergeypdev/zalgebra/tarball/43371bf211ad574cde90f653fea171f1cccb1716", .hash = "1220e1439198c5206dbb924420aac0f57dd11fd4b6639e1aa9559abc09f91bfd2c9a", }, + .@"zig-tracy" = .{ + .url = "https://github.com/sergeypdev/zig-tracy/tarball/2b818574810a66deacc424298c1a7679ca6e4375", + .hash = "1220638bc94d67225a620e1abd71d85b299c8b764490fd51233ed73d76ee44cc5835", + }, }, .paths = .{ // This makes *all* files, recursively, included in this package. It is generally diff --git a/src/AssetManager.zig b/src/AssetManager.zig index 4b6dbc1..4d2b601 100644 --- a/src/AssetManager.zig +++ b/src/AssetManager.zig @@ -24,6 +24,7 @@ const checkGLError = @import("Render.zig").checkGLError; const BuddyAllocator = @import("BuddyAllocator.zig"); const Vec2 = @import("zalgebra").Vec2; const Vec3 = @import("zalgebra").Vec3; +const tracy = @import("tracy"); pub const AssetId = assets.AssetId; pub const Handle = assets.Handle; @@ -158,6 +159,9 @@ pub fn resolveMaterial(self: *AssetManager, handle: Handle.Material) formats.Mat // TODO: proper watching pub fn watchChanges(self: *AssetManager) void { + const zone = tracy.initZone(@src(), .{ .name = "AssetManager.watchChanges" }); + defer zone.deinit(); + var iter = self.loaded_assets.iterator(); while (iter.next()) |entry| { const gop = self.modified_times.getOrPut(self.allocator, entry.key_ptr.*) catch return; diff --git a/src/Render.zig b/src/Render.zig index 5f73d19..0dd687d 100644 --- a/src/Render.zig +++ b/src/Render.zig @@ -7,6 +7,7 @@ const globals = @import("globals.zig"); pub const Material = @import("formats.zig").Material; const math = @import("math.zig"); const formats = @import("formats.zig"); +const tracy = @import("tracy"); const za = @import("zalgebra"); const Vec2 = za.Vec2; @@ -438,13 +439,17 @@ pub fn draw(self: *Render, cmd: DrawCommand) void { } pub fn finish(self: *Render) void { - const ginit = globals.g_init; + const zone = tracy.initZone(@src(), .{ .name = "Render.finish" }); + defer zone.deinit(); const camera_projection = self.camera.projection(); const view_proj = camera_projection.mul(self.camera.view_mat); // Sort draw calls: opaque -> blended { + const zoneSort = tracy.initZone(@src(), .{ .name = "Render.finish_sortDraws" }); + defer zoneSort.deinit(); + const cmds = self.command_buffer[0..self.command_count]; std.mem.sortUnstable(DrawCommand, cmds, self, struct { pub fn lessThan(render: *const Render, lhs: DrawCommand, rhs: DrawCommand) bool { @@ -500,6 +505,9 @@ pub fn finish(self: *Render) void { // Light shadow maps { + const zoneShadowmaps = tracy.initZone(@src(), .{ .name = "Render.finish_shadowmaps" }); + defer zoneShadowmaps.deinit(); + gl.enable(gl.DEPTH_CLAMP); defer gl.disable(gl.DEPTH_CLAMP); @@ -737,55 +745,62 @@ pub fn finish(self: *Render) void { checkGLError(); defer gl.deleteBuffers(1, &draw_cmd_data_buf); - const materials = self.materials_pbr_ssbo.getInstance(self.tripple_buffer_index); - materials.count.* = 0; - - var material_map = std.StringHashMap(i32).init(self.frame_arena); - - var materials_count: usize = 0; var rendered_count: usize = 0; - cmds: for (self.command_buffer[0..self.command_count]) |*cmd| { - const mesh = self.assetman.resolveMesh(cmd.mesh); - const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max); - if (!self.world_camera_frustum.intersectAABB(aabb.transform(cmd.transform))) { - continue; + // Prepare indirect draw commands + { + const zonePrepareInidirectDraws = tracy.initZone(@src(), .{ .name = "Render.finish_PrepareInidirectDraws" }); + defer zonePrepareInidirectDraws.deinit(); + + const materials = self.materials_pbr_ssbo.getInstance(self.tripple_buffer_index); + materials.count.* = 0; + + var material_map = std.StringHashMap(i32).init(self.frame_arena); + + var materials_count: usize = 0; + cmds: for (self.command_buffer[0..self.command_count]) |*cmd| { + const mesh = self.assetman.resolveMesh(cmd.mesh); + // const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max); + + // if (!self.world_camera_frustum.intersectAABB(aabb.transform(cmd.transform))) { + // continue; + // } + + const material: Material = if (cmd.material_override) |mat| mat else mesh.material; + + // Opaque objects are drawn, start rendering alpha blended objects + if (material.blend_mode == .AlphaBlend and !switched_to_alpha_blend) { + break :cmds; + // switched_to_alpha_blend = true; + // gl.enable(gl.BLEND); + // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + } + + const material_bytes = std.mem.asBytes(&material); + const material_copy = self.frame_arena.alloc(u8, material_bytes.len) catch @panic("OOM"); + @memcpy(material_copy, material_bytes); + const gop = material_map.getOrPut(material_copy) catch @panic("OOM"); + if (!gop.found_existing) { + gop.value_ptr.* = @intCast(materials_count); + materials.data[materials_count] = MaterialPBR.fromMaterial(self.assetman, &material); + materials_count += 1; + } + + draw_cmd_data[rendered_count] = DrawCommandData{ + .transform = cmd.transform, + .material_index = gop.value_ptr.*, + }; + + draw_indirect_cmds[rendered_count] = DrawIndirectCmd{ + .count = mesh.indices.count, + .instance_count = 1, + .first_index = mesh.indices.offset / 4, + .base_vertex = mesh.indices.base_vertex, + .base_instance = 0, + }; + + rendered_count += 1; } - - const material: Material = if (cmd.material_override) |mat| mat else mesh.material; - - // Opaque objects are drawn, start rendering alpha blended objects - if (material.blend_mode == .AlphaBlend and !switched_to_alpha_blend) { - break :cmds; - // switched_to_alpha_blend = true; - // gl.enable(gl.BLEND); - // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - } - - const material_bytes = std.mem.asBytes(&material); - const material_copy = self.frame_arena.alloc(u8, material_bytes.len) catch @panic("OOM"); - @memcpy(material_copy, material_bytes); - const gop = material_map.getOrPut(material_copy) catch @panic("OOM"); - if (!gop.found_existing) { - gop.value_ptr.* = @intCast(materials_count); - materials.data[materials_count] = MaterialPBR.fromMaterial(self.assetman, &material); - materials_count += 1; - } - - draw_cmd_data[rendered_count] = DrawCommandData{ - .transform = cmd.transform, - .material_index = gop.value_ptr.*, - }; - - draw_indirect_cmds[rendered_count] = DrawIndirectCmd{ - .count = mesh.indices.count, - .instance_count = 1, - .first_index = mesh.indices.offset / 4, - .base_vertex = mesh.indices.base_vertex, - .base_instance = 0, - }; - - rendered_count += 1; } { @@ -992,8 +1007,6 @@ pub fn finish(self: *Render) void { } self.gl_fences[self.tripple_buffer_index] = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); - c.SDL_GL_SwapWindow(ginit.window); - //c.SDL_Delay(1); } pub fn pointLightRange(self: *const PointLight) f32 { @@ -1044,26 +1057,50 @@ const cube_camera_dirs = [6]CubeCameraDir{ }; fn renderShadow(self: *Render, frustum: *const math.Frustum) void { + const zone = tracy.initZone(@src(), .{ .name = "Render.renderShadow" }); + defer zone.deinit(); + _ = frustum; // autofix + self.assetman.vertex_heap.vertices.bind(Render.Attrib.Position.value()); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer); + + // TODO: this wastes space in temp allocator + var draw_indirect_cmds = std.ArrayList(DrawIndirectCmd).init(self.frame_arena); + var transforms = std.ArrayList(Mat4).init(self.frame_arena); + for (self.command_buffer[0..self.command_count]) |*cmd| { const mesh = self.assetman.resolveMesh(cmd.mesh); - const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max); + // const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max); - if (!frustum.intersectAABBSkipNear(aabb.transform(cmd.transform))) { - continue; - } + // if (!frustum.intersectAABBSkipNear(aabb.transform(cmd.transform))) { + // continue; + // } - gl.uniformMatrix4fv(Uniform.ModelMatrix.value(), 1, gl.FALSE, @ptrCast(&cmd.transform.data)); - mesh.positions.bind(Render.Attrib.Position.value()); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer); + const draw_indirect_cmd = draw_indirect_cmds.addOne() catch @panic("OOM"); + const transform = transforms.addOne() catch @panic("OOM"); - gl.drawElementsBaseVertex( - gl.TRIANGLES, - @intCast(mesh.indices.count), - mesh.indices.type, - @ptrFromInt(mesh.indices.offset), - mesh.indices.base_vertex, - ); + draw_indirect_cmd.* = .{ + .count = mesh.indices.count, + .instance_count = 1, + .first_index = mesh.indices.offset / 4, + .base_vertex = mesh.indices.base_vertex, + .base_instance = 0, + }; + + transform.* = cmd.transform; } + + var bufs = [2]gl.GLuint{ 0, 0 }; + gl.createBuffers(bufs.len, &bufs); + checkGLError(); + defer _ = gl.deleteBuffers(bufs.len, &bufs); + + gl.namedBufferStorage(bufs[0], @intCast(@sizeOf(DrawIndirectCmd) * draw_indirect_cmds.items.len), draw_indirect_cmds.items.ptr, 0); + gl.namedBufferStorage(bufs[1], @intCast(@sizeOf(Mat4) * transforms.items.len), transforms.items.ptr, 0); + + gl.bindBuffer(gl.DRAW_INDIRECT_BUFFER, bufs[0]); + gl.bindBufferBase(gl.SHADER_STORAGE_BUFFER, SSBO.DrawCommandData.value(), bufs[1]); + + gl.multiDrawElementsIndirect(gl.TRIANGLES, gl.UNSIGNED_INT, null, @intCast(draw_indirect_cmds.items.len), 0); } pub fn checkGLError() void { diff --git a/src/game.zig b/src/game.zig index 6ee878e..ccdf884 100644 --- a/src/game.zig +++ b/src/game.zig @@ -15,6 +15,7 @@ const Mat4 = za.Mat4; const Quat = za.Quat; const a = @import("asset_manifest"); const windows = std.os.windows; +const tracy = @import("tracy"); pub extern "dwmapi" fn DwmEnableMMCSS(fEnableMMCSS: windows.BOOL) callconv(windows.WINAPI) windows.HRESULT; pub extern "dwmapi" fn DwmFlush() callconv(windows.WINAPI) void; @@ -161,6 +162,7 @@ const mesh_program = a.ShaderPrograms.mesh; export fn game_init(global_allocator: *std.mem.Allocator) void { loadGL(); + tracy.startupProfiler(); std.log.debug("game_init\n", .{}); globals.g_mem = global_allocator.create(GameMemory) catch @panic("OOM"); @@ -188,8 +190,8 @@ export fn game_init(global_allocator: *std.mem.Allocator) void { _ = globals.g_mem.world.addEntity(.{ .flags = .{ .dir_light = true, .rotate = true }, - .transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(20, 0, 0)) }, - .light = .{ .color_intensity = Vec4.new(1, 1, 0.83, 0.7) }, + .transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(70, 0, 0)) }, + .light = .{ .color_intensity = Vec4.new(std.math.pow(f32, 1, 2.2), std.math.pow(f32, 0.9568627450980393, 2.2), std.math.pow(f32, 0.9176470588235294, 2.2), 1.0) }, .rotate = .{ .axis = Vec3.up(), .rate = -10 }, }); @@ -224,70 +226,72 @@ export fn game_init(global_allocator: *std.mem.Allocator) void { // }); // Plane - _ = globals.g_mem.world.addEntity(.{ - .flags = .{ .mesh = true }, - .transform = .{ .scale = Vec3.one().scale(10) }, - .mesh = .{ - .handle = a.Meshes.plane.Plane, - .material = .{ - .albedo = Vec4.one(), - .normal_map = a.Textures.@"tile.norm", - }, - .override_material = true, - }, - }); + // _ = globals.g_mem.world.addEntity(.{ + // .flags = .{ .mesh = true }, + // .transform = .{ .scale = Vec3.one().scale(10) }, + // .mesh = .{ + // .handle = a.Meshes.plane.Plane, + // .material = .{ + // .albedo = Vec4.one(), + // .normal_map = a.Textures.@"tile.norm", + // }, + // .override_material = true, + // }, + // }); // 10 dielectric bunnies - { - for (0..100) |y| { - for (0..10) |x| { - _ = globals.g_mem.world.addEntity(.{ - .transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(x)) * 0.3 - 0.3 * 4.5, 0, @as(f32, @floatFromInt(y)) * 0.3 - 0.3 * 4.5) }, + // { + // for (0..100) |y| { + // for (0..1) |x| { + // _ = globals.g_mem.world.addEntity(.{ + // .transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(x)) * 0.3 - 0.3 * 4.5, 0, @as(f32, @floatFromInt(y)) * 0.3 - 0.3 * 4.5) }, - .flags = .{ .mesh = true }, - .mesh = .{ - .handle = a.Meshes.bunny.BunnyStanfordUVUnwrapped_res1_bun_zipper_res1, - .material = .{ - .albedo_map = a.Textures.bunny_tex1, - // .normal_map = a.Textures.@"tile.norm", - .roughness = @as(f32, @floatFromInt(y)) / 100.0, - }, - .override_material = true, - }, - }); - } - } - } - // 10 metallic bunnies - { - for (0..10) |i| { - _ = globals.g_mem.world.addEntity(.{ - .transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(i)) * 0.3 - 0.3 * 4.5, 0.3, 0) }, + // .flags = .{ .mesh = true }, + // .mesh = .{ + // .handle = a.Meshes.bunny.BunnyStanfordUVUnwrapped_res1_bun_zipper_res1, + // .material = .{ + // .albedo_map = a.Textures.bunny_tex1, + // // .normal_map = a.Textures.@"tile.norm", + // .roughness = @as(f32, @floatFromInt(y)) / 100.0, + // }, + // .override_material = true, + // }, + // }); + // } + // } + // } + // // 10 metallic bunnies + // { + // for (0..10) |i| { + // _ = globals.g_mem.world.addEntity(.{ + // .transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(i)) * 0.3 - 0.3 * 4.5, 0.3, 0) }, - .flags = .{ .mesh = true }, - .mesh = .{ - .handle = a.Meshes.bunny.BunnyStanfordUVUnwrapped_res1_bun_zipper_res1, - .material = .{ - .blend_mode = .AlphaBlend, - .albedo = Vec4.new(1.000, 0.766, 0.336, 0.5), - // .albedo_map = a.Textures.bunny_tex1, - // .normal_map = a.Textures.@"tile.norm", - .roughness = @as(f32, @floatFromInt(i + 1)) / 10.0, - .metallic = 1.0, - }, - .override_material = true, - }, - }); - } - } + // .flags = .{ .mesh = true }, + // .mesh = .{ + // .handle = a.Meshes.bunny.BunnyStanfordUVUnwrapped_res1_bun_zipper_res1, + // .material = .{ + // .blend_mode = .AlphaBlend, + // .albedo = Vec4.new(1.000, 0.766, 0.336, 0.5), + // // .albedo_map = a.Textures.bunny_tex1, + // // .normal_map = a.Textures.@"tile.norm", + // .roughness = @as(f32, @floatFromInt(i + 1)) / 10.0, + // .metallic = 1.0, + // }, + // .override_material = true, + // }, + // }); + // } + // } - const scene = globals.g_mem.world.createScene(globals.g_assetman.resolveScene(a.Scenes.amd_ryzen_9.scene)); + const scene = globals.g_mem.world.createScene(globals.g_assetman.resolveScene(a.Scenes.bistro.scene)); const ent = globals.g_mem.world.getEntity(scene) orelse @panic("WTF"); - ent.data.transform.pos = Vec3.new(0, 1, 0); - ent.data.transform.scale = Vec3.one().scale(0.2); + ent.data.transform.pos = Vec3.new(0, 0, 0); + // ent.data.transform.scale = Vec3.one().scale(1.0); } export fn game_update() bool { + const zoneGameUpdate = tracy.initZone(@src(), .{}); + defer zoneGameUpdate.deinit(); const ginit = globals.g_init; const gmem = globals.g_mem; // std.debug.print("FPS: {d}\n", .{1.0 / g_mem.delta_time}); @@ -298,108 +302,112 @@ export fn game_update() bool { var move = Vec3.zero(); var look = Vec2.zero(); - while (c.SDL_PollEvent(&event) != 0) { - switch (event.type) { - c.SDL_QUIT => { - return false; - }, - c.SDL_MOUSEMOTION => { - if (gmem.mouse_focus) { - look.xMut().* += @floatFromInt(event.motion.xrel); - look.yMut().* += @floatFromInt(event.motion.yrel); - } - }, - c.SDL_MOUSEBUTTONUP => { - if (!gmem.mouse_focus) { - _ = c.SDL_SetRelativeMouseMode(c.SDL_TRUE); + { + const zone = tracy.initZone(@src(), .{ .name = "SDL poll events" }); + defer zone.deinit(); + while (c.SDL_PollEvent(&event) != 0) { + switch (event.type) { + c.SDL_QUIT => { + return false; + }, + c.SDL_MOUSEMOTION => { + if (gmem.mouse_focus) { + look.xMut().* += @floatFromInt(event.motion.xrel); + look.yMut().* += @floatFromInt(event.motion.yrel); + } + }, + c.SDL_MOUSEBUTTONUP => { + if (!gmem.mouse_focus) { + _ = c.SDL_SetRelativeMouseMode(c.SDL_TRUE); - gmem.mouse_focus = true; - } - }, - c.SDL_MOUSEWHEEL => { - if (gmem.mouse_focus) { - gmem.free_cam.move_speed = @max(gmem.free_cam.move_speed + event.wheel.preciseY * 0.1, 0); - } - }, - c.SDL_KEYUP, c.SDL_KEYDOWN => { - const pressed = event.key.state == c.SDL_PRESSED; + gmem.mouse_focus = true; + } + }, + c.SDL_MOUSEWHEEL => { + if (gmem.mouse_focus) { + gmem.free_cam.move_speed = @max(gmem.free_cam.move_speed + event.wheel.preciseY * 0.1, 0); + } + }, + c.SDL_KEYUP, c.SDL_KEYDOWN => { + const pressed = event.key.state == c.SDL_PRESSED; - switch (event.key.keysym.scancode) { - // Toggle fullscreen - c.SDL_SCANCODE_RETURN => { - if (event.type == c.SDL_KEYDOWN and event.key.keysym.mod & c.KMOD_ALT > 0) { - toggleFullScreen() catch continue; - } - }, - // Toggle vsync - c.SDL_SCANCODE_F10 => { - if (event.type == c.SDL_KEYDOWN) { - const newSwap: c_int = if (ginit.vsync) 0 else 1; - sdl_try(c.SDL_GL_SetSwapInterval(newSwap)) catch continue; - ginit.vsync = !ginit.vsync; - } - }, - // Freeze view frustum - c.SDL_SCANCODE_F8 => { - if (event.type == c.SDL_KEYDOWN) { - gmem.render.update_view_frustum = !gmem.render.update_view_frustum; - } - }, - // Expand camera far - c.SDL_SCANCODE_F7 => { - if (event.type == c.SDL_KEYDOWN) { - if (gmem.render.camera.far == 10) { - gmem.render.camera.far = 50; - } else { - gmem.render.camera.far = 10; - } - } - }, - c.SDL_SCANCODE_ESCAPE => { - if (event.type == c.SDL_KEYUP) { - if (ginit.fullscreen) { + switch (event.key.keysym.scancode) { + // Toggle fullscreen + c.SDL_SCANCODE_RETURN => { + if (event.type == c.SDL_KEYDOWN and event.key.keysym.mod & c.KMOD_ALT > 0) { toggleFullScreen() catch continue; - } else if (gmem.mouse_focus) { - _ = c.SDL_SetRelativeMouseMode(c.SDL_FALSE); - gmem.mouse_focus = false; - } else { - return false; } - } - }, - c.SDL_SCANCODE_W => { - gmem.input_state.forward = pressed; - }, - c.SDL_SCANCODE_S => { - gmem.input_state.backward = pressed; - }, - c.SDL_SCANCODE_A => { - gmem.input_state.left = pressed; - }, - c.SDL_SCANCODE_D => { - gmem.input_state.right = pressed; - }, - c.SDL_SCANCODE_SPACE => { - gmem.input_state.up = pressed; - }, - c.SDL_SCANCODE_LCTRL => { - gmem.input_state.down = pressed; - }, - else => {}, - } - }, - c.SDL_WINDOWEVENT => { - switch (event.window.event) { - c.SDL_WINDOWEVENT_SIZE_CHANGED => { - c.SDL_GL_GetDrawableSize(ginit.window, &ginit.width, &ginit.height); - std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height }); + }, + // Toggle vsync + c.SDL_SCANCODE_F10 => { + if (event.type == c.SDL_KEYDOWN) { + const newSwap: c_int = if (ginit.vsync) 0 else 1; + sdl_try(c.SDL_GL_SetSwapInterval(newSwap)) catch continue; + ginit.vsync = !ginit.vsync; + } + }, + // Freeze view frustum + c.SDL_SCANCODE_F8 => { + if (event.type == c.SDL_KEYDOWN) { + gmem.render.update_view_frustum = !gmem.render.update_view_frustum; + } + }, + // Expand camera far + c.SDL_SCANCODE_F7 => { + if (event.type == c.SDL_KEYDOWN) { + if (gmem.render.camera.far == 10) { + gmem.render.camera.far = 50; + } else { + gmem.render.camera.far = 10; + } + } + }, + c.SDL_SCANCODE_ESCAPE => { + if (event.type == c.SDL_KEYUP) { + if (ginit.fullscreen) { + toggleFullScreen() catch continue; + } else if (gmem.mouse_focus) { + _ = c.SDL_SetRelativeMouseMode(c.SDL_FALSE); + gmem.mouse_focus = false; + } else { + return false; + } + } + }, + c.SDL_SCANCODE_W => { + gmem.input_state.forward = pressed; + }, + c.SDL_SCANCODE_S => { + gmem.input_state.backward = pressed; + }, + c.SDL_SCANCODE_A => { + gmem.input_state.left = pressed; + }, + c.SDL_SCANCODE_D => { + gmem.input_state.right = pressed; + }, + c.SDL_SCANCODE_SPACE => { + gmem.input_state.up = pressed; + }, + c.SDL_SCANCODE_LCTRL => { + gmem.input_state.down = pressed; + }, + else => {}, + } + }, + c.SDL_WINDOWEVENT => { + switch (event.window.event) { + c.SDL_WINDOWEVENT_SIZE_CHANGED => { + c.SDL_GL_GetDrawableSize(ginit.window, &ginit.width, &ginit.height); + std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height }); - gl.viewport(0, 0, ginit.width, ginit.height); - }, - else => {}, - } - }, - else => {}, + gl.viewport(0, 0, ginit.width, ginit.height); + }, + else => {}, + } + }, + else => {}, + } } } @@ -438,6 +446,8 @@ export fn game_update() bool { // Update { + const zone = tracy.initZone(@src(), .{ .name = "update entities" }); + defer zone.deinit(); for (gmem.world.entities[0..gmem.world.entity_count]) |*ent| { if (!ent.data.flags.active) continue; @@ -449,6 +459,8 @@ export fn game_update() bool { // Render { + const zone = tracy.initZone(@src(), .{ .name = "game.render()" }); + defer zone.deinit(); gmem.render.begin(); defer gmem.render.finish(); @@ -503,7 +515,15 @@ export fn game_update() bool { } } - globals.g_assetman.watchChanges(); + { + const zone = tracy.initZone(@src(), .{ .name = "SDL_GL_SwapWindow" }); + defer zone.deinit(); + c.SDL_GL_SwapWindow(ginit.window); + } + tracy.frameMark(); + //c.SDL_Delay(1); + + // globals.g_assetman.watchChanges(); return true; } @@ -514,6 +534,7 @@ export fn game_shutdown() void { gmem.global_allocator.free(gmem.frame_fba.buffer); gmem.global_allocator.destroy(gmem); gl.disable(gl.DEBUG_OUTPUT); + tracy.shutdownProfiler(); } export fn game_shutdown_window() void { diff --git a/tools/asset_compiler.zig b/tools/asset_compiler.zig index 98c8af3..2b399c0 100644 --- a/tools/asset_compiler.zig +++ b/tools/asset_compiler.zig @@ -44,7 +44,7 @@ pub fn resolveAssetTypeByExtension(path: []const u8) ?AssetType { if (std.mem.endsWith(u8, path, ".glsl")) { return .Shader; } - if (std.mem.endsWith(u8, path, ".png") or std.mem.endsWith(u8, path, ".jpg") or std.mem.endsWith(u8, path, ".exr")) { + if (std.mem.endsWith(u8, path, ".png") or std.mem.endsWith(u8, path, ".jpg") or std.mem.endsWith(u8, path, ".exr") or std.mem.endsWith(u8, path, ".dds") or std.mem.endsWith(u8, path, ".tga")) { return .Texture; } return null;