diff --git a/build.zig.zon b/build.zig.zon index 397109d..0ec7b31 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -31,8 +31,8 @@ .hash = "zmath-0.11.0-dev-wjwivdMsAwD-xaLj76YHUq3t9JDH-X16xuMTmnDzqbu2", }, .SPIRV_Interpreter = .{ - .url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#cc041c967725d08d7312888167148c2241d7bf00", - .hash = "SPIRV_Interpreter-0.0.1-ajmpn3q0BAD_YB7eNEB3WUMUGEdjkmxsksEZ-Gxexrwc", + .url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#046b1c8f9e9a6f61498c58fa39fde8ec3d044d58", + .hash = "SPIRV_Interpreter-0.0.1-ajmpn-blBAAmIOGIbqCR3BWWY7QDcrsdZHdse-4OBxNF", .lazy = true, }, //.SPIRV_Interpreter = .{ diff --git a/src/soft/SoftDescriptorSet.zig b/src/soft/SoftDescriptorSet.zig index fa7c4e3..94e2e78 100644 --- a/src/soft/SoftDescriptorSet.zig +++ b/src/soft/SoftDescriptorSet.zig @@ -8,7 +8,6 @@ const Buffer = base.Buffer; const ImageView = base.ImageView; const SoftBuffer = @import("SoftBuffer.zig"); -const SoftImage = @import("SoftImage.zig"); const SoftImageView = @import("SoftImageView.zig"); const SoftSampler = @import("SoftSampler.zig"); @@ -29,7 +28,7 @@ const DescriptorTexture = struct { }; const DescriptorImage = struct { - object: ?*SoftImage, + object: ?*SoftImageView, }; const Descriptor = union(enum) { @@ -138,7 +137,7 @@ pub fn write(interface: *Interface, write_data: vk.WriteDescriptorSet) VkError!v desc.* = .{ .object = null }; if (image_info.image_view != .null_handle) { const image_view = try NonDispatchable(ImageView).fromHandleObject(image_info.image_view); - desc.object = @as(*SoftImage, @alignCast(@fieldParentPtr("interface", image_view.image))); + desc.object = @as(*SoftImageView, @alignCast(@fieldParentPtr("interface", image_view))); } } }, diff --git a/src/soft/SoftImage.zig b/src/soft/SoftImage.zig index b7417ee..12fc023 100644 --- a/src/soft/SoftImage.zig +++ b/src/soft/SoftImage.zig @@ -1,8 +1,11 @@ const std = @import("std"); const vk = @import("vulkan"); const base = @import("base"); - const lib = @import("lib.zig"); +const blitter = @import("device/blitter.zig"); + +const F32x4 = blitter.F32x4; +const U32x4 = blitter.U32x4; const VkError = base.VkError; const Device = base.Device; @@ -316,6 +319,38 @@ pub fn copy( } } +pub fn readFloat4(self: *Self, offset: vk.Offset3D, subresource: vk.ImageSubresource, format: vk.Format) VkError!F32x4 { + const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv; + const texel_size = base.format.texelSize(format); + const texel_offset = try self.getTexelMemoryOffset(offset, subresource); + const map: []const u8 = @as([*]u8, @ptrCast(try memory.map(self.interface.memory_offset + texel_offset, texel_size)))[0..texel_size]; + return blitter.readFloat4(map, format); +} + +pub fn readInt4(self: *Self, offset: vk.Offset3D, subresource: vk.ImageSubresource, format: vk.Format) VkError!U32x4 { + const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv; + const texel_size = base.format.texelSize(format); + const texel_offset = try self.getTexelMemoryOffset(offset, subresource); + const map: []const u8 = @as([*]u8, @ptrCast(try memory.map(self.interface.memory_offset + texel_offset, texel_size)))[0..texel_size]; + return blitter.readInt4(map, format); +} + +pub fn writeFloat4(self: *Self, offset: vk.Offset3D, subresource: vk.ImageSubresource, format: vk.Format, pixel: F32x4) VkError!void { + const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv; + const texel_size = base.format.texelSize(format); + const texel_offset = try self.getTexelMemoryOffset(offset, subresource); + const map: []u8 = @as([*]u8, @ptrCast(try memory.map(self.interface.memory_offset + texel_offset, texel_size)))[0..texel_size]; + blitter.writeFloat4(pixel, map, format); +} + +pub fn writeInt4(self: *Self, offset: vk.Offset3D, subresource: vk.ImageSubresource, format: vk.Format, pixel: U32x4) VkError!void { + const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv; + const texel_size = base.format.texelSize(format); + const texel_offset = try self.getTexelMemoryOffset(offset, subresource); + const map: []u8 = @as([*]u8, @ptrCast(try memory.map(self.interface.memory_offset + texel_offset, texel_size)))[0..texel_size]; + blitter.writeInt4(pixel, map, format); +} + pub fn getTexelMemoryOffsetInSubresource(self: *const Self, offset: vk.Offset3D, subresource: vk.ImageSubresource) usize { return @as(usize, @intCast(offset.z)) * self.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level) + @as(usize, @intCast(offset.y)) * self.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level) + diff --git a/src/soft/SoftPipeline.zig b/src/soft/SoftPipeline.zig index 928fd1e..b7841aa 100644 --- a/src/soft/SoftPipeline.zig +++ b/src/soft/SoftPipeline.zig @@ -3,13 +3,16 @@ const vk = @import("vulkan"); const base = @import("base"); const spv = @import("spv"); -const VkError = base.VkError; const Device = base.Device; +const VkError = base.VkError; +const SpvRuntimeError = spv.Runtime.RuntimeError; const NonDispatchable = base.NonDispatchable; const ShaderModule = base.ShaderModule; const SoftDevice = @import("SoftDevice.zig"); +const SoftImage = @import("SoftImage.zig"); +const SoftImageView = @import("SoftImageView.zig"); const SoftInstance = @import("SoftInstance.zig"); const SoftShaderModule = @import("SoftShaderModule.zig"); @@ -77,7 +80,16 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache: const runtimes = runtimes_allocator.alloc(spv.Runtime, runtimes_count) catch return VkError.OutOfHostMemory; for (runtimes) |*runtime| { - runtime.* = spv.Runtime.init(runtimes_allocator, &soft_module.module) catch |err| { + runtime.* = spv.Runtime.init( + runtimes_allocator, + &soft_module.module, + .{ + .readImageFloat4 = readImageFloat4, + .readImageInt4 = readImageInt4, + .writeImageFloat4 = writeImageFloat4, + .writeImageInt4 = writeImageInt4, + }, + ) catch |err| { std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)}); return VkError.Unknown; }; @@ -151,7 +163,16 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache: const runtimes = runtimes_allocator.alloc(spv.Runtime, runtimes_count) catch return VkError.OutOfHostMemory; for (runtimes) |*runtime| { - runtime.* = spv.Runtime.init(runtimes_allocator, &soft_module.module) catch |err| { + runtime.* = spv.Runtime.init( + runtimes_allocator, + &soft_module.module, + .{ + .readImageFloat4 = readImageFloat4, + .readImageInt4 = readImageInt4, + .writeImageFloat4 = writeImageFloat4, + .writeImageInt4 = writeImageInt4, + }, + ) catch |err| { std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)}); return VkError.Unknown; }; @@ -206,3 +227,89 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void { self.runtimes_allocator.deinit(); allocator.destroy(self); } + +fn readImageFloat4(context: *anyopaque, x: i32, y: i32, z: i32) SpvRuntimeError!spv.Runtime.Vec4(f32) { + const image_view: *SoftImageView = @ptrCast(@alignCast(context)); + const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.interface.image)); + const pixel = image.readFloat4( + .{ + .x = x, + .y = y, + .z = z, + }, + .{ + .aspect_mask = image_view.interface.subresource_range.aspect_mask, + .mip_level = image_view.interface.subresource_range.base_mip_level, + .array_layer = image_view.interface.subresource_range.base_array_layer, + }, + image_view.interface.format, + ) catch return SpvRuntimeError.Unknown; + return .{ + .x = pixel[0], + .y = pixel[1], + .z = pixel[2], + .w = pixel[3], + }; +} + +fn readImageInt4(context: *anyopaque, x: i32, y: i32, z: i32) SpvRuntimeError!spv.Runtime.Vec4(u32) { + const image_view: *SoftImageView = @ptrCast(@alignCast(context)); + const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.interface.image)); + const pixel = image.readInt4( + .{ + .x = x, + .y = y, + .z = z, + }, + .{ + .aspect_mask = image_view.interface.subresource_range.aspect_mask, + .mip_level = image_view.interface.subresource_range.base_mip_level, + .array_layer = image_view.interface.subresource_range.base_array_layer, + }, + image_view.interface.format, + ) catch return SpvRuntimeError.Unknown; + return .{ + .x = pixel[0], + .y = pixel[1], + .z = pixel[2], + .w = pixel[3], + }; +} + +fn writeImageFloat4(context: *anyopaque, x: i32, y: i32, z: i32, pixel: spv.Runtime.Vec4(f32)) SpvRuntimeError!void { + const image_view: *SoftImageView = @ptrCast(@alignCast(context)); + const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.interface.image)); + image.writeFloat4( + .{ + .x = x, + .y = y, + .z = z, + }, + .{ + .aspect_mask = image_view.interface.subresource_range.aspect_mask, + .mip_level = image_view.interface.subresource_range.base_mip_level, + .array_layer = image_view.interface.subresource_range.base_array_layer, + }, + image_view.interface.format, + .{ pixel.x, pixel.y, pixel.z, pixel.w }, + ) catch return SpvRuntimeError.Unknown; +} + +fn writeImageInt4(context: *anyopaque, x: i32, y: i32, z: i32, pixel: spv.Runtime.Vec4(u32)) SpvRuntimeError!void { + const image_view: *SoftImageView = @ptrCast(@alignCast(context)); + const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.interface.image)); + image.writeInt4( + .{ + .x = x, + .y = y, + .z = z, + }, + .{ + .aspect_mask = image_view.interface.subresource_range.aspect_mask, + .mip_level = image_view.interface.subresource_range.base_mip_level, + .array_layer = image_view.interface.subresource_range.base_array_layer, + }, + image_view.interface.format, + .{ pixel.x, pixel.y, pixel.z, pixel.w }, + ) catch return SpvRuntimeError.Unknown; +} diff --git a/src/soft/device/ComputeDispatcher.zig b/src/soft/device/ComputeDispatcher.zig index 57e4be8..6911fa3 100644 --- a/src/soft/device/ComputeDispatcher.zig +++ b/src/soft/device/ComputeDispatcher.zig @@ -189,11 +189,10 @@ fn writeDescriptorSets(self: *Self, rt: *spv.Runtime) !void { } }, .image => |image_data_array| for (image_data_array, 0..) |image_data, descriptor_index| { - if (image_data.object) |image| { - const memory = if (image.interface.memory) |memory| memory else continue :bindings; - const map: []u8 = @as([*]u8, @ptrCast(try memory.map(image.interface.memory_offset, try image.interface.getTotalSize())))[0..try image.interface.getTotalSize()]; + if (image_data.object) |image_view| { + const addr: usize = @intFromPtr(image_view); try rt.writeDescriptorSet( - map, + std.mem.asBytes(&addr), @as(u32, @intCast(set_index)), @as(u32, @intCast(binding_index)), @as(u32, @intCast(descriptor_index)), diff --git a/src/soft/device/Renderer.zig b/src/soft/device/Renderer.zig index bd18886..7228ce3 100644 --- a/src/soft/device/Renderer.zig +++ b/src/soft/device/Renderer.zig @@ -83,7 +83,6 @@ pub fn draw(self: *Self, vertex_count: usize, instance_count: usize, first_verte const render_target_view: *base.ImageView = (self.framebuffer orelse return).interface.attachments[0]; const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image)); - const render_target_memory = if (render_target.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv; var arena: std.heap.ArenaAllocator = .init(self.device.device_allocator.allocator()); defer arena.deinit(); @@ -122,10 +121,8 @@ pub fn draw(self: *Self, vertex_count: usize, instance_count: usize, first_verte } }; - const texel_size = base.format.texelSize(render_target_view.format); - for (draw_call.fragments) |fragment| { - const texel_offset = try render_target.getTexelMemoryOffset( + try render_target.writeFloat4( .{ .x = @intFromFloat(fragment.position[0]), .y = @intFromFloat(fragment.position[1]), @@ -136,9 +133,9 @@ pub fn draw(self: *Self, vertex_count: usize, instance_count: usize, first_verte .mip_level = render_target_view.subresource_range.base_mip_level, .array_layer = render_target_view.subresource_range.base_array_layer, }, + render_target_view.format, + fragment.color, ); - const map: []u8 = @as([*]u8, @ptrCast(try render_target_memory.map(render_target.interface.memory_offset + texel_offset, texel_size)))[0..texel_size]; - blitter.writeFloat4(fragment.color, map, render_target_view.format); } _ = first_vertex; diff --git a/src/soft/device/blitter.zig b/src/soft/device/blitter.zig index 8820f3c..8370b4c 100644 --- a/src/soft/device/blitter.zig +++ b/src/soft/device/blitter.zig @@ -10,8 +10,8 @@ const VkError = base.VkError; pub const SoftImage = @import("../SoftImage.zig"); pub const SoftImageView = @import("../SoftImageView.zig"); -const F32x4 = zm.F32x4; -const U32x4 = @Vector(4, u32); +pub const F32x4 = zm.F32x4; +pub const U32x4 = @Vector(4, u32); const State = struct { src_format: vk.Format,