improving rasterization performances
Test / build_and_test (push) Successful in 33s
Build / build (push) Successful in 1m2s

This commit is contained in:
2026-05-14 21:44:53 +02:00
parent 1eb367ac17
commit d460f22a45
10 changed files with 227 additions and 112 deletions
+131 -8
View File
@@ -5,17 +5,67 @@ const clip = @import("clip.zig");
const bresenham = @import("rasterizer/bresenham.zig");
const edge_function = @import("rasterizer/edge_function.zig");
const common = @import("rasterizer/common.zig");
const Renderer = @import("Renderer.zig");
const Vertex = Renderer.Vertex;
const DrawCall = Renderer.DrawCall;
const SoftImage = @import("../SoftImage.zig");
const VkError = base.VkError;
pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocator, draw_call: *DrawCall) VkError!void {
const io = draw_call.renderer.device.interface.io();
const pipeline_data = (renderer.state.pipeline orelse return VkError.InvalidHandleDrv).interface.mode.graphics;
const topology = pipeline_data.input_assembly.topology;
const color_attachment = if (draw_call.render_pass.interface.subpasses[0].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv;
const render_target_view: *base.ImageView = draw_call.color_attachments[color_attachment];
const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image));
const color_range = render_target_view.subresource_range;
const color_format = render_target_view.format;
const color_attachment_subresource_offset = try render_target.getSubresourceOffset(
color_range.aspect_mask,
color_range.base_mip_level,
color_range.base_array_layer,
);
const color_attachment_subresource_size = render_target.getLayerSize(color_range.aspect_mask);
const color_attachment_access: common.RenderTargetAccess = .{
.mutex = undefined,
.base = try render_target.mapAsSliceWithAddedOffset(u8, color_attachment_subresource_offset, color_attachment_subresource_size),
.row_pitch = render_target.getRowPitchMemSizeForMipLevelWithFormat(color_range.aspect_mask, color_range.base_mip_level, color_format),
.texel_size = base.format.texelSize(color_format),
.format = color_format,
};
const depth_attachment_view: ?*base.ImageView = if (draw_call.depth_attachment) |view| view else null;
const depth_attachment: ?*SoftImage = if (depth_attachment_view) |view| @alignCast(@fieldParentPtr("interface", view.image)) else null;
var depth_attachment_access: ?common.RenderTargetAccess = blk: {
if (depth_attachment == null)
break :blk null;
const depth_range = depth_attachment_view.?.subresource_range;
const depth_format = depth_attachment_view.?.format;
const attachment_subresource_offset = try depth_attachment.?.getSubresourceOffset(
depth_range.aspect_mask,
depth_range.base_mip_level,
depth_range.base_array_layer,
);
const attachment_subresource_size = depth_attachment.?.getLayerSize(depth_range.aspect_mask);
break :blk .{
.mutex = .init,
.base = try depth_attachment.?.mapAsSliceWithAddedOffset(u8, attachment_subresource_offset, attachment_subresource_size),
.row_pitch = render_target.getRowPitchMemSizeForMipLevelWithFormat(depth_range.aspect_mask, depth_range.base_mip_level, depth_format),
.texel_size = base.format.texelSize(depth_format),
.format = depth_format,
};
};
switch (topology) {
.triangle_list => for (0..@divTrunc(draw_call.vertices.len, 3)) |triangle_index| {
const first_vertex = triangle_index * 3;
@@ -23,7 +73,16 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
const v1 = &draw_call.vertices[first_vertex + 1];
const v2 = &draw_call.vertices[first_vertex + 2];
try clipTransformAndRasterizeTriangle(renderer, allocator, draw_call, v0, v1, v2);
try clipTransformAndRasterizeTriangle(
renderer,
allocator,
draw_call,
v0,
v1,
v2,
&color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
},
.triangle_fan => if (draw_call.vertices.len >= 3) {
const v0 = &draw_call.vertices[0];
@@ -31,7 +90,16 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
const v1 = &draw_call.vertices[vertex_index];
const v2 = &draw_call.vertices[vertex_index + 1];
try clipTransformAndRasterizeTriangle(renderer, allocator, draw_call, v0, v1, v2);
try clipTransformAndRasterizeTriangle(
renderer,
allocator,
draw_call,
v0,
v1,
v2,
&color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
}
},
.triangle_strip => if (draw_call.vertices.len >= 3) {
@@ -41,17 +109,46 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
const v2 = &draw_call.vertices[vertex_index + 2];
if ((vertex_index & 1) == 0) {
try clipTransformAndRasterizeTriangle(renderer, allocator, draw_call, v0, v1, v2);
try clipTransformAndRasterizeTriangle(
renderer,
allocator,
draw_call,
v0,
v1,
v2,
&color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
} else {
try clipTransformAndRasterizeTriangle(renderer, allocator, draw_call, v1, v0, v2);
try clipTransformAndRasterizeTriangle(
renderer,
allocator,
draw_call,
v1,
v0,
v2,
&color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
}
}
},
else => base.unsupported("primitive topology {any}", .{topology}),
}
draw_call.rasterizer_wait_group.await(io) catch return VkError.DeviceLost;
}
fn clipTransformAndRasterizeTriangle(renderer: *Renderer, allocator: std.mem.Allocator, draw_call: *DrawCall, v0: *Vertex, v1: *Vertex, v2: *Vertex) VkError!void {
fn clipTransformAndRasterizeTriangle(
renderer: *Renderer,
allocator: std.mem.Allocator,
draw_call: *DrawCall,
v0: *Vertex,
v1: *Vertex,
v2: *Vertex,
color_attachment_access: *const common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
const clipped_polygon = try clip.clipTriangle(allocator, v0, v1, v2);
if (clipped_polygon.len < 3)
@@ -66,11 +163,29 @@ fn clipTransformAndRasterizeTriangle(renderer: *Renderer, allocator: std.mem.All
clip.viewportTransformVertex(draw_call.viewport, &tv1);
clip.viewportTransformVertex(draw_call.viewport, &tv2);
try rasterizeTriangle(renderer, allocator, draw_call, &tv0, &tv1, &tv2);
try rasterizeTriangle(
renderer,
allocator,
draw_call,
&tv0,
&tv1,
&tv2,
color_attachment_access,
depth_attachment_access,
);
}
}
fn rasterizeTriangle(renderer: *Renderer, allocator: std.mem.Allocator, draw_call: *DrawCall, v0: *Vertex, v1: *Vertex, v2: *Vertex) VkError!void {
fn rasterizeTriangle(
renderer: *Renderer,
allocator: std.mem.Allocator,
draw_call: *DrawCall,
v0: *Vertex,
v1: *Vertex,
v2: *Vertex,
color_attachment_access: *const common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
if (try triangleIsCulled(renderer, v0, v1, v2))
return;
@@ -78,7 +193,15 @@ fn rasterizeTriangle(renderer: *Renderer, allocator: std.mem.Allocator, draw_cal
const pipeline_data = (renderer.state.pipeline orelse return VkError.InvalidHandleDrv).interface.mode.graphics;
switch (pipeline_data.rasterization.polygon_mode) {
.fill => try edge_function.drawTriangle(allocator, draw_call, v0, v1, v2),
.fill => try edge_function.drawTriangle(
allocator,
draw_call,
v0,
v1,
v2,
color_attachment_access,
depth_attachment_access,
),
.line => {
try bresenham.drawLine(allocator, draw_call, v0, v1);
try bresenham.drawLine(allocator, draw_call, v1, v2);