adding base blit
All checks were successful
Test / build_and_test (push) Successful in 55m18s
Build / build (push) Successful in 1m54s

This commit is contained in:
2026-04-14 02:46:25 +02:00
parent 95e8edabe0
commit ee0ffbe09d
7 changed files with 62 additions and 41 deletions

View File

@@ -41,6 +41,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
.begin = begin,
.bindDescriptorSets = bindDescriptorSets,
.bindPipeline = bindPipeline,
.blitImage = blitImage,
.clearColorImage = clearColorImage,
.copyBuffer = copyBuffer,
.copyBufferToImage = copyBufferToImage,
@@ -162,7 +163,37 @@ pub fn bindPipeline(interface: *Interface, bind_point: vk.PipelineBindPoint, pip
self.commands.append(allocator, Command.from(cmd)) catch return VkError.OutOfHostMemory;
}
pub fn clearColorImage(interface: *Interface, image: *base.Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, range: vk.ImageSubresourceRange) VkError!void {
pub fn blitImage(interface: *Interface, src: *base.Image, _: vk.ImageLayout, dst: *base.Image, _: vk.ImageLayout, regions: []const vk.ImageBlit, filter: vk.Filter) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
src: *const SoftImage,
dst: *SoftImage,
regions: []const vk.ImageBlit,
filter: vk.Filter,
pub fn execute(impl: *const Impl, device: *ExecutionDevice) VkError!void {
for (impl.regions[0..]) |region| {
try device.blitter.blitRegion(impl.src, impl.dst, region);
}
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{
.src = @alignCast(@fieldParentPtr("interface", src)),
.dst = @alignCast(@fieldParentPtr("interface", dst)),
.regions = allocator.dupe(vk.ImageBlit, regions) catch return VkError.OutOfHostMemory, // Will be freed on cmdbuf reset or destroy
.filter = filter,
};
self.commands.append(allocator, Command.from(cmd)) catch return VkError.OutOfHostMemory;
}
pub fn clearColorImage(interface: *Interface, image: *base.Image, _: vk.ImageLayout, color: *const vk.ClearColorValue, range: vk.ImageSubresourceRange) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
@@ -170,12 +201,12 @@ pub fn clearColorImage(interface: *Interface, image: *base.Image, layout: vk.Ima
const Impl = @This();
image: *SoftImage,
layout: vk.ImageLayout,
clear_color: vk.ClearColorValue,
range: vk.ImageSubresourceRange,
pub fn execute(impl: *const Impl, _: *ExecutionDevice) VkError!void {
try impl.image.clearRange(impl.clear_color, impl.range);
pub fn execute(impl: *const Impl, device: *ExecutionDevice) VkError!void {
const clear_format = try impl.image.getClearFormat();
try device.blitter.clear(.{ .color = impl.clear_color }, clear_format, impl.image, impl.image.interface.format, impl.range, null);
}
};
@@ -183,7 +214,6 @@ pub fn clearColorImage(interface: *Interface, image: *base.Image, layout: vk.Ima
errdefer allocator.destroy(cmd);
cmd.* = .{
.image = @alignCast(@fieldParentPtr("interface", image)),
.layout = layout,
.clear_color = color.*,
.range = range,
};

View File

@@ -5,7 +5,6 @@ const builtin = @import("builtin");
const config = @import("config");
const SoftQueue = @import("SoftQueue.zig");
const Blitter = @import("device/Blitter.zig");
pub const SoftBinarySemaphore = @import("SoftBinarySemaphore.zig");
pub const SoftBuffer = @import("SoftBuffer.zig");
@@ -44,7 +43,6 @@ const DeviceAllocator = struct {
interface: Interface,
device_allocator: if (config.debug_allocator) std.heap.DebugAllocator(.{}) else DeviceAllocator,
workers: std.Thread.Pool,
blitter: Blitter,
pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
@@ -85,7 +83,6 @@ pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocato
.interface = interface,
.device_allocator = if (config.debug_allocator) .init else .{},
.workers = undefined,
.blitter = .init,
};
self.workers.init(.{ .allocator = self.device_allocator.allocator() }) catch |err| return switch (err) {

View File

@@ -42,21 +42,13 @@ pub fn getMemoryRequirements(_: *Interface, requirements: *vk.MemoryRequirements
requirements.alignment = lib.MEMORY_REQUIREMENTS_IMAGE_ALIGNMENT;
}
inline fn clear(self: *Self, pixel: vk.ClearValue, format: vk.Format, view_format: vk.Format, range: vk.ImageSubresourceRange, area: ?vk.Rect2D) VkError!void {
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", self.interface.owner));
try soft_device.blitter.clear(pixel, format, self, view_format, range, area);
}
pub fn clearRange(self: *Self, color: vk.ClearColorValue, range: vk.ImageSubresourceRange) VkError!void {
std.debug.assert(range.aspect_mask == vk.ImageAspectFlags{ .color_bit = true });
const clear_format: vk.Format = if (base.vku.vkuFormatIsSINT(@intCast(@intFromEnum(self.interface.format))))
pub fn getClearFormat(self: *Self) VkError!vk.Format {
return if (base.vku.vkuFormatIsSINT(@intCast(@intFromEnum(self.interface.format))))
.r32g32b32a32_sint
else if (base.vku.vkuFormatIsUINT(@intCast(@intFromEnum(self.interface.format))))
.r32g32b32a32_uint
else
.r32g32b32a32_sfloat;
try self.clear(.{ .color = color }, clear_format, self.interface.format, range, null);
}
/// Based on SwiftShader vk::Image::copyTo
@@ -311,13 +303,13 @@ pub fn copy(
}
}
fn getTexelMemoryOffsetInSubresource(self: *const Self, offset: vk.Offset3D, subresource: vk.ImageSubresource) usize {
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) +
@as(usize, @intCast(offset.x)) * base.format.texelSize(base.format.fromAspect(self.interface.format, subresource.aspect_mask));
}
fn getTexelMemoryOffset(self: *const Self, offset: vk.Offset3D, subresource: vk.ImageSubresource) VkError!usize {
pub fn getTexelMemoryOffset(self: *const Self, offset: vk.Offset3D, subresource: vk.ImageSubresource) VkError!usize {
return self.getTexelMemoryOffsetInSubresource(offset, subresource) + try self.getSubresourceOffset(subresource.aspect_mask, subresource.mip_level, subresource.array_layer);
}
@@ -372,7 +364,7 @@ fn getTotalSizeForAspect(interface: *const Interface, aspect_mask: vk.ImageAspec
return size * self.interface.array_layers;
}
fn getLayerSize(self: *const Self, aspect_mask: vk.ImageAspectFlags) usize {
pub fn getLayerSize(self: *const Self, aspect_mask: vk.ImageAspectFlags) usize {
var size: usize = 0;
for (0..self.interface.mip_levels) |mip_level| {
size += self.getMultiSampledLevelSize(aspect_mask, @intCast(mip_level));
@@ -380,15 +372,15 @@ fn getLayerSize(self: *const Self, aspect_mask: vk.ImageAspectFlags) usize {
return size;
}
inline fn getMultiSampledLevelSize(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
pub inline fn getMultiSampledLevelSize(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
return self.getMipLevelSize(aspect_mask, mip_level) * self.interface.samples.toInt();
}
inline fn getMipLevelSize(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
pub inline fn getMipLevelSize(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
return self.getSliceMemSizeForMipLevel(aspect_mask, mip_level) * self.getMipLevelExtent(mip_level).depth;
}
fn getMipLevelExtent(self: *const Self, mip_level: u32) vk.Extent3D {
pub fn getMipLevelExtent(self: *const Self, mip_level: u32) vk.Extent3D {
var extent: vk.Extent3D = .{
.width = self.interface.extent.width >> @intCast(mip_level),
.height = self.interface.extent.height >> @intCast(mip_level),
@@ -402,13 +394,13 @@ fn getMipLevelExtent(self: *const Self, mip_level: u32) vk.Extent3D {
return extent;
}
fn getSliceMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
pub fn getSliceMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
const mip_extent = self.getMipLevelExtent(mip_level);
const format = self.interface.formatFromAspect(aspect_mask);
return base.format.sliceMemSize(format, mip_extent.width, mip_extent.height);
}
fn getRowPitchMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
pub fn getRowPitchMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
const mip_extent = self.getMipLevelExtent(mip_level);
const format = self.interface.formatFromAspect(aspect_mask);
return base.format.pitchMemSize(format, mip_extent.width);

View File

@@ -11,11 +11,7 @@ pub const SoftImageView = @import("../SoftImageView.zig");
const Self = @This();
blit_mutex: std.Thread.Mutex,
pub const init: Self = .{
.blit_mutex = .{},
};
pub const init: Self = .{};
pub fn clear(self: *Self, pixel: vk.ClearValue, format: vk.Format, dest: *SoftImage, view_format: vk.Format, range: vk.ImageSubresourceRange, area: ?vk.Rect2D) VkError!void {
const dst_format = base.format.fromAspect(view_format, range.aspect_mask);
@@ -104,3 +100,9 @@ fn fastClear(self: *Self, clear_value: vk.ClearValue, clear_format: vk.Format, d
}
return false;
}
pub fn blitRegion(_: *Self, src: *const SoftImage, dst: *SoftImage, region: vk.ImageBlit) VkError!void {
_ = src;
_ = dst;
_ = region;
}

View File

@@ -6,6 +6,7 @@ const SoftDescriptorSet = @import("../SoftDescriptorSet.zig");
const SoftDevice = @import("../SoftDevice.zig");
const SoftPipeline = @import("../SoftPipeline.zig");
const Blitter = @import("Blitter.zig");
const ComputeRoutines = @import("ComputeRoutines.zig");
const PipelineState = @import("PipelineState.zig");
@@ -13,6 +14,8 @@ const VkError = base.VkError;
const Self = @This();
blitter: Blitter,
compute_routines: ComputeRoutines,
/// .graphics = 0
@@ -20,6 +23,7 @@ compute_routines: ComputeRoutines,
pipeline_states: [2]PipelineState,
pub const init: Self = .{
.blitter = .init,
.compute_routines = undefined,
.pipeline_states = undefined,
};

View File

@@ -40,6 +40,7 @@ pub const DispatchTable = struct {
begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void,
bindDescriptorSets: *const fn (*Self, vk.PipelineBindPoint, u32, [lib.VULKAN_MAX_DESCRIPTOR_SETS]?*DescriptorSet, []const u32) VkError!void,
bindPipeline: *const fn (*Self, vk.PipelineBindPoint, *Pipeline) VkError!void,
blitImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, []const vk.ImageBlit, vk.Filter) VkError!void,
clearColorImage: *const fn (*Self, *Image, vk.ImageLayout, *const vk.ClearColorValue, vk.ImageSubresourceRange) VkError!void,
copyBuffer: *const fn (*Self, *Buffer, *Buffer, []const vk.BufferCopy) VkError!void,
copyBufferToImage: *const fn (*Self, *Buffer, *Image, vk.ImageLayout, []const vk.BufferImageCopy) VkError!void,
@@ -148,6 +149,10 @@ pub inline fn bindPipeline(self: *Self, bind_point: vk.PipelineBindPoint, pipeli
try self.dispatch_table.bindPipeline(self, bind_point, pipeline);
}
pub inline fn blitImage(self: *Self, src: *Image, src_layout: vk.ImageLayout, dst: *Image, dst_layout: vk.ImageLayout, regions: []const vk.ImageBlit, filter: vk.Filter) VkError!void {
try self.dispatch_table.blitImage(self, src, src_layout, dst, dst_layout, regions, filter);
}
pub inline fn clearColorImage(self: *Self, image: *Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, ranges: []const vk.ImageSubresourceRange) VkError!void {
for (ranges) |range| {
try self.dispatch_table.clearColorImage(self, image, layout, color, range);

View File

@@ -1735,16 +1735,7 @@ pub export fn strollCmdBlitImage(
const src = NonDispatchable(Image).fromHandleObject(p_src_image) catch |err| return errorLogger(err);
const dst = NonDispatchable(Image).fromHandleObject(p_dst_image) catch |err| return errorLogger(err);
notImplementedWarning();
_ = cmd;
_ = src;
_ = src_layout;
_ = dst;
_ = dst_layout;
_ = count;
_ = regions;
_ = filter;
cmd.blitImage(src, src_layout, dst, dst_layout, regions[0..count], filter) catch |err| return errorLogger(err);
}
pub export fn strollCmdClearAttachments(p_cmd: vk.CommandBuffer, attachment_count: u32, attachments: [*]const vk.ClearAttachment, rect_count: u32, rects: [*]const vk.ClearRect) callconv(vk.vulkan_call_conv) void {