diff --git a/src/soft/device/Renderer.zig b/src/soft/device/Renderer.zig index 9242f51..fe2a215 100644 --- a/src/soft/device/Renderer.zig +++ b/src/soft/device/Renderer.zig @@ -59,12 +59,25 @@ pub const DrawCall = struct { viewport: vk.Viewport, scissor: vk.Rect2D, + color_attachments: []*base.ImageView, + depth_attachment: ?*base.ImageView, + + render_pass: *SoftRenderPass, + framebuffer: *SoftFramebuffer, + fn init(allocator: std.mem.Allocator, vertex_count: usize, instance_count: usize, renderer: *Self) VkError!@This() { + const framebuffer = renderer.framebuffer orelse return VkError.InvalidHandleDrv; + const render_pass = renderer.render_pass orelse return VkError.InvalidHandleDrv; + const self: @This() = .{ .vertices = allocator.alloc(Vertex, vertex_count * instance_count) catch return VkError.OutOfDeviceMemory, .renderer = renderer, .viewport = undefined, .scissor = undefined, + .color_attachments = framebuffer.interface.attachments[0..], + .depth_attachment = if (render_pass.interface.subpasses[0].depth_stencil_attachments) |desc| framebuffer.interface.attachments[desc.attachment] else null, + .render_pass = render_pass, + .framebuffer = framebuffer, }; for (self.vertices) |*vertex| { diff --git a/src/soft/device/blitter.zig b/src/soft/device/blitter.zig index 2b3deb5..9ec797f 100644 --- a/src/soft/device/blitter.zig +++ b/src/soft/device/blitter.zig @@ -577,7 +577,9 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 { .r32_uint, => c[0] = @floatFromInt(std.mem.bytesToValue(u32, map)), - .r32_sfloat => c[0] = std.mem.bytesToValue(f32, map), + .d32_sfloat, + .r32_sfloat, + => c[0] = std.mem.bytesToValue(f32, map), .r32g32b32a32_sfloat => c = std.mem.bytesToValue(F32x4, map), diff --git a/src/soft/device/rasterizer/bresenham.zig b/src/soft/device/rasterizer/bresenham.zig index 3094e52..6bc889b 100644 --- a/src/soft/device/rasterizer/bresenham.zig +++ b/src/soft/device/rasterizer/bresenham.zig @@ -119,7 +119,8 @@ fn runWrapper(data: RunData) void { } inline fn run(data: RunData) !void { - const render_target_view: *base.ImageView = (data.draw_call.renderer.framebuffer orelse return).interface.attachments[0]; + const color_attachment = if (data.draw_call.render_pass.interface.subpasses[0].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv; + const render_target_view: *base.ImageView = data.draw_call.color_attachments[color_attachment]; const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image)); var step = data.start_step; diff --git a/src/soft/device/rasterizer/edge_function.zig b/src/soft/device/rasterizer/edge_function.zig index 1fecfcf..22a3145 100644 --- a/src/soft/device/rasterizer/edge_function.zig +++ b/src/soft/device/rasterizer/edge_function.zig @@ -108,9 +108,13 @@ fn runWrapper(data: RunData) void { } inline fn run(data: RunData) !void { - const render_target_view: *base.ImageView = (data.draw_call.renderer.framebuffer orelse return).interface.attachments[0]; + const color_attachment = if (data.draw_call.render_pass.interface.subpasses[0].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv; + const render_target_view: *base.ImageView = data.draw_call.color_attachments[color_attachment]; const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image)); + const depth_attachment_view: ?*base.ImageView = if (data.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 y = data.min_y; while (y <= data.max_y) : (y += 1) { var x = data.min_x; @@ -138,6 +142,40 @@ inline fn run(data: RunData) !void { const b2 = w2 / data.area; const z = (b0 * data.v0.position[2]) + (b1 * data.v1.position[2]) + (b2 * data.v2.position[2]); + if (depth_attachment) |depth| { + const depth_value = try depth.readFloat4( + .{ + .x = x, + .y = y, + .z = 0, + }, + .{ + .aspect_mask = depth_attachment_view.?.subresource_range.aspect_mask, + .mip_level = depth_attachment_view.?.subresource_range.base_mip_level, + .array_layer = depth_attachment_view.?.subresource_range.base_array_layer, + }, + depth_attachment_view.?.format, + ); + + if (z >= depth_value[0]) + continue; + + try depth.writeFloat4( + .{ + .x = x, + .y = y, + .z = 0, + }, + .{ + .aspect_mask = depth_attachment_view.?.subresource_range.aspect_mask, + .mip_level = depth_attachment_view.?.subresource_range.base_mip_level, + .array_layer = depth_attachment_view.?.subresource_range.base_array_layer, + }, + depth_attachment_view.?.format, + zm.f32x4s(z), + ); + } + const pixel = fragment.shaderInvocation( data.allocator, data.draw_call, @@ -156,7 +194,7 @@ inline fn run(data: RunData) !void { .{ .x = x, .y = y, - .z = 0, // FIXME + .z = 0, }, .{ .aspect_mask = render_target_view.subresource_range.aspect_mask, diff --git a/src/vulkan/RenderPass.zig b/src/vulkan/RenderPass.zig index 02e9e0c..ee3f62c 100644 --- a/src/vulkan/RenderPass.zig +++ b/src/vulkan/RenderPass.zig @@ -10,8 +10,19 @@ const Device = @import("Device.zig"); const Self = @This(); pub const ObjectType: vk.ObjectType = .render_pass; +const SubpassDescription = struct { + flags: vk.SubpassDescriptionFlags, + pipeline_bind_point: vk.PipelineBindPoint, + input_attachments: ?[]const vk.AttachmentReference, + color_attachments: ?[]const vk.AttachmentReference, + resolve_attachments: ?[]const vk.AttachmentReference, + depth_stencil_attachments: ?vk.AttachmentReference, + preserve_attachments: ?[]const u32, +}; + owner: *Device, attachments: []vk.AttachmentDescription, +subpasses: []SubpassDescription, vtable: *const VTable, @@ -33,14 +44,52 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Rende return VkError.ValidationFailed; } + const subpasses = allocator.alloc(SubpassDescription, info.subpass_count) catch return VkError.OutOfHostMemory; + errdefer allocator.free(subpasses); + + for (subpasses[0..], info.p_subpasses[0..]) |*subpass, subpass_info| { + subpass.* = .{ + .flags = subpass_info.flags, + .pipeline_bind_point = subpass_info.pipeline_bind_point, + .input_attachments = if (subpass_info.p_input_attachments) |subpass_attachments| + allocator.dupe(vk.AttachmentReference, subpass_attachments[0..subpass_info.input_attachment_count]) catch return VkError.OutOfHostMemory + else + null, + .color_attachments = if (subpass_info.p_color_attachments) |subpass_attachments| + allocator.dupe(vk.AttachmentReference, subpass_attachments[0..subpass_info.color_attachment_count]) catch return VkError.OutOfHostMemory + else + null, + .resolve_attachments = if (subpass_info.p_resolve_attachments) |subpass_attachments| + allocator.dupe(vk.AttachmentReference, subpass_attachments[0..subpass_info.color_attachment_count]) catch return VkError.OutOfHostMemory + else + null, + .depth_stencil_attachments = if (subpass_info.p_depth_stencil_attachment) |subpass_attachment| + subpass_attachment.* + else + null, + .preserve_attachments = if (subpass_info.p_preserve_attachments) |subpass_attachments| + allocator.dupe(u32, subpass_attachments[0..subpass_info.preserve_attachment_count]) catch return VkError.OutOfHostMemory + else + null, + }; + } + return .{ .owner = device, .attachments = attachments, + .subpasses = subpasses, .vtable = undefined, }; } pub fn destroy(self: *Self, allocator: std.mem.Allocator) void { allocator.free(self.attachments); + for (self.subpasses[0..]) |subpass| { + if (subpass.input_attachments) |attachments| allocator.free(attachments); + if (subpass.color_attachments) |attachments| allocator.free(attachments); + if (subpass.resolve_attachments) |attachments| allocator.free(attachments); + if (subpass.preserve_attachments) |attachments| allocator.free(attachments); + } + allocator.free(self.subpasses); self.vtable.destroy(self, allocator); } diff --git a/src/vulkan/error_set.zig b/src/vulkan/error_set.zig index 5b2beb6..bfad08a 100644 --- a/src/vulkan/error_set.zig +++ b/src/vulkan/error_set.zig @@ -55,6 +55,7 @@ pub const VkError = error{ InvalidHandleDrv, InvalidPipelineDrv, InvalidDeviceMemoryDrv, + InvalidAttachmentDrv, }; pub inline fn errorLogger(err: VkError) void {