diff --git a/build.zig.zon b/build.zig.zon index 8168439..67a1e06 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -31,8 +31,8 @@ .lazy = true, }, .SPIRV_Interpreter = .{ - .url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#a765246ee96bd2990471cab1d06468dab8ca5a90", - .hash = "SPIRV_Interpreter-0.0.1-ajmpnwJJBQBf3lGA1o8VXvEotGeeajtQGgcrGeDVd21S", + .url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#b82d37e7b66a94b58464c972092e184e219e98d8", + .hash = "SPIRV_Interpreter-0.0.1-ajmpnyI_BQACRyFzfq9PUcgOz7OqJP4qSoLfhJxj2XSY", .lazy = true, }, //.SPIRV_Interpreter = .{ diff --git a/src/soft/SoftDescriptorSet.zig b/src/soft/SoftDescriptorSet.zig index 49e2edc..0dd8462 100644 --- a/src/soft/SoftDescriptorSet.zig +++ b/src/soft/SoftDescriptorSet.zig @@ -98,18 +98,42 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, layout: *base. .uniform_buffer, .storage_buffer, .storage_buffer_dynamic, - => descriptor.* = .{ - .buffer = local_allocator.alloc(DescriptorBuffer, binding.array_size) catch return VkError.OutOfHostMemory, + => descriptor.* = blk: { + const desc: Descriptor = .{ + .buffer = local_allocator.alloc(DescriptorBuffer, binding.array_size) catch return VkError.OutOfHostMemory, + }; + for (desc.buffer[0..]) |*d| { + d.* = .{ + .object = null, + .offset = 0, + .size = 0, + }; + } + break :blk desc; }, + .storage_image, .input_attachment, - => descriptor.* = .{ - .image = local_allocator.alloc(DescriptorImage, binding.array_size) catch return VkError.OutOfHostMemory, + => descriptor.* = blk: { + const desc: Descriptor = .{ + .image = local_allocator.alloc(DescriptorImage, binding.array_size) catch return VkError.OutOfHostMemory, + }; + for (desc.image[0..]) |*d| { + d.* = .{ .object = null }; + } + break :blk desc; }, + .storage_texel_buffer, .uniform_texel_buffer, - => descriptor.* = .{ - .texel_buffer = local_allocator.alloc(DescriptorTexel, binding.array_size) catch return VkError.OutOfHostMemory, + => descriptor.* = blk: { + const desc: Descriptor = .{ + .texel_buffer = local_allocator.alloc(DescriptorTexel, binding.array_size) catch return VkError.OutOfHostMemory, + }; + for (desc.texel_buffer[0..]) |*d| { + d.* = .{ .object = null }; + } + break :blk desc; }, else => {}, } diff --git a/src/soft/device/ComputeDispatcher.zig b/src/soft/device/ComputeDispatcher.zig index 1728692..a2505ec 100644 --- a/src/soft/device/ComputeDispatcher.zig +++ b/src/soft/device/ComputeDispatcher.zig @@ -4,7 +4,8 @@ const base = @import("base"); const spv = @import("spv"); const lib = @import("../lib.zig"); -const PipelineState = @import("Device.zig").PipelineState; +const ExecutionDevice = @import("Device.zig"); +const PipelineState = ExecutionDevice.PipelineState; const SoftDevice = @import("../SoftDevice.zig"); const SoftPipeline = @import("../SoftPipeline.zig"); @@ -96,7 +97,7 @@ inline fn run(data: RunData) !void { const entry = try rt.getEntryPointByName(shader.entry); - try data.self.writeDescriptorSets(rt); + try ExecutionDevice.writeDescriptorSets(data.self.state, rt); var group_index: usize = data.batch_id; while (group_index < data.group_count) : (group_index += data.self.batch_size) { @@ -165,52 +166,6 @@ inline fn dumpResultsTable(allocator: std.mem.Allocator, io: std.Io, rt: *spv.Ru try rt.dumpResultsTable(allocator, &writer.interface); } -fn writeDescriptorSets(self: *Self, rt: *spv.Runtime) !void { - sets: for (self.state.sets[0..], 0..) |set, set_index| { - if (set == null) - continue :sets; - - bindings: for (set.?.descriptors[0..], 0..) |binding, binding_index| { - switch (binding) { - .buffer => |buffer_data_array| for (buffer_data_array, 0..) |buffer_data, descriptor_index| { - if (buffer_data.object) |buffer| { - const map = buffer.mapAsSliceWithOffset(u8, buffer_data.offset, buffer_data.size) catch continue :bindings; - try rt.writeDescriptorSet( - map, - @as(u32, @intCast(set_index)), - @as(u32, @intCast(binding_index)), - @as(u32, @intCast(descriptor_index)), - ); - } - }, - .image => |image_data_array| for (image_data_array, 0..) |image_data, descriptor_index| { - if (image_data.object) |image_view| { - const addr: usize = @intFromPtr(image_view); - try rt.writeDescriptorSet( - std.mem.asBytes(&addr), - @as(u32, @intCast(set_index)), - @as(u32, @intCast(binding_index)), - @as(u32, @intCast(descriptor_index)), - ); - } - }, - .texel_buffer => |texel_data_array| for (texel_data_array, 0..) |texel_data, descriptor_index| { - if (texel_data.object) |buffer_view| { - const addr: usize = @intFromPtr(buffer_view); - try rt.writeDescriptorSet( - std.mem.asBytes(&addr), - @as(u32, @intCast(set_index)), - @as(u32, @intCast(binding_index)), - @as(u32, @intCast(descriptor_index)), - ); - } - }, - else => {}, - } - } - } -} - fn setupWorkgroupBuiltins( self: *Self, rt: *spv.Runtime, diff --git a/src/soft/device/Device.zig b/src/soft/device/Device.zig index 98db38b..06c47e1 100644 --- a/src/soft/device/Device.zig +++ b/src/soft/device/Device.zig @@ -2,6 +2,7 @@ const std = @import("std"); const vk = @import("vulkan"); const base = @import("base"); const lib = @import("../lib.zig"); +const spv = @import("spv"); const SoftDescriptorSet = @import("../SoftDescriptorSet.zig"); const SoftDevice = @import("../SoftDevice.zig"); @@ -60,3 +61,49 @@ pub fn setup(self: *Self, device: *SoftDevice) void { self.compute = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.compute)]); self.renderer = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.graphics)]); } + +pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void { + sets: for (state.sets[0..], 0..) |set, set_index| { + if (set == null) + continue :sets; + + bindings: for (set.?.descriptors[0..], 0..) |binding, binding_index| { + switch (binding) { + .buffer => |buffer_data_array| for (buffer_data_array, 0..) |buffer_data, descriptor_index| { + if (buffer_data.object) |buffer| { + const map = buffer.mapAsSliceWithOffset(u8, buffer_data.offset, buffer_data.size) catch continue :bindings; + try rt.writeDescriptorSet( + map, + @as(u32, @intCast(set_index)), + @as(u32, @intCast(binding_index)), + @as(u32, @intCast(descriptor_index)), + ); + } + }, + .image => |image_data_array| for (image_data_array, 0..) |image_data, descriptor_index| { + if (image_data.object) |image_view| { + const addr: usize = @intFromPtr(image_view); + try rt.writeDescriptorSet( + std.mem.asBytes(&addr), + @as(u32, @intCast(set_index)), + @as(u32, @intCast(binding_index)), + @as(u32, @intCast(descriptor_index)), + ); + } + }, + .texel_buffer => |texel_data_array| for (texel_data_array, 0..) |texel_data, descriptor_index| { + if (texel_data.object) |buffer_view| { + const addr: usize = @intFromPtr(buffer_view); + try rt.writeDescriptorSet( + std.mem.asBytes(&addr), + @as(u32, @intCast(set_index)), + @as(u32, @intCast(binding_index)), + @as(u32, @intCast(descriptor_index)), + ); + } + }, + else => {}, + } + } + } +} diff --git a/src/soft/device/Renderer.zig b/src/soft/device/Renderer.zig index f6a95bc..087d23f 100644 --- a/src/soft/device/Renderer.zig +++ b/src/soft/device/Renderer.zig @@ -4,7 +4,8 @@ const base = @import("base"); const zm = base.zm; const spv = @import("spv"); -const PipelineState = @import("Device.zig").PipelineState; +const ExecutionDevice = @import("Device.zig"); +const PipelineState = ExecutionDevice.PipelineState; const BoundedAllocator = @import("BoundedAllocator.zig"); const SoftBuffer = @import("../SoftBuffer.zig"); @@ -182,11 +183,11 @@ fn drawCall(self: *Self, bounded_allocator: *BoundedAllocator, vertex_count: usi const pipeline = self.state.pipeline orelse return VkError.InvalidPipelineDrv; const vertex_shader = pipeline.stages.getPtrAssertContains(.vertex); for (vertex_shader.runtimes[0..]) |*runtime| { - writeDescriptorSets(&draw_call, &runtime.rt) catch return VkError.Unknown; + ExecutionDevice.writeDescriptorSets(self.state, &runtime.rt) catch return VkError.Unknown; } const fragment_shader = pipeline.stages.getPtrAssertContains(.fragment); for (fragment_shader.runtimes[0..]) |*runtime| { - writeDescriptorSets(&draw_call, &runtime.rt) catch return VkError.Unknown; + ExecutionDevice.writeDescriptorSets(self.state, &runtime.rt) catch return VkError.Unknown; } self.vertexShaderStage(allocator, &draw_call, vertex_count, instance_count, first_vertex, first_instance, indices) catch |err| { @@ -307,38 +308,3 @@ fn resolveScissor(self: *Self, scissor_index: usize) VkError!vk.Rect2D { return VkError.Unknown; } - -fn writeDescriptorSets(draw_call: *DrawCall, rt: *spv.Runtime) !void { - sets: for (draw_call.renderer.state.sets[0..], 0..) |set, set_index| { - if (set == null) - continue :sets; - - bindings: for (set.?.descriptors[0..], 0..) |binding, binding_index| { - switch (binding) { - .buffer => |buffer_data_array| for (buffer_data_array, 0..) |buffer_data, descriptor_index| { - if (buffer_data.object) |buffer| { - const map = buffer.mapAsSliceWithOffset(u8, buffer_data.offset, buffer_data.size) catch continue :bindings; - try rt.writeDescriptorSet( - map, - @as(u32, @intCast(set_index)), - @as(u32, @intCast(binding_index)), - @as(u32, @intCast(descriptor_index)), - ); - } - }, - .image => |image_data_array| for (image_data_array, 0..) |image_data, descriptor_index| { - if (image_data.object) |image_view| { - const addr: usize = @intFromPtr(image_view); - try rt.writeDescriptorSet( - std.mem.asBytes(&addr), - @as(u32, @intCast(set_index)), - @as(u32, @intCast(binding_index)), - @as(u32, @intCast(descriptor_index)), - ); - } - }, - else => {}, - } - } - } -} diff --git a/src/soft/device/blitter.zig b/src/soft/device/blitter.zig index e2bece7..693a9f3 100644 --- a/src/soft/device/blitter.zig +++ b/src/soft/device/blitter.zig @@ -649,7 +649,7 @@ pub fn writeFloat4(color: F32x4, map: []u8, dst_format: vk.Format) void { .r8_snorm, .r8_unorm, .s8_uint, - => map[0] = @intFromFloat(@round(color[0] * 255.0)), + => map[0] = @intFromFloat(@round(color[0] * std.math.maxInt(u8))), .r16_sint, .r16_uint, @@ -692,6 +692,13 @@ pub fn writeFloat4(color: F32x4, map: []u8, dst_format: vk.Format) void { .r32g32b32a32_sfloat => std.mem.bytesAsValue(F32x4, map).* = color, + .r5g6b5_unorm_pack16 => { + const r: u5 = @intFromFloat(@round(color[0] * std.math.maxInt(u5))); + const g: u6 = @intFromFloat(@round(color[1] * std.math.maxInt(u6))); + const b: u5 = @intFromFloat(@round(color[2] * std.math.maxInt(u5))); + std.mem.bytesAsValue(u16, map[0..]).* = (@as(u16, r) << 11) | (@as(u16, g) << 5) | @as(u16, b); + }, + else => base.unsupported("Blitter: write float to destination format {any}", .{dst_format}), } } diff --git a/src/soft/device/fragment.zig b/src/soft/device/fragment.zig index eb9d649..b8c1192 100644 --- a/src/soft/device/fragment.zig +++ b/src/soft/device/fragment.zig @@ -4,7 +4,7 @@ const base = @import("base"); const zm = base.zm; const spv = @import("spv"); -const lib = @import("../lib.zig"); +const VertexInterpolation = @import("rasterizer/common.zig").VertexInterpolation; const Renderer = @import("Renderer.zig"); const SoftImage = @import("../SoftImage.zig"); @@ -12,7 +12,13 @@ const SoftImage = @import("../SoftImage.zig"); const VkError = base.VkError; const SpvRuntimeError = spv.Runtime.RuntimeError; -pub fn shaderInvocation(allocator: std.mem.Allocator, draw_call: *Renderer.DrawCall, batch_id: usize, position: zm.F32x4, inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][]const u8) SpvRuntimeError!zm.F32x4 { +pub fn shaderInvocation( + allocator: std.mem.Allocator, + draw_call: *Renderer.DrawCall, + batch_id: usize, + position: zm.F32x4, + inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation, +) SpvRuntimeError!zm.F32x4 { const io = draw_call.renderer.device.interface.io(); _ = position; @@ -34,8 +40,9 @@ pub fn shaderInvocation(allocator: std.mem.Allocator, draw_call: *Renderer.DrawC SpvRuntimeError.NotFound => continue, else => return err, }; - try rt.writeInput(inputs[location], result_word); - allocator.free(inputs[location]); + try rt.writeInput(inputs[location].blob, result_word); + if (inputs[location].free_responsability) + allocator.free(inputs[location].blob); } rt.callEntryPoint(allocator, entry) catch |err| switch (err) { diff --git a/src/soft/device/rasterizer/common.zig b/src/soft/device/rasterizer/common.zig index d3189ed..72a8195 100644 --- a/src/soft/device/rasterizer/common.zig +++ b/src/soft/device/rasterizer/common.zig @@ -17,6 +17,11 @@ pub const RenderTargetAccess = struct { format: vk.Format, }; +pub const VertexInterpolation = struct { + blob: []const u8, + free_responsability: bool, +}; + pub fn scissorContainsPixel(scissor: vk.Rect2D, x: i32, y: i32) bool { const min_x: i64 = @as(i64, scissor.offset.x); const min_y: i64 = @as(i64, scissor.offset.y); @@ -41,8 +46,8 @@ pub fn interpolateVertexOutputs( b0: f32, b1: f32, b2: f32, -) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS][]u8 { - var inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][]u8 = undefined; +) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation { + var inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation = undefined; for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| { const out0 = v0.outputs[location] orelse continue; @@ -50,7 +55,7 @@ pub fn interpolateVertexOutputs( const out2 = v2.outputs[location] orelse continue; if (out0.interpolation_type == .flat or out0.blob.len == 0) { - inputs[location] = out0.blob; + inputs[location] = .{ .blob = out0.blob, .free_responsability = false }; continue; } @@ -75,13 +80,18 @@ pub fn interpolateVertexOutputs( if (byte_index < len) @memcpy(input[byte_index..], out0.blob[byte_index..len]); - inputs[location] = input; + inputs[location] = .{ .blob = input, .free_responsability = true }; } return inputs; } -pub fn interpolateLineOutputs(allocator: std.mem.Allocator, v0: *const Renderer.Vertex, v1: *const Renderer.Vertex, t: f32) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS][]u8 { +pub fn interpolateLineOutputs( + allocator: std.mem.Allocator, + v0: *const Renderer.Vertex, + v1: *const Renderer.Vertex, + t: f32, +) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation { return interpolateVertexOutputs(allocator, v0, v1, v0, 1.0 - t, t, 0.0); } diff --git a/src/vulkan/wsi/clients/wayland.zig b/src/vulkan/wsi/clients/wayland.zig index e692a01..a3f056e 100644 --- a/src/vulkan/wsi/clients/wayland.zig +++ b/src/vulkan/wsi/clients/wayland.zig @@ -65,10 +65,7 @@ pub fn load() VkError!void { if (ref_count.load(.monotonic) != 0) return; - module = std.DynLib.open("libwayland-client.so.0") catch { - _ = ref_count.fetchSub(1, .monotonic); - return VkError.Unknown; - }; + module = std.DynLib.open("libwayland-client.so.0") catch return VkError.Unknown; errdefer module.close(); errdefer std.log.scoped(.WaylandClient).err("Could not open 'libwayland-client.so.0': {s}", .{std.c.dlerror() orelse "unknown error"}); @@ -94,7 +91,7 @@ pub fn unload() void { } } -pub fn wl_registry_bind(registry: *wl_registry, name: u32, interface: *const wl_interface, version: u32) callconv(.c) ?*wl_proxy { +pub fn wl_registry_bind(registry: *wl_registry, name: u32, interface: *const wl_interface, version: u32) ?*wl_proxy { return wl_proxy_marshal_flags( @ptrCast(@alignCast(registry)), WL_REGISTRY_BIND, @@ -108,7 +105,7 @@ pub fn wl_registry_bind(registry: *wl_registry, name: u32, interface: *const wl_ ); } -pub fn wl_display_get_registry(display: *wl_display) callconv(.c) ?*wl_registry { +pub fn wl_display_get_registry(display: *wl_display) ?*wl_registry { return @ptrCast(@alignCast(wl_proxy_marshal_flags( @ptrCast(@alignCast(display)), WL_DISPLAY_GET_REGISTRY, @@ -119,7 +116,7 @@ pub fn wl_display_get_registry(display: *wl_display) callconv(.c) ?*wl_registry ))); } -pub fn wl_registry_add_listener(registry: *wl_registry, listener: *const wl_registry_listener, data: ?*anyopaque) callconv(.c) c_int { +pub fn wl_registry_add_listener(registry: *wl_registry, listener: *const wl_registry_listener, data: ?*anyopaque) c_int { return wl_proxy_add_listener(@ptrCast(@alignCast(registry)), @ptrCast(@alignCast(@constCast(listener))), data); } @@ -136,7 +133,7 @@ pub fn wl_shm_create_pool(shm: *wl_shm, fd: i32, size: i32) callconv(.c) ?*wl_sh ))); } -pub fn wl_shm_pool_destroy(shm_pool: *wl_shm_pool) callconv(.c) void { +pub fn wl_shm_pool_destroy(shm_pool: *wl_shm_pool) void { _ = wl_proxy_marshal_flags( @ptrCast(@alignCast(shm_pool)), WL_SHM_POOL_DESTROY, @@ -146,7 +143,7 @@ pub fn wl_shm_pool_destroy(shm_pool: *wl_shm_pool) callconv(.c) void { ); } -pub fn wl_shm_pool_create_buffer(shm_pool: *wl_shm_pool, offset: i32, width: i32, height: i32, stride: i32, format: u32) callconv(.c) ?*wl_buffer { +pub fn wl_shm_pool_create_buffer(shm_pool: *wl_shm_pool, offset: i32, width: i32, height: i32, stride: i32, format: u32) ?*wl_buffer { return @ptrCast(@alignCast(wl_proxy_marshal_flags( @ptrCast(@alignCast(shm_pool)), WL_SHM_POOL_CREATE_BUFFER, @@ -162,7 +159,7 @@ pub fn wl_shm_pool_create_buffer(shm_pool: *wl_shm_pool, offset: i32, width: i32 ))); } -pub fn wl_buffer_destroy(buffer: *wl_buffer) callconv(.c) void { +pub fn wl_buffer_destroy(buffer: *wl_buffer) void { _ = wl_proxy_marshal_flags( @ptrCast(@alignCast(buffer)), WL_BUFFER_DESTROY, @@ -172,7 +169,7 @@ pub fn wl_buffer_destroy(buffer: *wl_buffer) callconv(.c) void { ); } -pub fn wl_surface_attach(surface: *wl_surface, buffer: *wl_buffer, x: i32, y: i32) callconv(.c) void { +pub fn wl_surface_attach(surface: *wl_surface, buffer: *wl_buffer, x: i32, y: i32) void { _ = wl_proxy_marshal_flags( @ptrCast(@alignCast(surface)), WL_SURFACE_ATTACH, @@ -185,7 +182,7 @@ pub fn wl_surface_attach(surface: *wl_surface, buffer: *wl_buffer, x: i32, y: i3 ); } -pub fn wl_surface_damage(surface: *wl_surface, x: i32, y: i32, width: i32, height: i32) callconv(.c) void { +pub fn wl_surface_damage(surface: *wl_surface, x: i32, y: i32, width: i32, height: i32) void { _ = wl_proxy_marshal_flags( @ptrCast(@alignCast(surface)), WL_SURFACE_DAMAGE, @@ -199,7 +196,7 @@ pub fn wl_surface_damage(surface: *wl_surface, x: i32, y: i32, width: i32, heigh ); } -pub fn wl_surface_commit(surface: *wl_surface) callconv(.c) void { +pub fn wl_surface_commit(surface: *wl_surface) void { _ = wl_proxy_marshal_flags( @ptrCast(@alignCast(surface)), WL_SURFACE_COMMIT,