adding util to runtime api
Test / build (push) Failing after 31s
Build / build (push) Successful in 48s

This commit is contained in:
2026-06-05 17:48:21 +02:00
parent ee5a400010
commit ad87703ea8
4 changed files with 166 additions and 1 deletions
+24
View File
@@ -452,6 +452,20 @@ typedef enum
SPV_LOCATION_OUTPUT = 1
} SpvLocationType;
typedef enum
{
SPV_ENTRY_POINT_COMPLETED = 0,
SPV_ENTRY_POINT_BARRIER = 1
} SpvEntryPointStatus;
typedef enum
{
SPV_PRIMITIVE_BOOL = 0,
SPV_PRIMITIVE_FLOAT = 1,
SPV_PRIMITIVE_SINT = 2,
SPV_PRIMITIVE_UINT = 3
} SpvPrimitiveType;
typedef struct
{
float x;
@@ -497,19 +511,29 @@ SPV_API void SpvDeinitRuntime(SpvRuntime runtime);
SPV_API SpvResult SpvFlushDescriptorSets(SpvRuntime runtime);
SPV_API SpvResult SpvAddSpecializationInfo(SpvRuntime runtime, SpvRuntimeSpecializationEntry entry, const SpvByte* data, SpvSize data_size);
SPV_API SpvResult SpvPopulatePushConstants(SpvRuntime runtime, const SpvByte* data, SpvSize data_size);
SPV_API SpvResult SpvGetResultByName(SpvRuntime runtime, const char* name, SpvWord* result);
SPV_API SpvResult SpvGetResultLocation(SpvRuntime runtime, SpvWord location, SpvLocationType type, SpvWord* result);
SPV_API SpvResult SpvGetResultByLocation(SpvRuntime runtime, SpvWord location, SpvLocationType type, SpvWord* result);
SPV_API SpvResult SpvGetResultByLocationComponent(SpvRuntime runtime, SpvWord location, SpvWord component, SpvLocationType type, SpvWord* result);
SPV_API SpvResult SpvGetEntryPointByName(SpvRuntime runtime, const char* name, SpvWord* result);
SPV_API SpvResult SpvGetResultMemorySize(SpvRuntime runtime, SpvWord result, SpvSize* size);
SPV_API SpvResult SpvGetInputLocationMemorySize(SpvRuntime runtime, SpvWord location, SpvSize* size);
SPV_API SpvResult SpvGetResultPrimitiveType(SpvRuntime runtime, SpvWord result, SpvPrimitiveType* primitive_type);
SPV_API SpvBool SpvResultIsInteger(SpvRuntime runtime, SpvWord result);
SPV_API SpvBool SpvHasResultDecoration(SpvRuntime runtime, SpvWord result, SpvDecoration decoration);
SPV_API SpvResult SpvCallEntryPoint(SpvRuntime runtime, SpvWord entry_point_index);
SPV_API SpvResult SpvBeginEntryPoint(SpvRuntime runtime, SpvWord entry_point_index, SpvEntryPointStatus* status);
SPV_API SpvResult SpvContinueEntryPoint(SpvRuntime runtime, SpvEntryPointStatus* status);
SPV_API void SpvResetInvocation(SpvRuntime runtime);
SPV_API SpvResult SpvReadOutput(SpvRuntime runtime, SpvByte* output, SpvSize output_size, SpvWord result);
SPV_API SpvResult SpvReadBuiltIn(SpvRuntime runtime, SpvByte* output, SpvSize output_size, SpvBuiltIn builtin);
SPV_API SpvResult SpvWriteInput(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvWord result);
SPV_API SpvResult SpvWriteInputLocation(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvWord location);
SPV_API SpvResult SpvWriteBuiltIn(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvBuiltIn builtin);
SPV_API SpvResult SpvWriteDescriptorSet(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvWord set, SpvWord binding, SpvWord descriptor_index);
+93
View File
@@ -13,6 +13,18 @@ const LocationType = enum(c_int) {
output = 1,
};
const EntryPointStatus = enum(c_int) {
completed = 0,
barrier = 1,
};
const PrimitiveType = enum(c_int) {
bool = 0,
float = 1,
sint = 2,
uint = 3,
};
const Vec4f = extern struct {
x: f32,
y: f32,
@@ -82,6 +94,13 @@ fn fromCResult(res: ffi.Result) spv.Runtime.RuntimeError!void {
};
}
fn toCEntryPointStatus(status: spv.Runtime.EntryPointStatus) EntryPointStatus {
return switch (status) {
.completed => .completed,
.barrier => .barrier,
};
}
/// Hacky wrapper
const ImageAPIBridge = struct {
threadlocal var current_image_api: ?*const ImageAPI = null;
@@ -206,6 +225,12 @@ export fn SpvDeinitRuntime(rt: *RuntimeWrapper) callconv(.c) void {
allocator.destroy(rt);
}
export fn SpvFlushDescriptorSets(rt: *RuntimeWrapper) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
rt.rt.flushDescriptorSets(allocator) catch |err| return toCResult(err);
return .Success;
}
export fn SpvAddSpecializationInfo(rt: *RuntimeWrapper, entry: CSpecializationEntry, data: [*]const u8, data_size: c_ulong) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
rt.rt.addSpecializationInfo(
@@ -220,6 +245,11 @@ export fn SpvAddSpecializationInfo(rt: *RuntimeWrapper, entry: CSpecializationEn
return .Success;
}
export fn SpvPopulatePushConstants(rt: *RuntimeWrapper, data: [*]const u8, data_size: c_ulong) callconv(.c) ffi.Result {
rt.rt.populatePushConstants(data[0..data_size]) catch |err| return toCResult(err);
return .Success;
}
export fn SpvGetEntryPointByName(rt: *RuntimeWrapper, name: [*:0]const u8, result: *spv.SpvWord) callconv(.c) ffi.Result {
result.* = rt.rt.getEntryPointByName(std.mem.span(name)) catch |err| return toCResult(err);
return .Success;
@@ -233,6 +263,18 @@ export fn SpvGetResultByLocation(rt: *RuntimeWrapper, location: spv.SpvWord, kin
return .Success;
}
export fn SpvGetResultLocation(rt: *RuntimeWrapper, location: spv.SpvWord, kind: LocationType, result: *spv.SpvWord) callconv(.c) ffi.Result {
return SpvGetResultByLocation(rt, location, kind, result);
}
export fn SpvGetResultByLocationComponent(rt: *RuntimeWrapper, location: spv.SpvWord, component: spv.SpvWord, kind: LocationType, result: *spv.SpvWord) callconv(.c) ffi.Result {
result.* = rt.rt.getResultByLocationComponent(location, component, switch (kind) {
.input => .input,
.output => .output,
}) catch |err| return toCResult(err);
return .Success;
}
export fn SpvGetResultByName(rt: *RuntimeWrapper, name: [*:0]const u8, result: *spv.SpvWord) callconv(.c) ffi.Result {
result.* = rt.rt.getResultByName(std.mem.span(name)) catch |err| return toCResult(err);
return .Success;
@@ -243,6 +285,25 @@ export fn SpvGetResultMemorySize(rt: *RuntimeWrapper, result: spv.SpvWord, size:
return .Success;
}
export fn SpvGetInputLocationMemorySize(rt: *RuntimeWrapper, location: spv.SpvWord, size: *c_ulong) callconv(.c) ffi.Result {
size.* = rt.rt.getInputLocationMemorySize(location) catch |err| return toCResult(err);
return .Success;
}
export fn SpvGetResultPrimitiveType(rt: *RuntimeWrapper, result: spv.SpvWord, primitive_type: *PrimitiveType) callconv(.c) ffi.Result {
primitive_type.* = switch (rt.rt.getResultPrimitiveType(result) catch |err| return toCResult(err)) {
.Bool => .bool,
.Float => .float,
.SInt => .sint,
.UInt => .uint,
};
return .Success;
}
export fn SpvResultIsInteger(rt: *RuntimeWrapper, result: spv.SpvWord) callconv(.c) c_int {
return if (rt.rt.resultIsInteger(result)) 1 else 0;
}
export fn SpvHasResultDecoration(rt: *RuntimeWrapper, result: spv.SpvWord, decoration: spv.spv.SpvDecoration) callconv(.c) c_int {
return if (rt.rt.hasResultDecoration(result, decoration)) 1 else 0;
}
@@ -259,6 +320,33 @@ export fn SpvCallEntryPoint(rt: *RuntimeWrapper, entry_point: spv.SpvWord) callc
return .Success;
}
export fn SpvBeginEntryPoint(rt: *RuntimeWrapper, entry_point: spv.SpvWord, status: *EntryPointStatus) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
const previous_image_api = ImageAPIBridge.current_image_api;
ImageAPIBridge.current_image_api = &rt.image_api;
defer ImageAPIBridge.current_image_api = previous_image_api;
status.* = toCEntryPointStatus(rt.rt.beginEntryPoint(allocator, entry_point) catch |err| return toCResult(err));
return .Success;
}
export fn SpvContinueEntryPoint(rt: *RuntimeWrapper, status: *EntryPointStatus) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
const previous_image_api = ImageAPIBridge.current_image_api;
ImageAPIBridge.current_image_api = &rt.image_api;
defer ImageAPIBridge.current_image_api = previous_image_api;
status.* = toCEntryPointStatus(rt.rt.continueEntryPoint(allocator) catch |err| return toCResult(err));
return .Success;
}
export fn SpvResetInvocation(rt: *RuntimeWrapper) callconv(.c) void {
const allocator = std.heap.c_allocator;
rt.rt.resetInvocation(allocator);
}
export fn SpvReadOutput(rt: *RuntimeWrapper, output: [*]u8, output_size: c_ulong, result: spv.SpvWord) callconv(.c) ffi.Result {
rt.rt.readOutput(output[0..output_size], result) catch |err| return toCResult(err);
return .Success;
@@ -274,6 +362,11 @@ export fn SpvWriteInput(rt: *RuntimeWrapper, input: [*]const u8, input_size: c_u
return .Success;
}
export fn SpvWriteInputLocation(rt: *RuntimeWrapper, input: [*]const u8, input_size: c_ulong, location: spv.SpvWord) callconv(.c) ffi.Result {
rt.rt.writeInputLocation(input[0..input_size], location) catch |err| return toCResult(err);
return .Success;
}
export fn SpvWriteBuiltIn(rt: *RuntimeWrapper, input: [*]const u8, input_size: c_ulong, builtin: spv.spv.SpvBuiltIn) callconv(.c) ffi.Result {
rt.rt.writeBuiltIn(input[0..input_size], builtin) catch |err| return toCResult(err);
return .Success;
+16 -1
View File
@@ -12,7 +12,9 @@ const SpvWord = spv.SpvWord;
const SpvBool = spv.SpvBool;
const Module = @import("Module.zig");
const PrimitiveType = @import("Value.zig").PrimitiveType;
const Result = @import("Result.zig");
const Value = @import("Value.zig").Value;
const WordIterator = @import("WordIterator.zig");
const Self = @This();
@@ -195,6 +197,19 @@ pub fn getResultByLocationComponent(self: *const Self, location: SpvWord, compon
return RuntimeError.NotFound;
}
pub fn getResultPrimitiveType(self: *const Self, result: SpvWord) RuntimeError!PrimitiveType {
if (result >= self.results.len)
return RuntimeError.OutOfBounds;
return (try self.results[result].getConstValue()).resolvePrimitiveType();
}
pub fn resultIsInteger(self: *const Self, result: SpvWord) bool {
return switch (self.getResultPrimitiveType(result) catch return false) {
.SInt, .UInt => true,
else => false,
};
}
pub fn dumpResultsTable(self: *Self, allocator: std.mem.Allocator, writer: *std.Io.Writer) RuntimeError!void {
const dump = pretty.dump(allocator, self.results, .{
.tab_size = 4,
@@ -414,7 +429,7 @@ fn resolveInputLocationTarget(self: *const Self, location: SpvWord) RuntimeError
return RuntimeError.NotFound;
}
fn getInputLocationTargetValue(self: *const Self, target: InputLocationTarget) RuntimeError!*@import("Value.zig").Value {
fn getInputLocationTargetValue(self: *const Self, target: InputLocationTarget) RuntimeError!*Value {
const value = switch ((try self.results[target.result].getVariant()).*) {
.Variable => |*v| &v.value,
.AccessChain => |*a| &a.value,
+33
View File
@@ -169,6 +169,39 @@ pub const Value = union(Type) {
};
}
pub fn resolvePrimitiveType(self: *const Self) RuntimeError!PrimitiveType {
return switch (self.*) {
.Bool => .Bool,
.Float,
.Vector2f32,
.Vector3f32,
.Vector4f32,
=> .Float,
.Int => |int| if (int.is_signed) .SInt else .UInt,
.Vector2i32,
.Vector3i32,
.Vector4i32,
=> .SInt,
.Vector2u32,
.Vector3u32,
.Vector4u32,
=> .UInt,
.Vector => |lanes| {
if (lanes.len == 0)
return RuntimeError.InvalidValueType;
return lanes[0].resolvePrimitiveType();
},
else => RuntimeError.InvalidValueType,
};
}
pub fn isInteger(self: *const Self) bool {
return switch (self.resolvePrimitiveType() catch return false) {
.SInt, .UInt => true,
else => false,
};
}
pub fn init(allocator: std.mem.Allocator, results: []const Result, target_type: SpvWord, is_externally_visible: bool) RuntimeError!Self {
const resolved = results[target_type].resolveTypeWordOrNull() orelse target_type;
return initUnresolved(allocator, results, resolved, is_externally_visible);