From 0658c2fdfa7011e82d6fbe37e83c306a42584293 Mon Sep 17 00:00:00 2001 From: duck Date: Fri, 26 Sep 2025 00:19:11 +0500 Subject: [PATCH] Optional antialiasing --- src/assets/texture.zig | 15 ++-- src/graphics.zig | 151 ++++++++++++++++++++++++++--------------- 2 files changed, 103 insertions(+), 63 deletions(-) diff --git a/src/assets/texture.zig b/src/assets/texture.zig index 05e8dc9..c3790e1 100644 --- a/src/assets/texture.zig +++ b/src/assets/texture.zig @@ -29,13 +29,14 @@ pub fn load(path: []const u8, alloc: std.mem.Allocator) Assets.LoadError!@This() const bytes_per_pixel = 4; const mip_level = if (std.math.isPowerOfTwo(width) and width == height) @as(u32, Graphics.MIP_LEVEL) else @as(u32, 1); - const texture = Graphics.createTexture( - width, - height, - target_format, - sdl.GPU_TEXTUREUSAGE_SAMPLER | sdl.GPU_TEXTUREUSAGE_COLOR_TARGET, - mip_level, - ); + const texture = sdl.CreateGPUTexture(Graphics.device, &.{ + .width = width, + .height = height, + .layer_count_or_depth = 1, + .format = target_format, + .usage = sdl.GPU_TEXTUREUSAGE_SAMPLER | sdl.GPU_TEXTUREUSAGE_COLOR_TARGET, + .num_levels = mip_level, + }) orelse err.sdl(); errdefer Graphics.freeTexture(texture); const transfer_buffer_capacity = Graphics.TRANSFER_BUFFER_DEFAULT_CAPACITY; diff --git a/src/graphics.zig b/src/graphics.zig index 73caa92..6913c6a 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -14,22 +14,20 @@ pub var device: *sdl.GPUDevice = undefined; var command_buffer: ?*sdl.GPUCommandBuffer = null; var render_pass: ?*sdl.GPURenderPass = null; var render_target: ?*sdl.GPUTexture = null; -var render_fsaa: bool = undefined; var batches: Batches = undefined; var shader_vert: *sdl.GPUShader = undefined; var shader_frag: *sdl.GPUShader = undefined; var depth_texture: *sdl.GPUTexture = undefined; -var fsaa_target: *sdl.GPUTexture = undefined; +var antialias: Antialias = undefined; +var aa_target: *sdl.GPUTexture = undefined; var pipeline: *sdl.GPUGraphicsPipeline = undefined; pub var window_width: u32 = undefined; pub var window_height: u32 = undefined; pub var pixel_width: u32 = undefined; pub var pixel_height: u32 = undefined; -var fsaa_scale: u32 = 4; -var fsaa_level: u32 = 3; var render_width: u32 = undefined; var render_height: u32 = undefined; @@ -40,6 +38,41 @@ const DEPTH_FORMAT = sdl.GPU_TEXTUREFORMAT_D32_FLOAT; pub const TRANSFER_BUFFER_DEFAULT_CAPACITY = 512 * 1024; pub const MIP_LEVEL = 4; +const Antialias = union(enum) { + none, + msaa: enum(sdl.GPUSampleCount) { + @"2" = sdl.GPU_SAMPLECOUNT_2, + @"4" = sdl.GPU_SAMPLECOUNT_4, + @"8" = sdl.GPU_SAMPLECOUNT_8, + }, + fsaa: enum { + @"2", + @"4", + @"8", + }, + + pub fn getMsaaSamples(self: @This()) sdl.GPUSampleCount { + if (self != .msaa) return sdl.GPU_SAMPLECOUNT_1; + return @intFromEnum(self.msaa); + } + pub fn getFsaaScale(self: @This()) u8 { + if (self != .fsaa) return 1; + return switch (self.fsaa) { + .@"2" => 2, + .@"4" => 4, + .@"8" => 8, + }; + } + pub fn getFsaaLevel(self: @This()) u8 { + if (self != .fsaa) return 1; + return switch (self.fsaa) { + .@"2" => 2, + .@"4" => 3, + .@"8" => 4, + }; + } +}; + const Batch = struct { object: *Assets.Object, transform: Transform, @@ -76,6 +109,8 @@ pub fn create() void { Graphics.render_width = pixel_width; Graphics.render_height = pixel_height; + Graphics.antialias = .none; + // Device Graphics.device = sdl.CreateGPUDevice( sdl.GPU_SHADERFORMAT_SPIRV, @@ -109,20 +144,24 @@ pub fn create() void { const target_format = sdl.GetGPUSwapchainTextureFormat(Graphics.device, Graphics.window); if (target_format == sdl.GPU_TEXTUREFORMAT_INVALID) err.sdl(); - Graphics.depth_texture = createTexture( - @as(u32, @intCast(Graphics.render_width)) * Graphics.fsaa_scale, - @as(u32, @intCast(Graphics.render_height)) * Graphics.fsaa_scale, - DEPTH_FORMAT, - sdl.GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, - 1, - ); - Graphics.fsaa_target = createTexture( - @as(u32, @intCast(Graphics.render_width)) * Graphics.fsaa_scale, - @as(u32, @intCast(Graphics.render_height)) * Graphics.fsaa_scale, - target_format, - sdl.GPU_TEXTUREUSAGE_COLOR_TARGET | sdl.GPU_TEXTUREUSAGE_SAMPLER, - fsaa_level, - ); + Graphics.depth_texture = sdl.CreateGPUTexture(device, &.{ + .width = Graphics.render_width * Graphics.antialias.getFsaaScale(), + .height = Graphics.render_height * Graphics.antialias.getFsaaScale(), + .layer_count_or_depth = 1, + .format = DEPTH_FORMAT, + .usage = sdl.GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, + .num_levels = 1, + .sample_count = Graphics.antialias.getMsaaSamples(), + }) orelse err.sdl(); + Graphics.aa_target = sdl.CreateGPUTexture(device, &.{ + .width = Graphics.render_width * Graphics.antialias.getFsaaScale(), + .height = Graphics.render_height * Graphics.antialias.getFsaaScale(), + .layer_count_or_depth = 1, + .format = target_format, + .usage = if (Graphics.antialias == .fsaa) sdl.GPU_TEXTUREUSAGE_COLOR_TARGET | sdl.GPU_TEXTUREUSAGE_SAMPLER else sdl.GPU_TEXTUREUSAGE_COLOR_TARGET, + .num_levels = Graphics.antialias.getFsaaLevel(), + .sample_count = Graphics.antialias.getMsaaSamples(), + }) orelse err.sdl(); Graphics.pipeline = sdl.CreateGPUGraphicsPipeline(Graphics.device, &.{ .vertex_shader = Graphics.shader_vert, @@ -150,6 +189,9 @@ pub fn create() void { }, .num_vertex_attributes = 2, }, + .multisample_state = .{ + .sample_count = Graphics.antialias.getMsaaSamples(), + }, .primitive_type = sdl.GPU_PRIMITIVETYPE_TRIANGLELIST, .rasterizer_state = presets.RASTERIZER_CULL, .depth_stencil_state = presets.DEPTH_ENABLED, @@ -180,7 +222,7 @@ pub fn destroy() void { sdl.DestroyWindow(Graphics.window); sdl.ReleaseGPUGraphicsPipeline(Graphics.device, Graphics.pipeline); - sdl.ReleaseGPUTexture(Graphics.device, Graphics.fsaa_target); + sdl.ReleaseGPUTexture(Graphics.device, Graphics.aa_target); sdl.ReleaseGPUTexture(Graphics.device, Graphics.depth_texture); sdl.ReleaseGPUShader(Graphics.device, Graphics.shader_vert); @@ -212,14 +254,14 @@ pub fn beginDraw() bool { Graphics.camera.aspect = @as(f32, @floatFromInt(Graphics.render_width)) / @as(f32, @floatFromInt(Graphics.render_height)); } - Graphics.render_fsaa = Graphics.fsaa_level > 1; Graphics.render_pass = sdl.BeginGPURenderPass(Graphics.command_buffer.?, &.{ .clear_color = .{ .r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0 }, .cycle = false, - .load_op = sdl.GPU_LOADOP_CLEAR, - .store_op = sdl.GPU_STOREOP_STORE, + .load_op = sdl.GPU_LOADOP_DONT_CARE, + .store_op = if (Graphics.antialias == .msaa) sdl.GPU_STOREOP_RESOLVE else sdl.GPU_STOREOP_STORE, .mip_level = 0, - .texture = if (Graphics.render_fsaa) Graphics.fsaa_target else Graphics.render_target, + .texture = if (Graphics.antialias == .fsaa or Graphics.antialias == .msaa) Graphics.aa_target else Graphics.render_target, + .resolve_texture = if (Graphics.antialias == .msaa) Graphics.render_target else null, }, 1, &.{ .clear_depth = 0.0, .load_op = sdl.GPU_LOADOP_CLEAR, @@ -270,9 +312,10 @@ pub fn clearDepth() void { .clear_color = .{ .r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0 }, .cycle = false, .load_op = sdl.GPU_LOADOP_LOAD, - .store_op = sdl.GPU_STOREOP_STORE, + .store_op = if (Graphics.antialias == .msaa) sdl.GPU_STOREOP_RESOLVE else sdl.GPU_STOREOP_STORE, .mip_level = 0, - .texture = if (Graphics.render_fsaa) Graphics.fsaa_target else Graphics.render_target, + .texture = if (Graphics.antialias == .fsaa or Graphics.antialias == .msaa) Graphics.aa_target else Graphics.render_target, + .resolve_texture = if (Graphics.antialias == .msaa) Graphics.render_target else null, }, 1, &.{ .clear_depth = 0.0, .load_op = sdl.GPU_LOADOP_CLEAR, @@ -314,14 +357,14 @@ pub fn endDraw() void { Graphics.finishPass(); - if (Graphics.render_fsaa) { - sdl.GenerateMipmapsForGPUTexture(Graphics.command_buffer, Graphics.fsaa_target); + if (Graphics.antialias == .fsaa) { + sdl.GenerateMipmapsForGPUTexture(Graphics.command_buffer, Graphics.aa_target); sdl.BlitGPUTexture(Graphics.command_buffer, &.{ .source = .{ - .texture = Graphics.fsaa_target, + .texture = Graphics.aa_target, .w = Graphics.render_width, .h = Graphics.render_height, - .mip_level = fsaa_level - 1, + .mip_level = Graphics.antialias.getFsaaLevel() - 1, }, .destination = .{ .texture = Graphics.render_target, @@ -348,18 +391,6 @@ fn loadShader(path: []const u8, info: sdl.GPUShaderCreateInfo) *sdl.GPUShader { return sdl.CreateGPUShader(device, &updated_info) orelse err.sdl(); } -pub fn createTexture(width: u32, height: u32, format: c_uint, usage: c_uint, mip_level: u32) *sdl.GPUTexture { - return sdl.CreateGPUTexture(device, &.{ - .format = format, - .layer_count_or_depth = 1, - .width = width, - .height = height, - .num_levels = mip_level, - .sample_count = sdl.GPU_SAMPLECOUNT_1, - .usage = usage, - }) orelse err.sdl(); -} - pub fn freeTexture(texture: *sdl.GPUTexture) void { sdl.ReleaseGPUTexture(Graphics.device, texture); } @@ -384,24 +415,32 @@ pub fn freeSampler(sampler: *sdl.GPUSampler) void { fn resetTextures(width: u32, height: u32) void { sdl.ReleaseGPUTexture(Graphics.device, Graphics.depth_texture); - Graphics.depth_texture = createTexture( - width * Graphics.fsaa_scale, - height * Graphics.fsaa_scale, - DEPTH_FORMAT, - sdl.GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, - 1, - ); + Graphics.depth_texture = sdl.CreateGPUTexture(device, &.{ + .width = width * Graphics.antialias.getFsaaScale(), + .height = height * Graphics.antialias.getFsaaScale(), + .layer_count_or_depth = 1, + .format = DEPTH_FORMAT, + .usage = sdl.GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, + .num_levels = 1, + .sample_count = Graphics.antialias.getMsaaSamples(), + }) orelse err.sdl(); const target_format = sdl.GetGPUSwapchainTextureFormat(Graphics.device, Graphics.window); - sdl.ReleaseGPUTexture(Graphics.device, Graphics.fsaa_target); - Graphics.fsaa_target = createTexture( - width * Graphics.fsaa_scale, - height * Graphics.fsaa_scale, - target_format, - sdl.GPU_TEXTUREUSAGE_COLOR_TARGET | sdl.GPU_TEXTUREUSAGE_SAMPLER, - fsaa_level, - ); + sdl.ReleaseGPUTexture(Graphics.device, Graphics.aa_target); + Graphics.aa_target = sdl.CreateGPUTexture(device, &.{ + .width = width * Graphics.antialias.getFsaaScale(), + .height = height * Graphics.antialias.getFsaaScale(), + .layer_count_or_depth = 1, + .format = target_format, + .usage = switch (Graphics.antialias) { + .none => sdl.GPU_TEXTUREUSAGE_COLOR_TARGET, + .fsaa => sdl.GPU_TEXTUREUSAGE_COLOR_TARGET | sdl.GPU_TEXTUREUSAGE_SAMPLER, + .msaa => sdl.GPU_TEXTUREUSAGE_COLOR_TARGET, + }, + .num_levels = Graphics.antialias.getFsaaLevel(), + .sample_count = Graphics.antialias.getMsaaSamples(), + }) orelse err.sdl(); } pub fn windowId() sdl.WindowID {