diff --git a/build.zig b/build.zig index 457d56b..98c1a88 100644 --- a/build.zig +++ b/build.zig @@ -606,6 +606,7 @@ fn addPhiDaemon(b: *std.Build, optimize: std.builtin.OptimizeMode, cc: []const u const sources = [_][]const u8{ "src/phi/mic/main.c", + "src/phi/mic/Blitter.c", "src/phi/mic/Buffer.c", "src/phi/mic/CommandBuffer.c", "src/phi/mic/Daemon.c", diff --git a/src/phi/PhiCommandBuffer.zig b/src/phi/PhiCommandBuffer.zig index 79e4cc0..0055501 100644 --- a/src/phi/PhiCommandBuffer.zig +++ b/src/phi/PhiCommandBuffer.zig @@ -181,12 +181,12 @@ pub fn bindVertexBuffer(interface: *Interface, index: usize, buffer: *base.Buffe pub fn blitImage(interface: *Interface, src: *base.Image, src_layout: vk.ImageLayout, dst: *base.Image, dst_layout: vk.ImageLayout, regions: []const vk.ImageBlit, filter: vk.Filter) VkError!void { const self: *Self = @alignCast(@fieldParentPtr("interface", interface)); self.cmd_count += 1; - _ = src; + _ = src_layout; - _ = dst; _ = dst_layout; - _ = regions; - _ = filter; + + for (regions) |region| + try copy.blitImage(self, src, dst, region, filter); } pub fn clearAttachment(interface: *Interface, attachment: vk.ClearAttachment, rect: vk.ClearRect) VkError!void { diff --git a/src/phi/copy_commands.zig b/src/phi/copy_commands.zig index 08f6917..1c656f4 100644 --- a/src/phi/copy_commands.zig +++ b/src/phi/copy_commands.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const vk = @import("vulkan"); const base = @import("base"); const lib = @import("lib.zig"); @@ -416,3 +417,116 @@ pub fn copyImage(cmd: *PhiCommandBuffer, src: *base.Image, dst: *base.Image, reg region, ); } + +pub fn blitImage(cmd: *PhiCommandBuffer, src: *base.Image, dst: *base.Image, region: vk.ImageBlit, filter: vk.Filter) VkError!void { + const src_memory = try remoteImageMemory(src); + const dst_memory = try remoteImageMemory(dst); + + var src_offset_0 = region.src_offsets[0]; + var src_offset_1 = region.src_offsets[1]; + + var dst_offset_0 = region.dst_offsets[0]; + var dst_offset_1 = region.dst_offsets[1]; + + if (dst_offset_0.x > dst_offset_1.x) { + std.mem.swap(i32, &dst_offset_0.x, &dst_offset_1.x); + std.mem.swap(i32, &src_offset_0.x, &src_offset_1.x); + } + + if (dst_offset_0.y > dst_offset_1.y) { + std.mem.swap(i32, &dst_offset_0.y, &dst_offset_1.y); + std.mem.swap(i32, &src_offset_0.y, &src_offset_1.y); + } + + if (dst_offset_0.z > dst_offset_1.z) { + std.mem.swap(i32, &dst_offset_0.z, &dst_offset_1.z); + std.mem.swap(i32, &src_offset_0.z, &src_offset_1.z); + } + + const src_extent = try getMipExtent(src, region.src_subresource.mip_level); + + const step_x = @as(f32, @floatFromInt(src_offset_1.x - src_offset_0.x)) / @as(f32, @floatFromInt(dst_offset_1.x - dst_offset_0.x)); + const step_y = @as(f32, @floatFromInt(src_offset_1.y - src_offset_0.y)) / @as(f32, @floatFromInt(dst_offset_1.y - dst_offset_0.y)); + + const step_z = @as(f32, @floatFromInt(src_offset_1.z - src_offset_0.z)) / @as(f32, @floatFromInt(dst_offset_1.z - dst_offset_0.z)); + const src_x0 = @as(f32, @floatFromInt(src_offset_0.x)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.x))) * step_x; + + const src_y0 = @as(f32, @floatFromInt(src_offset_0.y)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.y))) * step_y; + const src_z0 = @as(f32, @floatFromInt(src_offset_0.z)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.z))) * step_z; + + const src_layout = try src.getSubresourceLayout(.{ + .aspect_mask = region.src_subresource.aspect_mask, + .mip_level = region.src_subresource.mip_level, + .array_layer = region.src_subresource.base_array_layer, + }); + + const dst_layout = try dst.getSubresourceLayout(.{ + .aspect_mask = region.dst_subresource.aspect_mask, + .mip_level = region.dst_subresource.mip_level, + .array_layer = region.dst_subresource.base_array_layer, + }); + + const src_format = src.formatFromAspect(region.src_subresource.aspect_mask); + const dst_format = dst.formatFromAspect(region.dst_subresource.aspect_mask); + + const apply_filter = (filter != .nearest); + const resolve_srgb = src.samples.toInt() > 1 and + dst.samples.toInt() == 1 and + base.format.isSrgb(src_format) and + base.format.isSrgb(dst_format); + const allow_srgb_conversion = apply_filter or resolve_srgb or base.format.isSrgb(src_format) != base.format.isSrgb(dst_format); + + const clamp_to_edge = src_offset_0.x < 0 or + src_offset_0.y < 0 or + @as(u32, @intCast(src_offset_1.x)) > src_extent.width or + @as(u32, @intCast(src_offset_1.y)) > src_extent.height or + (filter != .nearest and ((src_x0 < 0.5) or (src_y0 < 0.5))); + + try cmd.appendCommand( + proto.PhiCmdBlitImage, + proto.PHI_CMD_BLIT_IMAGE, + .{ + .src_memory = @intCast(src_memory.remote_handle), + .src_offset = src.memory_offset + src_layout.offset, + .src_row_pitch = src_layout.row_pitch, + .src_slice_pitch = src_layout.depth_pitch, + .src_layer_pitch = src_layout.array_pitch, + + .dst_memory = @intCast(dst_memory.remote_handle), + .dst_offset = dst.memory_offset + dst_layout.offset, + .dst_row_pitch = dst_layout.row_pitch, + .dst_slice_pitch = dst_layout.depth_pitch, + .dst_layer_pitch = dst_layout.array_pitch, + + .dst_format = @intCast(@as(i32, @intFromEnum(dst_format))), + .src_format = @intCast(@as(i32, @intFromEnum(src_format))), + + .src_width = src_extent.width, + .src_height = src_extent.height, + .src_depth = src_extent.depth, + + .dst_x0 = dst_offset_0.x, + .dst_y0 = dst_offset_0.y, + .dst_z0 = dst_offset_0.z, + .dst_x1 = dst_offset_1.x, + .dst_y1 = dst_offset_1.y, + .dst_z1 = dst_offset_1.z, + + .src_x0 = src_x0, + .src_y0 = src_y0, + .src_z0 = src_z0, + + .step_x = step_x, + .step_y = step_y, + .step_z = step_z, + + .layer_count = region.dst_subresource.layer_count, + + .filter = @intCast(@intFromEnum(filter)), + .clamp_to_edge = @intFromBool(clamp_to_edge), + .allow_srgb_conversion = @intFromBool(allow_srgb_conversion), + + .reserved = 0, + }, + ); +} diff --git a/src/phi/mic/Blitter.c b/src/phi/mic/Blitter.c new file mode 100644 index 0000000..94171e2 --- /dev/null +++ b/src/phi/mic/Blitter.c @@ -0,0 +1,14 @@ +#include +#include + +PhiStatus BlitImage(const PhiCmdBlitImage* command) +{ + const Memory* src_memory = (const Memory*)(uintptr_t)command->src_memory; + Memory* dst_memory = (Memory*)(uintptr_t)command->dst_memory; + + for(uint32_t layer = 0; layer < command->layer_count; ++layer) + { + } + + return PHI_STATUS_OK; +} diff --git a/src/phi/mic/Blitter.h b/src/phi/mic/Blitter.h new file mode 100644 index 0000000..a60d5ba --- /dev/null +++ b/src/phi/mic/Blitter.h @@ -0,0 +1,9 @@ +#define APE_PHI_BLITTER_H +#ifndef APE_PHI_BUFFER_H + +#include +#include + +PhiStatus BlitImage(const PhiCmdBlitImage* command); + +#endif diff --git a/src/phi/mic/Image.c b/src/phi/mic/Image.c index 1806c22..d09bb5c 100644 --- a/src/phi/mic/Image.c +++ b/src/phi/mic/Image.c @@ -1,6 +1,8 @@ +#include "Commands.h" #include #include +#include #include #include #include @@ -331,18 +333,6 @@ static PhiStatus CopyImageRegion(const PhiCmdCopyImage* command) return PHI_STATUS_OK; } -static PhiStatus ExecuteCopyImage(PhiCommandReader* reader) -{ - PhiCmdCopyImage command; - - PhiStatus status = ReadCommandData(reader, &command, sizeof(command)); - - if(status != PHI_STATUS_OK) - return status; - - return CopyImageRegion(&command); -} - int IsImageCommand(const PhiCmdHeader* header) { switch((PhiCmdType)header->type) @@ -350,6 +340,7 @@ int IsImageCommand(const PhiCmdHeader* header) case PHI_CMD_COPY_BUFFER_TO_IMAGE: case PHI_CMD_COPY_IMAGE_TO_BUFFER: case PHI_CMD_COPY_IMAGE: + case PHI_CMD_BLIT_IMAGE: return 1; default: @@ -364,7 +355,23 @@ PhiStatus ExecuteImageCommand(PhiCommandReader* reader, const PhiCmdHeader* head case PHI_CMD_COPY_BUFFER_TO_IMAGE: case PHI_CMD_COPY_IMAGE_TO_BUFFER: case PHI_CMD_COPY_IMAGE: - return ExecuteCopyImage(reader); + { + PhiCmdCopyImage command; + PhiStatus status = ReadCommandData(reader, &command, sizeof(command)); + if(status != PHI_STATUS_OK) + return status; + return CopyImageRegion(&command); + } + + case PHI_CMD_BLIT_IMAGE: + { + + PhiCmdBlitImage command; + PhiStatus status = ReadCommandData(reader, &command, sizeof(command)); + if(status != PHI_STATUS_OK) + return status; + return BlitImage(&command); + } default: return PHI_STATUS_BAD_MESSAGE; diff --git a/src/phi/shared/Commands.h b/src/phi/shared/Commands.h index 27abc48..ec2b574 100644 --- a/src/phi/shared/Commands.h +++ b/src/phi/shared/Commands.h @@ -14,6 +14,8 @@ typedef enum PhiCmdType PHI_CMD_COPY_BUFFER_TO_IMAGE = 2, PHI_CMD_COPY_IMAGE_TO_BUFFER = 3, PHI_CMD_COPY_IMAGE = 4, + + PHI_CMD_BLIT_IMAGE = 5, } PhiCmdType; typedef struct PhiCmdHeader @@ -65,4 +67,48 @@ typedef struct PhiCmdCopyImage uint32_t layer_count; } PhiCmdCopyImage; +typedef struct PhiCmdBlitImage +{ + uintptr_t src_memory; + uint64_t src_offset; + uint64_t src_row_pitch; + uint64_t src_slice_pitch; + uint64_t src_layer_pitch; + + uintptr_t dst_memory; + uint64_t dst_offset; + uint64_t dst_row_pitch; + uint64_t dst_slice_pitch; + uint64_t dst_layer_pitch; + + uint32_t src_format; + uint32_t dst_format; + + uint32_t src_width; + uint32_t src_height; + uint32_t src_depth; + + int32_t dst_x0; + int32_t dst_y0; + int32_t dst_z0; + int32_t dst_x1; + int32_t dst_y1; + int32_t dst_z1; + + float src_x0; + float src_y0; + float src_z0; + + float step_x; + float step_y; + float step_z; + + uint32_t layer_count; + + uint8_t filter; + uint8_t clamp_to_edge; + uint8_t allow_srgb_conversion; + uint8_t reserved; +} PhiCmdBlitImage; + #endif diff --git a/src/phi/shared/Protocol.h b/src/phi/shared/Protocol.h index 3ea7bd7..86978fd 100644 --- a/src/phi/shared/Protocol.h +++ b/src/phi/shared/Protocol.h @@ -43,6 +43,129 @@ typedef enum PhiStatus PHI_STATUS_INVALID_ARGUMENT = 7, } PhiStatus; +typedef enum PhiFormat +{ + PHI_FORMAT_UNDEFINED = 0, + + PHI_FORMAT_R4G4_UNORM_PACK8 = 1, + PHI_FORMAT_R4G4B4A4_UNORM_PACK16 = 2, + PHI_FORMAT_B4G4R4A4_UNORM_PACK16 = 3, + PHI_FORMAT_R5G6B5_UNORM_PACK16 = 4, + PHI_FORMAT_B5G6R5_UNORM_PACK16 = 5, + PHI_FORMAT_R5G5B5A1_UNORM_PACK16 = 6, + PHI_FORMAT_B5G5R5A1_UNORM_PACK16 = 7, + PHI_FORMAT_A1R5G5B5_UNORM_PACK16 = 8, + PHI_FORMAT_R8_UNORM = 9, + PHI_FORMAT_R8_SNORM = 10, + PHI_FORMAT_R8_USCALED = 11, + PHI_FORMAT_R8_SSCALED = 12, + PHI_FORMAT_R8_UINT = 13, + PHI_FORMAT_R8_SINT = 14, + PHI_FORMAT_R8_SRGB = 15, + PHI_FORMAT_R8G8_UNORM = 16, + PHI_FORMAT_R8G8_SNORM = 17, + PHI_FORMAT_R8G8_USCALED = 18, + PHI_FORMAT_R8G8_SSCALED = 19, + PHI_FORMAT_R8G8_UINT = 20, + PHI_FORMAT_R8G8_SINT = 21, + PHI_FORMAT_R8G8_SRGB = 22, + PHI_FORMAT_R8G8B8_UNORM = 23, + PHI_FORMAT_R8G8B8_SNORM = 24, + PHI_FORMAT_R8G8B8_USCALED = 25, + PHI_FORMAT_R8G8B8_SSCALED = 26, + PHI_FORMAT_R8G8B8_UINT = 27, + PHI_FORMAT_R8G8B8_SINT = 28, + PHI_FORMAT_R8G8B8_SRGB = 29, + PHI_FORMAT_B8G8R8_UNORM = 30, + PHI_FORMAT_B8G8R8_SNORM = 31, + PHI_FORMAT_B8G8R8_USCALED = 32, + PHI_FORMAT_B8G8R8_SSCALED = 33, + PHI_FORMAT_B8G8R8_UINT = 34, + PHI_FORMAT_B8G8R8_SINT = 35, + PHI_FORMAT_B8G8R8_SRGB = 36, + PHI_FORMAT_R8G8B8A8_UNORM = 37, + PHI_FORMAT_R8G8B8A8_SNORM = 38, + PHI_FORMAT_R8G8B8A8_USCALED = 39, + PHI_FORMAT_R8G8B8A8_SSCALED = 40, + PHI_FORMAT_R8G8B8A8_UINT = 41, + PHI_FORMAT_R8G8B8A8_SINT = 42, + PHI_FORMAT_R8G8B8A8_SRGB = 43, + PHI_FORMAT_B8G8R8A8_UNORM = 44, + PHI_FORMAT_B8G8R8A8_SNORM = 45, + PHI_FORMAT_B8G8R8A8_USCALED = 46, + PHI_FORMAT_B8G8R8A8_SSCALED = 47, + PHI_FORMAT_B8G8R8A8_UINT = 48, + PHI_FORMAT_B8G8R8A8_SINT = 49, + PHI_FORMAT_B8G8R8A8_SRGB = 50, + PHI_FORMAT_A8B8G8R8_UNORM_PACK32 = 51, + PHI_FORMAT_A8B8G8R8_SNORM_PACK32 = 52, + PHI_FORMAT_A8B8G8R8_USCALED_PACK32 = 53, + PHI_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54, + PHI_FORMAT_A8B8G8R8_UINT_PACK32 = 55, + PHI_FORMAT_A8B8G8R8_SINT_PACK32 = 56, + PHI_FORMAT_A8B8G8R8_SRGB_PACK32 = 57, + PHI_FORMAT_A2R10G10B10_UNORM_PACK32 = 58, + PHI_FORMAT_A2R10G10B10_SNORM_PACK32 = 59, + PHI_FORMAT_A2R10G10B10_USCALED_PACK32 = 60, + PHI_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61, + PHI_FORMAT_A2R10G10B10_UINT_PACK32 = 62, + PHI_FORMAT_A2R10G10B10_SINT_PACK32 = 63, + PHI_FORMAT_A2B10G10R10_UNORM_PACK32 = 64, + PHI_FORMAT_A2B10G10R10_SNORM_PACK32 = 65, + PHI_FORMAT_A2B10G10R10_USCALED_PACK32 = 66, + PHI_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67, + PHI_FORMAT_A2B10G10R10_UINT_PACK32 = 68, + PHI_FORMAT_A2B10G10R10_SINT_PACK32 = 69, + PHI_FORMAT_R16_UNORM = 70, + PHI_FORMAT_R16_SNORM = 71, + PHI_FORMAT_R16_USCALED = 72, + PHI_FORMAT_R16_SSCALED = 73, + PHI_FORMAT_R16_UINT = 74, + PHI_FORMAT_R16_SINT = 75, + PHI_FORMAT_R16_SFLOAT = 76, + PHI_FORMAT_R16G16_UNORM = 77, + PHI_FORMAT_R16G16_SNORM = 78, + PHI_FORMAT_R16G16_USCALED = 79, + PHI_FORMAT_R16G16_SSCALED = 80, + PHI_FORMAT_R16G16_UINT = 81, + PHI_FORMAT_R16G16_SINT = 82, + PHI_FORMAT_R16G16_SFLOAT = 83, + PHI_FORMAT_R16G16B16_UNORM = 84, + PHI_FORMAT_R16G16B16_SNORM = 85, + PHI_FORMAT_R16G16B16_USCALED = 86, + PHI_FORMAT_R16G16B16_SSCALED = 87, + PHI_FORMAT_R16G16B16_UINT = 88, + PHI_FORMAT_R16G16B16_SINT = 89, + PHI_FORMAT_R16G16B16_SFLOAT = 90, + PHI_FORMAT_R16G16B16A16_UNORM = 91, + PHI_FORMAT_R16G16B16A16_SNORM = 92, + PHI_FORMAT_R16G16B16A16_USCALED = 93, + PHI_FORMAT_R16G16B16A16_SSCALED = 94, + PHI_FORMAT_R16G16B16A16_UINT = 95, + PHI_FORMAT_R16G16B16A16_SINT = 96, + PHI_FORMAT_R16G16B16A16_SFLOAT = 97, + PHI_FORMAT_R32_UINT = 98, + PHI_FORMAT_R32_SINT = 99, + PHI_FORMAT_R32_SFLOAT = 100, + PHI_FORMAT_R32G32_UINT = 101, + PHI_FORMAT_R32G32_SINT = 102, + PHI_FORMAT_R32G32_SFLOAT = 103, + PHI_FORMAT_R32G32B32_UINT = 104, + PHI_FORMAT_R32G32B32_SINT = 105, + PHI_FORMAT_R32G32B32_SFLOAT = 106, + PHI_FORMAT_R32G32B32A32_UINT = 107, + PHI_FORMAT_R32G32B32A32_SINT = 108, + PHI_FORMAT_R32G32B32A32_SFLOAT = 109, + PHI_FORMAT_B10G11R11_UFLOAT_PACK32 = 122, + PHI_FORMAT_D16_UNORM = 124, + PHI_FORMAT_X8_D24_UNORM_PACK32 = 125, + PHI_FORMAT_D32_SFLOAT = 126, + PHI_FORMAT_S8_UINT = 127, + PHI_FORMAT_D16_UNORM_S8_UINT = 128, + PHI_FORMAT_D24_UNORM_S8_UINT = 129, + PHI_FORMAT_D32_SFLOAT_S8_UINT = 130, +} PhiFormat; + typedef struct PhiMessageHeader { uint32_t magic; diff --git a/src/software/device/blitter.zig b/src/software/device/blitter.zig index c9c7a08..49e0d07 100644 --- a/src/software/device/blitter.zig +++ b/src/software/device/blitter.zig @@ -45,7 +45,7 @@ const BlitData = struct { width_ratio: f32, }; -fn computeOffset3D(x: usize, y: usize, z: usize, slice_bytes: usize, pitch_bytes: usize, texel_bytes: usize) usize { +inline fn computeOffset3D(x: usize, y: usize, z: usize, slice_bytes: usize, pitch_bytes: usize, texel_bytes: usize) usize { return z * slice_bytes + y * pitch_bytes + x * texel_bytes; }