ci skip
Build / build (push) Has been skipped
Test / build_and_test (push) Has been skipped

This commit is contained in:
2026-05-01 22:12:39 +02:00
parent 354c9891d6
commit f87fae29e8
13 changed files with 506 additions and 221 deletions
+47 -13
View File
@@ -49,32 +49,66 @@ pub fn getMemoryRequirements(interface: *Interface, requirements: *vk.MemoryRequ
pub fn copyBuffer(self: *const Self, dst: *Self, regions: []const vk.BufferCopy) VkError!void {
for (regions) |region| {
const src_memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
const dst_memory = if (dst.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
const src_map: []u8 = @as([*]u8, @ptrCast(try src_memory.map(self.interface.offset + region.src_offset, region.size)))[0..region.size];
const dst_map: []u8 = @as([*]u8, @ptrCast(try dst_memory.map(dst.interface.offset + region.dst_offset, region.size)))[0..region.size];
const src_map = try self.mapAsSliceWithAddedOffset(u8, region.src_offset, region.size);
const dst_map = try dst.mapAsSliceWithAddedOffset(u8, region.dst_offset, region.size);
@memcpy(dst_map, src_map);
src_memory.unmap();
dst_memory.unmap();
}
}
pub fn fillBuffer(self: *Self, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) VkError!void {
const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
var memory_map: []u32 = @as([*]u32, @ptrCast(@alignCast(try memory.map(offset, size))))[0..size];
var bytes = if (size == vk.WHOLE_SIZE) memory.size - offset else size;
const map = try self.mapAsSliceWithOffset(u32, offset, bytes);
var i: usize = 0;
while (bytes >= 4) : ({
bytes -= 4;
i += 1;
}) {
memory_map[i] = data;
map[i] = data;
}
memory.unmap();
}
pub inline fn mapAs(self: *const Self, comptime T: type) VkError!*T {
return self.mapAsWithAddedOffset(T, 0);
}
pub inline fn mapTo(self: *const Self, comptime T: type) VkError!T {
return self.mapToWithAddedOffset(T, 0);
}
pub inline fn mapAsSlice(self: *const Self, comptime T: type, size: usize) VkError![]T {
return self.mapAsSliceWithAddedOffset(T, 0, size);
}
pub inline fn mapAsWithAddedOffset(self: *const Self, comptime T: type, offset: usize) VkError!*T {
return self.mapAsWithOffset(T, self.interface.offset + offset);
}
pub inline fn mapToWithAddedOffset(self: *const Self, comptime T: type, offset: usize) VkError!T {
return self.mapToWithOffset(T, self.interface.offset + offset);
}
pub inline fn mapAsSliceWithAddedOffset(self: *const Self, comptime T: type, size: usize, offset: usize) VkError![]T {
return self.mapAsSliceWithOffset(T, self.interface.offset + offset, size);
}
pub fn mapAsWithOffset(self: *const Self, comptime T: type, offset: usize) VkError!*T {
const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
const map = @as([*]u8, @ptrCast(@alignCast(try memory.map(offset, @sizeOf(T)))))[0..@sizeOf(T)];
return @alignCast(std.mem.bytesAsValue(T, map));
}
pub fn mapToWithOffset(self: *const Self, comptime T: type, offset: usize) VkError!T {
const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
const map = @as([*]u8, @ptrCast(@alignCast(try memory.map(offset, @sizeOf(T)))))[0..@sizeOf(T)];
return std.mem.bytesToValue(T, map);
}
pub fn mapAsSliceWithOffset(self: *const Self, comptime T: type, offset: usize, size: usize) VkError![]T {
const memory = if (self.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
const map = @as([*]u8, @ptrCast(@alignCast(try memory.map(offset, size))))[0..size];
return @alignCast(std.mem.bytesAsSlice(T, map));
}
+99 -35
View File
@@ -61,6 +61,8 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
.dispatchIndirect = dispatchIndirect,
.draw = draw,
.drawIndexed = drawIndexed,
.drawIndexedIndirect = drawIndexedIndirect,
.drawIndirect = drawIndirect,
.end = end,
.endRenderPass = endRenderPass,
.executeCommands = executeCommands,
@@ -545,10 +547,8 @@ pub fn dispatchIndirect(interface: *Interface, buffer: *base.Buffer, offset: vk.
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
const size = 3 * @sizeOf(u32);
const memory = if (impl.buffer.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
const map: []u32 = @as([*]u32, @ptrCast(@alignCast(try memory.map(impl.offset, size))))[0..3];
try device.compute.dispatch(map[0], map[1], map[2]);
const command = try impl.buffer.mapAsWithOffset(vk.DispatchIndirectCommand, impl.offset);
try device.compute.dispatch(command.x, command.y, command.z);
}
};
@@ -561,37 +561,6 @@ pub fn dispatchIndirect(interface: *Interface, buffer: *base.Buffer, offset: vk.
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn drawIndexed(interface: *Interface, index_count: usize, instance_count: usize, first_index: usize, vertex_offset: usize, first_instance: usize) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
index_count: usize,
first_index: usize,
instance_count: usize,
first_instance: usize,
vertex_offset: usize,
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
try device.renderer.drawIndexed(impl.index_count, impl.instance_count, impl.first_index, impl.first_instance, impl.vertex_offset);
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{
.index_count = index_count,
.first_index = first_index,
.instance_count = instance_count,
.first_instance = first_instance,
.vertex_offset = vertex_offset,
};
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn draw(interface: *Interface, vertex_count: usize, instance_count: usize, first_vertex: usize, first_instance: usize) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
@@ -621,6 +590,101 @@ pub fn draw(interface: *Interface, vertex_count: usize, instance_count: usize, f
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn drawIndexed(interface: *Interface, index_count: usize, instance_count: usize, first_index: usize, vertex_offset: i32, first_instance: usize) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
index_count: usize,
first_index: usize,
instance_count: usize,
first_instance: usize,
vertex_offset: i32,
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
try device.renderer.drawIndexed(impl.index_count, impl.instance_count, impl.first_index, impl.first_instance, impl.vertex_offset);
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{
.index_count = index_count,
.first_index = first_index,
.instance_count = instance_count,
.first_instance = first_instance,
.vertex_offset = vertex_offset,
};
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn drawIndexedIndirect(interface: *Interface, buffer: *base.Buffer, offset: usize, count: usize, stride: usize) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
buffer: *SoftBuffer,
offset: usize,
count: usize,
stride: usize,
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
for (0..impl.count) |index| {
const command = try impl.buffer.mapAsWithOffset(vk.DrawIndexedIndirectCommand, impl.offset + index * impl.stride);
try device.renderer.drawIndexed(command.index_count, command.instance_count, command.first_index, command.first_instance, command.vertex_offset);
}
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{
.buffer = @alignCast(@fieldParentPtr("interface", buffer)),
.offset = offset,
.count = count,
.stride = stride,
};
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn drawIndirect(interface: *Interface, buffer: *base.Buffer, offset: usize, count: usize, stride: usize) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
buffer: *SoftBuffer,
offset: usize,
count: usize,
stride: usize,
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
for (0..impl.count) |index| {
const command = try impl.buffer.mapAsWithOffset(vk.DrawIndirectCommand, impl.offset + index * impl.stride);
try device.renderer.draw(command.vertex_count, command.instance_count, command.first_vertex, command.first_instance);
}
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{
.buffer = @alignCast(@fieldParentPtr("interface", buffer)),
.offset = offset,
.count = count,
.stride = stride,
};
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn endRenderPass(interface: *Interface) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
+1 -1
View File
@@ -13,7 +13,7 @@ const Self = @This();
pub const Interface = base.PhysicalDevice;
// Device name should always be the same so avoid reprocessing it multiple times
var device_name = [_]u8{0} ** vk.MAX_PHYSICAL_DEVICE_NAME_SIZE;
var device_name: [vk.MAX_PHYSICAL_DEVICE_NAME_SIZE]u8 = @splat(0);
interface: Interface,
+8 -8
View File
@@ -123,7 +123,7 @@ pub fn draw(self: *Self, vertex_count: usize, instance_count: usize, first_verte
try self.postVertexDraw(allocator, &draw_call);
}
pub fn drawIndexed(self: *Self, index_count: usize, instance_count: usize, first_index: usize, first_instance: usize, vertex_offset: usize) VkError!void {
pub fn drawIndexed(self: *Self, index_count: usize, instance_count: usize, first_index: usize, first_instance: usize, vertex_offset: i32) VkError!void {
const io = self.device.interface.io();
var arena: std.heap.ArenaAllocator = .init(self.device.device_allocator.allocator());
@@ -154,7 +154,7 @@ pub fn deinit(self: *Self) void {
_ = self;
}
fn vertexShaderStage(self: *Self, allocator: std.mem.Allocator, draw_call: *DrawCall, vertex_count: usize, instance_count: usize, first_vertex: usize, first_instance: usize, indices: ?[]const u32) !void {
fn vertexShaderStage(self: *Self, allocator: std.mem.Allocator, draw_call: *DrawCall, vertex_count: usize, instance_count: usize, first_vertex: usize, first_instance: usize, indices: ?[]const i32) !void {
const pipeline = self.state.pipeline orelse return;
const batch_size = (pipeline.stages.getPtr(.vertex) orelse return).runtimes.len;
@@ -196,11 +196,11 @@ fn postVertexDraw(self: *Self, allocator: std.mem.Allocator, draw_call: *DrawCal
};
for (draw_call.fragments) |fragment| {
render_target.writeFloat4(
try render_target.writeFloat4(
.{
.x = @intFromFloat(fragment.position[0]),
.y = @intFromFloat(fragment.position[1]),
.z = 0,
.z = 0, // FIXME
},
.{
.aspect_mask = render_target_view.subresource_range.aspect_mask,
@@ -209,7 +209,7 @@ fn postVertexDraw(self: *Self, allocator: std.mem.Allocator, draw_call: *DrawCal
},
render_target_view.format,
fragment.color,
) catch {};
);
}
}
@@ -342,7 +342,7 @@ fn fragmentShaderStage(self: *Self, draw_call: *DrawCall) !void {
wg.await(self.device.interface.io()) catch return VkError.DeviceLost;
}
fn readIndexBuffer(self: *Self, allocator: std.mem.Allocator, index_count: usize, first_index: usize, vertex_offset: usize) VkError![]u32 {
fn readIndexBuffer(self: *Self, allocator: std.mem.Allocator, index_count: usize, first_index: usize, vertex_offset: i32) VkError![]i32 {
const index_buffer = self.state.data.graphics.index_buffer;
const buffer = index_buffer.buffer;
const buffer_memory = if (buffer.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
@@ -355,7 +355,7 @@ fn readIndexBuffer(self: *Self, allocator: std.mem.Allocator, index_count: usize
const byte_size = index_count * index_size;
const index_memory: []const u8 = @as([*]const u8, @ptrCast(@alignCast(try buffer_memory.map(byte_offset, byte_size))))[0..byte_size];
const indices = allocator.alloc(u32, index_count) catch return VkError.OutOfDeviceMemory;
const indices = allocator.alloc(i32, index_count) catch return VkError.OutOfDeviceMemory;
for (indices, 0..) |*index, i| {
const offset = i * index_size;
const raw_index: u32 = switch (index_size) {
@@ -364,7 +364,7 @@ fn readIndexBuffer(self: *Self, allocator: std.mem.Allocator, index_count: usize
4 => @intCast(std.mem.readInt(u32, index_memory[offset..][0..4], .little)),
else => unreachable,
};
index.* = @intCast(vertex_offset + raw_index);
index.* = vertex_offset + @as(i32, @intCast(raw_index));
}
return indices;
+2 -2
View File
@@ -20,7 +20,7 @@ pub const RunData = struct {
vertex_count: usize,
first_vertex: usize,
first_instance: usize,
indices: ?[]const u32,
indices: ?[]const i32,
instance_index: usize,
draw_call: *Renderer.DrawCall,
};
@@ -44,7 +44,7 @@ inline fn run(data: RunData) !void {
var invocation_index: usize = data.batch_id;
while (invocation_index < data.vertex_count) : (invocation_index += data.batch_size) {
const vertex_index = if (data.indices) |indices| indices[invocation_index] else data.first_vertex + invocation_index;
const vertex_index: usize = if (data.indices) |indices| @intCast(indices[invocation_index]) else data.first_vertex + invocation_index;
const instance_index = data.first_instance + data.instance_index;
setupBuiltins(rt, vertex_index, instance_index) catch |err| switch (err) {