implementing proper graphics pipeline creations
Build / build (push) Successful in 1m8s
Test / build_and_test (push) Successful in 25m29s

This commit is contained in:
2026-04-24 02:41:37 +02:00
parent 2a427c0b51
commit 5fc7d561fc
8 changed files with 161 additions and 80 deletions
+82 -33
View File
@@ -32,6 +32,7 @@ const Stages = enum {
};
interface: Interface,
runtimes_allocator: std.heap.ArenaAllocator,
stages: std.EnumMap(Stages, Shader),
pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.ComputePipelineCreateInfo) VkError!*Self {
@@ -50,6 +51,10 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
const device_allocator = soft_device.device_allocator.allocator();
var runtimes_allocator_arena: std.heap.ArenaAllocator = .init(device_allocator);
errdefer runtimes_allocator_arena.deinit();
const runtimes_allocator = runtimes_allocator_arena.allocator();
const instance: *SoftInstance = @alignCast(@fieldParentPtr("interface", device.instance));
const runtimes_count = switch (instance.threaded.async_limit) {
.nothing => 1,
@@ -62,22 +67,17 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
self.* = .{
.interface = interface,
.runtimes_allocator = runtimes_allocator_arena,
.stages = std.EnumMap(Stages, Shader).init(.{
.compute = blk: {
var shader: Shader = undefined;
soft_module.ref();
shader.module = soft_module;
const runtimes = device_allocator.alloc(spv.Runtime, runtimes_count) catch return VkError.OutOfHostMemory;
errdefer {
for (runtimes) |*runtime| {
runtime.deinit(device_allocator);
}
device_allocator.free(runtimes);
}
const runtimes = runtimes_allocator.alloc(spv.Runtime, runtimes_count) catch return VkError.OutOfHostMemory;
for (runtimes) |*runtime| {
runtime.* = spv.Runtime.init(device_allocator, &soft_module.module) catch |err| {
runtime.* = spv.Runtime.init(runtimes_allocator, &soft_module.module) catch |err| {
std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)});
return VkError.Unknown;
};
@@ -85,7 +85,7 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
if (specialization.p_map_entries) |map| {
const data: []const u8 = @as([*]const u8, @ptrCast(@alignCast(specialization.p_data)))[0..specialization.data_size];
for (map[0..], 0..specialization.map_entry_count) |entry, _| {
runtime.addSpecializationInfo(device_allocator, .{
runtime.addSpecializationInfo(runtimes_allocator, .{
.id = @intCast(entry.constant_id),
.offset = @intCast(entry.offset),
.size = @intCast(entry.size),
@@ -96,7 +96,9 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
}
shader.runtimes = runtimes;
shader.entry = device_allocator.dupe(u8, std.mem.span(info.stage.p_name)) catch return VkError.OutOfHostMemory;
shader.entry = runtimes_allocator.dupe(u8, std.mem.span(info.stage.p_name)) catch return VkError.OutOfHostMemory;
std.log.scoped(.ComputePipeline).debug("Created {d} runtimes for compute stage", .{runtimes_count});
break :blk shader;
},
}),
@@ -114,6 +116,13 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
.destroy = destroy,
};
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
const device_allocator = soft_device.device_allocator.allocator();
var runtimes_allocator_arena: std.heap.ArenaAllocator = .init(device_allocator);
errdefer runtimes_allocator_arena.deinit();
const runtimes_allocator = runtimes_allocator_arena.allocator();
const instance: *SoftInstance = @alignCast(@fieldParentPtr("interface", device.instance));
const runtimes_count = switch (instance.threaded.async_limit) {
.nothing => 1,
@@ -124,36 +133,76 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
},
};
const runtimes = allocator.alloc(spv.Runtime, runtimes_count) catch return VkError.OutOfHostMemory;
errdefer allocator.free(runtimes);
//for (runtimes) |*runtime| {
// runtime.* = spv.Runtime.init() catch |err| {
// std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)});
// return VkError.Unknown;
// };
//}
self.* = .{
.interface = interface,
.stages = std.enums.EnumMap(Stages, Shader).init(.{}),
.runtimes_allocator = runtimes_allocator_arena,
.stages = std.EnumMap(Stages, Shader).init(.{}),
};
if (info.p_stages) |stages| {
for (stages[0..], 0..info.stage_count) |stage, _| {
var shader: Shader = undefined;
const module = try NonDispatchable(ShaderModule).fromHandleObject(stage.module);
const soft_module: *SoftShaderModule = @alignCast(@fieldParentPtr("interface", module));
soft_module.ref();
shader.module = soft_module;
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| {
std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)});
return VkError.Unknown;
};
if (stage.p_specialization_info) |specialization| {
if (specialization.p_map_entries) |map| {
const data: []const u8 = @as([*]const u8, @ptrCast(@alignCast(specialization.p_data)))[0..specialization.data_size];
for (map[0..], 0..specialization.map_entry_count) |entry, _| {
runtime.addSpecializationInfo(runtimes_allocator, .{
.id = @intCast(entry.constant_id),
.offset = @intCast(entry.offset),
.size = @intCast(entry.size),
}, data) catch return VkError.OutOfHostMemory;
}
}
}
}
shader.runtimes = runtimes;
shader.entry = runtimes_allocator.dupe(u8, std.mem.span(stage.p_name)) catch return VkError.OutOfHostMemory;
std.log.scoped(.GraphicsPipeline).debug("Created {d} runtimes for:", .{runtimes_count});
if (stage.stage.contains(.{ .vertex_bit = true })) {
std.log.scoped(.GraphicsPipeline).debug("> Vertex stage", .{});
self.stages.put(.vertex, shader);
} else if (stage.stage.contains(.{ .fragment_bit = true })) {
std.log.scoped(.GraphicsPipeline).debug("> Fragment stage", .{});
self.stages.put(.fragment, shader);
} else if (stage.stage.contains(.{ .tessellation_control_bit = true })) {
std.log.scoped(.GraphicsPipeline).debug("> Tessellation control stage", .{});
self.stages.put(.tessellation_control, shader);
} else if (stage.stage.contains(.{ .tessellation_evaluation_bit = true })) {
std.log.scoped(.GraphicsPipeline).debug("> Tessellation evaluation stage", .{});
self.stages.put(.tessellation_evaluation, shader);
} else if (stage.stage.contains(.{ .geometry_bit = true })) {
std.log.scoped(.GraphicsPipeline).debug("> Geometry stage", .{});
self.stages.put(.geometry, shader);
} else {
std.log.scoped(.GraphicsPipeline).err("> invalid stage", .{});
return VkError.Unknown;
}
}
} else {
return VkError.ValidationFailed;
}
return self;
}
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
const device_allocator = soft_device.device_allocator.allocator();
var it = self.stages.iterator();
while (it.next()) |stage| {
for (stage.value.runtimes) |*runtime| {
runtime.deinit(device_allocator);
}
device_allocator.free(stage.value.runtimes);
device_allocator.free(stage.value.entry);
stage.value.module.unref(allocator);
}
self.runtimes_allocator.deinit();
allocator.destroy(self);
}