[Soft] removing SPIR-V interpreter fallback on IR interpreter fail
Mirror Gitea refs to GitHub / mirror (push) Successful in 20s
Test / build_and_test (push) Successful in 3m44s
Build / build (push) Successful in 5m1s

This commit is contained in:
2026-08-09 00:06:43 +02:00
parent f40e5b742d
commit e3e5fa4b18
16 changed files with 200 additions and 182 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ fn compileStage(allocator: std.mem.Allocator, info: *const vk.PipelineShaderStag
.graphics => if (expected_stage == .compute) return VkError.ValidationFailed,
}
const shader_module = base.NonDispatchable(base.ShaderModule).fromHandleObject(info.module) catch |err| return err;
const shader_module = try base.NonDispatchable(base.ShaderModule).fromHandleObject(info.module);
var module = shader_module.instantiateIr(allocator, .{
.entry_point = std.mem.span(info.p_name),
.stage = expected_stage,
+3 -1
View File
@@ -252,7 +252,9 @@ fn launchHostDaemon(instance: *base.Instance, allocator: std.mem.Allocator) VkEr
const local_path = std.fmt.allocPrint(allocator, "/tmp/ape_phi_device_{d}_{d}.host", .{ process_id, thread_id }) catch return VkError.OutOfHostMemory;
defer allocator.free(local_path);
errdefer std.Io.Dir.deleteFileAbsolute(io, local_path) catch {};
errdefer std.Io.Dir.deleteFileAbsolute(io, local_path) catch |err| {
std.log.scoped(.PhiDevice).warn("Failed to remove Phi host daemon after launch error: {s}", .{@errorName(err)});
};
std.Io.Dir.writeFile(.cwd(), io, .{
.sub_path = local_path,
+1 -1
View File
@@ -132,7 +132,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
.command_allocator = undefined,
.commands = .empty,
};
self.command_allocator = .init(interface.host_allocator.allocator());
self.command_allocator = .init(self.interface.host_allocator.allocator());
return self;
}
+1
View File
@@ -49,6 +49,7 @@ pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo)
.requestPhysicalDevices = requestPhysicalDevices,
.releasePhysicalDevices = releasePhysicalDevices,
.io = io,
.enumerate_drm_devices = false,
};
return &self.interface;
}
+21 -12
View File
@@ -48,13 +48,14 @@ const Runtime = struct {
rt: spv.Runtime,
};
const Shader = struct {
const SpvShader = struct {
module: *SoftShaderModule,
runtimes: []Runtime,
entry: []const u8,
interpreter: ?InterpreterShader,
};
const Shader = if (base.config.soft_ir_interpreter) InterpreterShader else SpvShader;
const Stages = enum {
vertex,
tessellation_control,
@@ -107,7 +108,10 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
};
self.stages.put(.compute, try createShader(allocator, device_allocator, runtimes_allocator, soft_cache, soft_module, &info.stage, runtimes_count));
std.log.scoped(.ComputePipeline).debug("Created {d} runtimes for compute stage", .{runtimes_count});
std.log.scoped(.ComputePipeline).debug("Created {d} {s} runtimes for compute stage", .{
runtimes_count,
if (comptime base.config.soft_ir_interpreter) "IR" else "SPIR-V",
});
return self;
}
@@ -152,7 +156,10 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
const soft_module: *SoftShaderModule = @alignCast(@fieldParentPtr("interface", module));
const shader = try createShader(allocator, device_allocator, runtimes_allocator, soft_cache, soft_module, &stage, runtimes_count);
std.log.scoped(.GraphicsPipeline).debug("Created {d} runtimes for:", .{runtimes_count});
std.log.scoped(.GraphicsPipeline).debug("Created {d} {s} runtimes for:", .{
runtimes_count,
if (comptime base.config.soft_ir_interpreter) "IR" else "SPIR-V",
});
if (stage.stage.contains(.{ .vertex_bit = true })) {
std.log.scoped(.GraphicsPipeline).debug("> Vertex stage", .{});
@@ -183,17 +190,20 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const device_allocator = interface.owner.device_allocator.allocator();
var it = self.stages.iterator();
if (comptime base.config.soft_ir_interpreter) {
while (it.next()) |entry|
entry.value.deinit();
} else {
const device_allocator = interface.owner.device_allocator.allocator();
while (it.next()) |entry| {
if (entry.value.interpreter) |*interpreter|
interpreter.deinit();
entry.value.module.unref(allocator);
for (entry.value.runtimes) |*runtime| {
runtime.rt.function_stack.clearAndFree(device_allocator); // Hacky to avoid leaks
}
}
}
self.runtimes_allocator.deinit();
allocator.destroy(self);
}
@@ -207,6 +217,9 @@ fn createShader(
stage: *const vk.PipelineShaderStageCreateInfo,
runtimes_count: usize,
) VkError!Shader {
if (comptime base.config.soft_ir_interpreter)
return InterpreterShader.compile(runtimes_allocator, module, stage, runtimes_count);
const entry = std.mem.span(stage.p_name);
const execution_model = executionModelForStage(stage.stage) orelse return VkError.Unknown;
const runtimes = runtimes_allocator.alloc(Runtime, runtimes_count) catch return VkError.OutOfDeviceMemory;
@@ -259,15 +272,11 @@ fn createShader(
}
}
var shader: Shader = .{
return .{
.module = module,
.runtimes = runtimes,
.entry = runtimes_allocator.dupe(u8, entry) catch return VkError.OutOfDeviceMemory,
.interpreter = null,
};
if (comptime base.config.soft_ir_interpreter)
shader.interpreter = try InterpreterShader.compile(runtimes_allocator, module, stage, runtimes_count);
return shader;
}
fn initRuntime(allocator: std.mem.Allocator, module: *SoftShaderModule, stage: *const vk.PipelineShaderStageCreateInfo, image_api: spv.Runtime.ImageAPI) VkError!spv.Runtime {
+37 -29
View File
@@ -71,10 +71,18 @@ pub fn dispatchBase(self: *Self, base_group_x: u32, base_group_y: u32, base_grou
const pipeline = self.state.pipeline orelse return VkError.InvalidPipelineDrv;
const shader = pipeline.stages.getPtr(.compute) orelse return VkError.InvalidPipelineDrv;
const io = self.device.interface.io();
const timer = std.Io.Timestamp.now(io, .real);
defer if (comptime base.config.logs != .none) {
const duration = timer.untilNow(io, .real);
const ms: f32 = @floatFromInt(duration.toMicroseconds());
std.log.scoped(.ComputeDispatcher).debug("Compute dispatch took {}ms using {s} interpreter", .{ ms / 1000, if (comptime base.config.soft_ir_interpreter) "IR" else "SPIR-V" });
};
if (comptime base.config.soft_ir_interpreter) {
if (shader.interpreter) |*interpreter_shader|
return ir_compute.dispatch(interpreter_shader, base_group_x, base_group_y, base_group_z, group_count_x, group_count_y, group_count_z);
}
return ir_compute.dispatch(shader, base_group_x, base_group_y, base_group_z, group_count_x, group_count_y, group_count_z);
} else {
const spv_module = &shader.module.module;
self.batch_size = if (spv_module.reflection_infos.has_atomics) 1 else shader.runtimes.len;
@@ -85,14 +93,6 @@ pub fn dispatchBase(self: *Self, base_group_x: u32, base_group_y: u32, base_grou
self.invocation_index.store(0, .monotonic);
const io = self.device.interface.io();
const timer = std.Io.Timestamp.now(io, .real);
defer if (comptime base.config.logs != .none) {
const duration = timer.untilNow(io, .real);
const ms: f32 = @floatFromInt(duration.toMicroseconds());
std.log.scoped(.ComputeDispatcher).debug("Compute dispatch took {}ms", .{ms / 1000});
};
var wg: std.Io.Group = .init;
for (0..@min(self.batch_size, group_count)) |batch_id| {
const run_data: RunData = .{
@@ -113,6 +113,7 @@ pub fn dispatchBase(self: *Self, base_group_x: u32, base_group_y: u32, base_grou
wg.async(self.device.interface.io(), runWrapper, .{run_data});
}
wg.await(self.device.interface.io()) catch return VkError.DeviceLost;
}
}
fn runWrapper(data: RunData) void {
@@ -138,17 +139,9 @@ inline fn run(data: RunData) !void {
var barrier_runtimes: []spv.Runtime = &.{};
var barrier_statuses: []spv.Runtime.EntryPointStatus = &.{};
if (uses_control_barrier) {
barrier_runtimes = try allocator.alloc(spv.Runtime, data.invocations_per_workgroup);
barrier_statuses = try allocator.alloc(spv.Runtime.EntryPointStatus, data.invocations_per_workgroup);
for (barrier_runtimes) |*barrier_rt| {
barrier_rt.* = try spv.Runtime.init(allocator, rt.mod, rt.image_api);
try barrier_rt.copySpecializationConstantsFrom(allocator, rt);
}
}
var initialized_barrier_runtimes: usize = 0;
defer {
for (barrier_runtimes) |*barrier_rt| {
for (barrier_runtimes[0..initialized_barrier_runtimes]) |*barrier_rt| {
barrier_rt.resetInvocation(allocator);
barrier_rt.deinit(allocator);
}
@@ -156,6 +149,19 @@ inline fn run(data: RunData) !void {
allocator.free(barrier_statuses);
}
if (uses_control_barrier) {
barrier_runtimes = try allocator.alloc(spv.Runtime, data.invocations_per_workgroup);
barrier_statuses = try allocator.alloc(spv.Runtime.EntryPointStatus, data.invocations_per_workgroup);
for (barrier_runtimes) |*barrier_rt| {
barrier_rt.* = try spv.Runtime.init(allocator, rt.mod, rt.image_api);
initialized_barrier_runtimes += 1;
try barrier_rt.copySpecializationConstantsFrom(allocator, rt);
try prepareRuntime(data.self, barrier_rt);
}
} else {
try prepareRuntime(data.self, rt);
}
var group_index: usize = data.batch_id;
while (group_index < data.group_count) : (group_index += data.self.batch_size) {
var modulo: usize = group_index;
@@ -188,10 +194,6 @@ inline fn run(data: RunData) !void {
defer rt.destroyWorkgroupMemory(allocator, workgroup_memory);
rt.resetInvocation(allocator);
if (rt.specialization_constants.count() != 0)
try rt.applySpecializationInvocationLayout(allocator);
try ExecutionDevice.writeDescriptorSets(data.self.state, rt);
try rt.populatePushConstants(data.self.state.push_constant_blob[0..]);
try rt.bindWorkgroupMemory(workgroup_memory);
try setupWorkgroupBuiltins(data.self, rt, data.local_size, group_count_vec, group_id_vec);
@@ -228,6 +230,16 @@ inline fn run(data: RunData) !void {
}
}
fn prepareRuntime(self: *Self, rt: *spv.Runtime) !void {
const allocator = self.device.interface.device_allocator.allocator();
rt.resetInvocation(allocator);
if (rt.specialization_constants.count() != 0)
try rt.applySpecializationInvocationLayout(allocator);
try ExecutionDevice.writeDescriptorSets(self.state, rt);
try rt.populatePushConstants(self.state.push_constant_blob[0..]);
}
fn runBarrierWorkgroup(
data: RunData,
runtimes: []spv.Runtime,
@@ -242,10 +254,6 @@ fn runBarrierWorkgroup(
defer runtimes[0].destroyWorkgroupMemory(allocator, workgroup_memory);
for (runtimes, 0..) |*rt, i| {
rt.resetInvocation(allocator);
if (rt.specialization_constants.count() != 0)
try rt.applySpecializationInvocationLayout(allocator);
try ExecutionDevice.writeDescriptorSets(data.self.state, rt);
try rt.populatePushConstants(data.self.state.push_constant_blob[0..]);
try rt.bindWorkgroupMemory(workgroup_memory);
try setupWorkgroupBuiltins(data.self, rt, data.local_size, group_count, group_id);
try setupSubgroupBuiltins(data.self, rt, data.local_size, group_id, i);
+4 -2
View File
@@ -246,15 +246,17 @@ fn drawCall(self: *Self, bounded_allocator: *BoundedAllocator, vertex_count: usi
};
const pipeline = self.state.pipeline orelse return VkError.InvalidPipelineDrv;
if (comptime !base.config.soft_ir_interpreter) {
const vertex_shader = pipeline.stages.getPtrAssertContains(.vertex);
for (vertex_shader.runtimes[0..]) |*runtime| {
for (vertex_shader.runtimes) |*runtime| {
ExecutionDevice.writeDescriptorSets(self.state, &runtime.rt) catch return VkError.Unknown;
}
if (pipeline.stages.getPtr(.fragment)) |fragment_shader| {
for (fragment_shader.runtimes[0..]) |*runtime| {
for (fragment_shader.runtimes) |*runtime| {
ExecutionDevice.writeDescriptorSets(self.state, &runtime.rt) catch return VkError.Unknown;
}
}
}
self.vertexShaderStage(allocator, &draw_call, vertex_count, instance_count, first_vertex, first_instance, indices, primitive_restart) catch |err| {
std.log.scoped(.@"Vertex stage").err("catched a '{s}'", .{@errorName(err)});
+3
View File
@@ -36,6 +36,9 @@ pub fn shaderInvocation(
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
derivative_inputs: ?DerivativeInputs,
) SpvRuntimeError!InvocationResult {
if (comptime base.config.soft_ir_interpreter)
return SpvRuntimeError.InvalidSpirV;
var fragment_inputs = inputs;
errdefer freeOwnedInputs(allocator, fragment_inputs);
+1 -1
View File
@@ -447,7 +447,7 @@ fn rasterizeTransformedPoint(
const point_min_x = vertex.position[0] - (point_size / 2.0);
const point_min_y = vertex.position[1] - (point_size / 2.0);
const pipeline = draw_call.renderer.state.pipeline orelse return;
const has_fragment_shader = pipeline.stages.getPtr(.fragment) != null;
const has_fragment_shader = if (comptime base.config.soft_ir_interpreter) false else pipeline.stages.getPtr(.fragment) != null;
var py = min_y;
while (py <= max_y) : (py += 1) {
+8 -3
View File
@@ -134,7 +134,12 @@ fn drawLineBresenham(
const pipeline = draw_call.renderer.state.pipeline orelse return;
const fragment_stage = pipeline.stages.getPtr(.fragment);
const runtimes_count = if (fragment_stage) |stage| stage.runtimes.len else 1;
const runtimes_count = if (comptime base.config.soft_ir_interpreter)
1
else if (fragment_stage) |stage|
stage.runtimes.len
else
1;
if (runtimes_count == 0)
return;
@@ -170,7 +175,7 @@ fn drawLineBresenham(
.color_attachment_access = color_attachment_access,
.depth_attachment_access = depth_attachment_access,
.stencil_attachment_access = stencil_attachment_access,
.has_fragment_shader = fragment_stage != null,
.has_fragment_shader = if (comptime base.config.soft_ir_interpreter) false else fragment_stage != null,
};
draw_call.rasterizer_wait_group.async(io, runWrapper, .{run_data});
@@ -191,7 +196,7 @@ fn drawLineDiamond(
) VkError!void {
const pipeline = draw_call.renderer.state.pipeline orelse return;
const fragment_stage = pipeline.stages.getPtr(.fragment);
const has_fragment_shader = fragment_stage != null;
const has_fragment_shader = if (comptime base.config.soft_ir_interpreter) false else fragment_stage != null;
const batch_id: usize = 0;
const min_x: i32 = @intFromFloat(@floor(@min(v0.position[0], v1.position[0]) - 1.0));
@@ -89,24 +89,37 @@ pub fn drawTriangle(
}
const fragment_stage = pipeline.stages.getPtr(.fragment);
const fragment_uses_derivatives = if (fragment_stage) |stage|
const fragment_uses_derivatives = if (comptime base.config.soft_ir_interpreter)
false
else if (fragment_stage) |stage|
stage.module.module.reflection_infos.needs_derivatives
else
false;
const early_fragment_tests = if (fragment_stage) |stage|
const early_fragment_tests = if (comptime base.config.soft_ir_interpreter)
false
else if (fragment_stage) |stage|
stage.module.module.reflection_infos.early_fragment_tests
else
false;
const fragment_uses_sample_id = if (fragment_stage) |stage|
const fragment_uses_sample_id = if (comptime base.config.soft_ir_interpreter)
false
else if (fragment_stage) |stage|
stage.module.module.builtins.get(.SampleId) != null
else
false;
const fragment_uses_centroid = if (fragment_stage) |stage|
const fragment_uses_centroid = if (comptime base.config.soft_ir_interpreter)
false
else if (fragment_stage) |stage|
fragmentStageUsesInputDecoration(stage, .Centroid)
else
false;
const runtimes_count = if (fragment_stage) |stage| stage.runtimes.len else 1;
const runtimes_count = if (comptime base.config.soft_ir_interpreter)
1
else if (fragment_stage) |stage|
stage.runtimes.len
else
1;
if (runtimes_count == 0)
return;
const sample_count = pipeline_data.multisample.rasterization_samples.toInt();
@@ -173,7 +186,7 @@ pub fn drawTriangle(
.depth_attachment_access = depth_attachment_access,
.stencil_attachment_access = stencil_attachment_access,
.front_face = front_face,
.has_fragment_shader = fragment_stage != null,
.has_fragment_shader = if (comptime base.config.soft_ir_interpreter) false else fragment_stage != null,
.early_fragment_tests = early_fragment_tests,
.fragment_uses_derivatives = fragment_uses_derivatives,
.fragment_uses_sample_id = fragment_uses_sample_id,
+1 -7
View File
@@ -43,14 +43,10 @@ pub fn runWrapper(data: RunData) void {
inline fn run(data: RunData) !void {
const shader = data.pipeline.stages.getPtrAssertContains(.vertex);
if (comptime base.config.soft_ir_interpreter) {
// Interpolation decorations are not represented in the common IR yet,
// so fragment-linked graphics pipelines retain the SPIR-V path.
if (data.pipeline.stages.getPtr(.fragment) == null) {
if (shader.interpreter) |*interpreter_shader| {
return ir_vertex.run(
data.allocator,
data.pipeline,
interpreter_shader,
shader,
data.batch_id,
data.batch_size,
data.vertex_count,
@@ -62,8 +58,6 @@ inline fn run(data: RunData) !void {
data.draw_call,
);
}
}
}
const runtime = &shader.runtimes[data.batch_id];
const mutex = &runtime.mutex;
const rt = &runtime.rt;
+33 -41
View File
@@ -47,24 +47,25 @@ interfaces: []const ?InterfaceBinding,
pub fn compile(backing_allocator: std.mem.Allocator, module: *const module_ir.Module) !Self {
try ir.validator.validate(module);
var result: Self = undefined;
result.arena = std.heap.ArenaAllocator.init(backing_allocator);
errdefer result.arena.deinit();
var arena = std.heap.ArenaAllocator.init(backing_allocator);
errdefer arena.deinit();
var lowerer = try Lowerer.init(result.arena.allocator(), module);
var lowerer = try Lowerer.init(arena.allocator(), module);
try lowerer.lower();
result.stage = module.stage;
result.entry_pc = lowerer.entry_pc;
result.register_count = lowerer.register_count;
result.scratch_count = lowerer.scratch_count;
result.code = lowerer.code.items;
result.edges = lowerer.edges.items;
result.copies = lowerer.copies.items;
result.branches = lowerer.branches.items;
result.initializers = lowerer.initializers.items;
result.interfaces = lowerer.interfaces;
return result;
return .{
.arena = arena,
.stage = module.stage,
.entry_pc = lowerer.entry_pc,
.register_count = lowerer.register_count,
.scratch_count = lowerer.scratch_count,
.code = lowerer.code.items,
.edges = lowerer.edges.items,
.copies = lowerer.copies.items,
.branches = lowerer.branches.items,
.initializers = lowerer.initializers.items,
.interfaces = lowerer.interfaces,
};
}
pub fn deinit(self: *Self) void {
@@ -158,41 +159,32 @@ const Lowerer = struct {
fn allocate(self: *Lowerer, type_id: ids.TypeId) !bc.Span {
const ty = self.module.types.get(type_id) orelse return CompileError.UnsupportedType;
var kind: bc.ValueKind = undefined;
var components: u8 = 1;
switch (ty.*) {
.boolean => kind = .boolean,
.integer => |integer| {
if (integer.bits != 32)
return CompileError.UnsupportedType;
kind = if (integer.signedness == .signed) .signed_integer else .unsigned_integer;
},
.floating => |floating| {
if (floating.bits != 32)
return CompileError.UnsupportedType;
kind = .floating;
},
.vector => |vector| {
const kind: bc.ValueKind = switch (ty.*) {
.boolean => .boolean,
.integer => |integer| if (integer.bits == 32)
if (integer.signedness == .signed) .signed_integer else .unsigned_integer
else
return CompileError.UnsupportedType,
.floating => |floating| if (floating.bits == 32)
.floating
else
return CompileError.UnsupportedType,
.vector => |vector| blk: {
const element = self.module.types.get(vector.element_type) orelse return CompileError.UnsupportedType;
components = vector.length;
kind = switch (element.*) {
break :blk switch (element.*) {
.boolean => .boolean,
.integer => |integer| blk: {
if (integer.bits != 32)
return CompileError.UnsupportedType;
break :blk if (integer.signedness == .signed) .signed_integer else .unsigned_integer;
},
.integer => |integer| if (integer.bits == 32)
if (integer.signedness == .signed) .signed_integer else .unsigned_integer
else
return CompileError.UnsupportedType,
.floating => |floating| if (floating.bits == 32) .floating else return CompileError.UnsupportedType,
else => return CompileError.UnsupportedType,
};
},
else => return CompileError.UnsupportedType,
}
};
const end = std.math.add(usize, self.register_count, components) catch return CompileError.TooManyRegisters;
if (end > @as(usize, std.math.maxInt(bc.Register)) + 1)
+16 -19
View File
@@ -21,17 +21,15 @@ program: Program,
runtimes: []RuntimeSlot,
workgroup_size: ?[3]u32,
/// Compiles a stage when the current interpreter can execute its complete
/// interface. `null` deliberately selects the existing SPIR-V runtime.
pub fn compile(
allocator: std.mem.Allocator,
module: *SoftShaderModule,
stage: *const vk.PipelineShaderStageCreateInfo,
runtime_count: usize,
) VkError!?Self {
const expected_stage = commonStage(stage.stage) orelse return null;
if (expected_stage == .fragment)
return null;
pub fn compile(allocator: std.mem.Allocator, module: *SoftShaderModule, stage: *const vk.PipelineShaderStageCreateInfo, runtime_count: usize) VkError!Self {
const expected_stage = commonStage(stage.stage) orelse {
std.log.scoped(.IrInterpreter).err("unsupported shader stage", .{});
return VkError.ValidationFailed;
};
if (expected_stage == .fragment) {
std.log.scoped(.IrInterpreter).err("fragment shaders are not supported", .{});
return VkError.ValidationFailed;
}
const specializations = try specializationValues(allocator, stage.p_specialization_info);
defer if (specializations.len != 0) allocator.free(specializations);
@@ -43,25 +41,24 @@ pub fn compile(
}) catch |err| {
if (err == error.OutOfMemory)
return VkError.OutOfDeviceMemory;
std.log.scoped(.SoftIrInterpreter).debug("IR translation fallback: {s}", .{@errorName(err)});
return null;
std.log.scoped(.IrInterpreter).err("IR translation failed: {s}", .{@errorName(err)});
return VkError.ValidationFailed;
};
defer module_ir.deinit();
var program = Program.compile(allocator, &module_ir) catch |err| {
if (err == error.OutOfMemory)
return VkError.OutOfDeviceMemory;
std.log.scoped(.SoftIrInterpreter).debug("bytecode lowering fallback: {s}", .{@errorName(err)});
return null;
std.log.scoped(.IrInterpreter).err("bytecode lowering failed: {s}", .{@errorName(err)});
return VkError.ValidationFailed;
};
errdefer program.deinit();
if (!hasCompatibleInterface(&program, expected_stage) or
(expected_stage == .compute and module_ir.execution_modes.workgroup_size == null))
{
std.log.scoped(.SoftIrInterpreter).debug("stage interface or execution modes require the SPIR-V runtime", .{});
program.deinit();
return null;
std.log.scoped(.IrInterpreter).err("unsupported stage interface or execution modes", .{});
return VkError.ValidationFailed;
}
const runtimes = allocator.alloc(RuntimeSlot, runtime_count) catch return VkError.OutOfDeviceMemory;
@@ -76,7 +73,7 @@ pub fn compile(
initialized += 1;
}
std.log.scoped(.SoftIrInterpreter).debug("compiled {s} stage to {d} bytecode instructions", .{
std.log.scoped(.IrInterpreter).debug("compiled {s} stage to {d} bytecode instructions", .{
@tagName(expected_stage),
program.code.len,
});
+1 -13
View File
@@ -3,7 +3,6 @@ const vk = @import("vulkan");
const base = @import("base");
const shader_ir = @import("shader_ir");
const bc = @import("bytecode.zig");
const Shader = @import("Shader.zig");
const SoftPipeline = @import("../SoftPipeline.zig");
const Renderer = @import("../device/Renderer.zig");
@@ -58,14 +57,7 @@ pub fn run(
}
}
fn populateInputs(
runtime: anytype,
program: *const @import("Program.zig"),
pipeline: *SoftPipeline,
draw_call: *Renderer.DrawCall,
vertex_index: u32,
instance_index: u32,
) VkError!void {
fn populateInputs(runtime: anytype, program: *const @import("Program.zig"), pipeline: *SoftPipeline, draw_call: *Renderer.DrawCall, vertex_index: u32, instance_index: u32) VkError!void {
for (program.interfaces, 0..) |optional_binding, index| {
const binding = optional_binding orelse continue;
if (binding.direction != .input)
@@ -167,7 +159,3 @@ fn findBinding(bindings: []const vk.VertexInputBindingDescription, binding: u32)
if (description.binding == binding) return description;
return null;
}
comptime {
_ = bc;
}
+5 -1
View File
@@ -34,6 +34,7 @@ pub const VTable = struct {
releasePhysicalDevices: *const fn (*Self, std.mem.Allocator) VkError!void,
requestPhysicalDevices: *const fn (*Self, std.mem.Allocator, []lib.drm.Card) VkError!void,
io: *const fn (*Self) std.Io,
enumerate_drm_devices: bool = true,
};
pub const DispatchTable = struct {
@@ -154,10 +155,13 @@ pub fn releasePhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError
}
pub fn requestPhysicalDevices(self: *Self, allocator: std.mem.Allocator) VkError!void {
if (self.vtable.enumerate_drm_devices) {
const devices = try drm.enumerateDrmPhysicalDevices(allocator, self);
defer allocator.free(devices);
try self.vtable.requestPhysicalDevices(self, allocator, devices);
} else {
try self.vtable.requestPhysicalDevices(self, allocator, &.{});
}
if (self.physical_devices.items.len == 0) {
std.log.scoped(.vkCreateInstance).err("No VkPhysicalDevice found", .{});