adding some opcodes
Some checks failed
Build / build (push) Has been cancelled
Test / build_and_test (push) Has been cancelled

This commit is contained in:
2026-03-11 01:28:33 +01:00
parent ffa1f56089
commit 857e877f33
7 changed files with 110 additions and 50 deletions

View File

@@ -59,8 +59,9 @@
.lazy = true,
},
.SPIRV_Interpreter = .{
.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#ad013d23fcf287d7354a05251ad0140f5fb883f7",
.hash = "SPIRV_Interpreter-0.0.1-ajmpnwSPAwD5VW4PJc1fUX0Q7niFovZyIHfhM7jZ2kkB",
//.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#1a48af468d345d8786cbb9b7d9f308f8832cbcd0",
//.hash = "SPIRV_Interpreter-0.0.1-ajmpn8CQAwD6-6jsLx5nODWFc4lAUvVTuZVVHop1X3-m",
.path = "../SPIRV-Interpreter",
},
},

View File

@@ -71,18 +71,24 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
allocator.destroy(self);
}
pub fn execute(self: *Self, device: *ExecutionDevice) VkError!void {
pub fn execute(self: *Self, device: *ExecutionDevice) void {
self.interface.submit() catch return;
defer self.interface.finish() catch {};
for (self.commands.items) |command| {
try command.vtable.execute(command.ptr, device);
command.vtable.execute(command.ptr, device) catch |err| {
base.errors.errorLoggerContext(err, "the software execution device");
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
return; // Should we return or continue ? Maybe device lost ?
};
}
}
pub fn begin(interface: *Interface, _: *const vk.CommandBufferBeginInfo) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self.command_allocator.reset(.free_all);
// No-op
_ = interface;
}
pub fn end(interface: *Interface) VkError!void {

View File

@@ -13,17 +13,22 @@ const NonDispatchable = base.NonDispatchable;
const Self = @This();
pub const Interface = base.DescriptorSet;
const DescriptorBuffer = struct {
object: ?*SoftBuffer,
offset: vk.DeviceSize,
size: vk.DeviceSize,
};
const Descriptor = union(enum) {
buffer: struct {
object: ?*SoftBuffer,
offset: vk.DeviceSize,
size: vk.DeviceSize,
},
buffer: []DescriptorBuffer,
image: struct {},
};
interface: Interface,
/// Memory containing actual binding descriptors and their array
heap: []u8,
descriptors: []Descriptor,
pub fn create(device: *base.Device, allocator: std.mem.Allocator, layout: *base.DescriptorSetLayout) VkError!*Self {
@@ -38,11 +43,38 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, layout: *base.
.write = write,
};
const descriptors = allocator.alloc(Descriptor, layout.bindings.len) catch return VkError.OutOfHostMemory;
errdefer allocator.free(descriptors);
const heap_size = blk: {
var size: usize = layout.bindings.len * @sizeOf(Descriptor);
for (layout.bindings) |binding| {
const struct_size: usize = switch (binding.descriptor_type) {
.storage_buffer, .storage_buffer_dynamic => @sizeOf(DescriptorBuffer),
else => 0,
};
size += binding.array_size * struct_size;
}
break :blk size;
};
const heap = allocator.alloc(u8, heap_size) catch return VkError.OutOfHostMemory;
errdefer allocator.free(heap);
var local_heap = std.heap.FixedBufferAllocator.init(heap);
const local_allocator = local_heap.allocator();
const descriptors = local_allocator.alloc(Descriptor, layout.bindings.len) catch return VkError.OutOfHostMemory;
for (descriptors, layout.bindings) |*descriptor, binding| {
switch (binding.descriptor_type) {
.storage_buffer, .storage_buffer_dynamic => descriptor.* = .{
.buffer = local_allocator.alloc(DescriptorBuffer, binding.array_size) catch return VkError.OutOfHostMemory,
},
else => {},
}
}
self.* = .{
.interface = interface,
.heap = heap,
.descriptors = descriptors,
};
return self;
@@ -56,7 +88,7 @@ pub fn copy(interface: *Interface, copy_data: vk.CopyDescriptorSet) VkError!void
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
allocator.free(self.descriptors);
allocator.free(self.heap);
allocator.destroy(self);
}
@@ -66,19 +98,17 @@ pub fn write(interface: *Interface, write_data: vk.WriteDescriptorSet) VkError!v
switch (write_data.descriptor_type) {
.storage_buffer, .storage_buffer_dynamic => {
for (write_data.p_buffer_info, 0..write_data.descriptor_count) |buffer_info, i| {
const desc = &self.descriptors[write_data.dst_binding + i];
const desc = &self.descriptors[write_data.dst_binding].buffer[i];
desc.* = .{
.buffer = .{
.object = null,
.offset = buffer_info.offset,
.size = buffer_info.range,
},
.object = null,
.offset = buffer_info.offset,
.size = buffer_info.range,
};
if (buffer_info.buffer != .null_handle) {
const buffer = try NonDispatchable(Buffer).fromHandleObject(buffer_info.buffer);
desc.buffer.object = @as(*SoftBuffer, @alignCast(@fieldParentPtr("interface", buffer)));
if (desc.buffer.size == vk.WHOLE_SIZE) {
desc.buffer.size = if (buffer.memory) |memory| memory.size - desc.buffer.offset else return VkError.InvalidDeviceMemoryDrv;
desc.object = @as(*SoftBuffer, @alignCast(@fieldParentPtr("interface", buffer)));
if (desc.size == vk.WHOLE_SIZE) {
desc.size = if (buffer.memory) |memory| memory.size - desc.offset else return VkError.InvalidDeviceMemoryDrv;
}
}
}

View File

@@ -104,12 +104,7 @@ fn taskRunner(self: *Self, info: Interface.SubmitInfo, p_fence: ?*base.Fence, ru
for (info.command_buffers.items) |command_buffer| {
const soft_command_buffer: *SoftCommandBuffer = @alignCast(@fieldParentPtr("interface", command_buffer));
soft_command_buffer.execute(&execution_device) catch |err| {
base.errors.errorLoggerContext(err, "the software execution device");
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
};
soft_command_buffer.execute(&execution_device);
}
if (p_fence) |fence| {

View File

@@ -35,7 +35,13 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
.use_simd_vectors_specializations = !std.process.hasEnvVarConstant(lib.NO_SHADER_SIMD_ENV_NAME),
}) catch |err| switch (err) {
spv.Module.ModuleError.OutOfMemory => return VkError.OutOfHostMemory,
else => return VkError.ValidationFailed,
else => {
std.log.scoped(.@"SPIR-V module").err("module creation catched a '{s}'", .{@errorName(err)});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
return VkError.ValidationFailed;
},
},
.ref_count = std.atomic.Value(usize).init(1),
};

View File

@@ -2,6 +2,7 @@ const std = @import("std");
const vk = @import("vulkan");
const base = @import("base");
const spv = @import("spv");
const lib = @import("../lib.zig");
const PipelineState = @import("PipelineState.zig");
@@ -52,18 +53,35 @@ pub fn dispatch(self: *Self, group_count_x: u32, group_count_y: u32, group_count
var wg: std.Thread.WaitGroup = .{};
for (0..@min(self.batch_size, group_count)) |batch_id| {
self.device.workers.spawnWg(&wg, runWrapper, .{
RunData{
.self = self,
.batch_id = batch_id,
.group_count = group_count,
.group_count_x = @as(usize, @intCast(group_count_x)),
.group_count_y = @as(usize, @intCast(group_count_y)),
.group_count_z = @as(usize, @intCast(group_count_z)),
.invocations_per_workgroup = invocations_per_workgroup,
.pipeline = pipeline,
},
});
if (std.process.hasEnvVarConstant(lib.SINGLE_THREAD_COMPUTE_EXECUTION_ENV_NAME)) {
@branchHint(.cold); // Should only be reached for debugging
runWrapper(
RunData{
.self = self,
.batch_id = batch_id,
.group_count = group_count,
.group_count_x = @as(usize, @intCast(group_count_x)),
.group_count_y = @as(usize, @intCast(group_count_y)),
.group_count_z = @as(usize, @intCast(group_count_z)),
.invocations_per_workgroup = invocations_per_workgroup,
.pipeline = pipeline,
},
);
} else {
self.device.workers.spawnWg(&wg, runWrapper, .{
RunData{
.self = self,
.batch_id = batch_id,
.group_count = group_count,
.group_count_x = @as(usize, @intCast(group_count_x)),
.group_count_y = @as(usize, @intCast(group_count_y)),
.group_count_z = @as(usize, @intCast(group_count_z)),
.invocations_per_workgroup = invocations_per_workgroup,
.pipeline = pipeline,
},
});
}
}
self.device.workers.waitAndWork(&wg);
}
@@ -135,14 +153,17 @@ fn writeDescriptorSets(self: *Self, rt: *spv.Runtime) !void {
bindings: for (set.?.descriptors[0..], 0..) |binding, binding_index| {
switch (binding) {
.buffer => |buffer_data| if (buffer_data.object) |buffer| {
const memory = if (buffer.interface.memory) |memory| memory else continue :bindings;
const map: []u8 = @as([*]u8, @ptrCast(try memory.map(buffer_data.offset, buffer_data.size)))[0..buffer_data.size];
try rt.writeDescriptorSet(
map,
@as(u32, @intCast(set_index)),
@as(u32, @intCast(binding_index)),
);
.buffer => |buffer_data_array| for (buffer_data_array, 0..) |buffer_data, descriptor_index| {
if (buffer_data.object) |buffer| {
const memory = if (buffer.interface.memory) |memory| memory else continue :bindings;
const map: []u8 = @as([*]u8, @ptrCast(try memory.map(buffer_data.offset, buffer_data.size)))[0..buffer_data.size];
try rt.writeDescriptorSet(
map,
@as(u32, @intCast(set_index)),
@as(u32, @intCast(binding_index)),
@as(u32, @intCast(descriptor_index)),
);
}
},
else => {},
}

View File

@@ -41,6 +41,7 @@ pub const DRIVER_VERSION = vk.makeApiVersion(0, 0, 0, 1);
pub const DEVICE_ID = 0x600DCAFE;
pub const NO_SHADER_SIMD_ENV_NAME = "STROLL_SOFT_NO_SIMD";
pub const SINGLE_THREAD_COMPUTE_EXECUTION_ENV_NAME = "STROLL_SINGLE_THREAD_COMPUTE_EXECUTION";
/// Generic system memory.
pub const MEMORY_TYPE_GENERIC_BIT = 0;