implementing missing functions in FFI
Build / build (push) Successful in 42s
Test / build (push) Successful in 1m17s

This commit is contained in:
2026-07-04 20:59:03 +02:00
parent 32806def90
commit 589d30168f
9 changed files with 368 additions and 113 deletions
+51 -7
View File
@@ -413,6 +413,28 @@ typedef unsigned char SpvByte;
typedef unsigned long SpvWord;
typedef unsigned long SpvSize;
typedef enum
{
SpvExecutionModelVertex = 0,
SpvExecutionModelTessellationControl = 1,
SpvExecutionModelTessellationEvaluation = 2,
SpvExecutionModelGeometry = 3,
SpvExecutionModelFragment = 4,
SpvExecutionModelGLCompute = 5,
SpvExecutionModelKernel = 6,
SpvExecutionModelTaskNV = 5267,
SpvExecutionModelMeshNV = 5268,
SpvExecutionModelRayGeneration = 5313,
SpvExecutionModelIntersection = 5314,
SpvExecutionModelAnyHit = 5315,
SpvExecutionModelClosestHit = 5316,
SpvExecutionModelMiss = 5317,
SpvExecutionModelCallable = 5318,
SpvExecutionModelTaskEXT = 5364,
SpvExecutionModelMeshEXT = 5365,
SpvExecutionModelMax = 0x7fffffff
} SpvExecutionModel;
typedef enum
{
SPV_RESULT_SUCCESS = 0,
@@ -451,6 +473,8 @@ typedef struct
SpvBool needs_derivatives;
SpvBool has_control_barriers;
SpvBool has_atomics;
SpvBool early_fragment_tests;
} SpvModuleReflectionInfos;
typedef struct
@@ -472,13 +496,20 @@ typedef enum
SPV_ENTRY_POINT_BARRIER = 1
} SpvEntryPointStatus;
typedef enum
typedef struct
{
SPV_PRIMITIVE_BOOL = 0,
SPV_PRIMITIVE_FLOAT = 1,
SPV_PRIMITIVE_SINT = 2,
SPV_PRIMITIVE_UINT = 3
} SpvPrimitiveType;
SpvBool has_size;
SpvWord x;
SpvWord y;
SpvWord z;
} SpvWorkgroupSize;
typedef struct
{
SpvWord result;
SpvByte* data;
SpvSize size;
} SpvWorkgroupMemoryItem;
typedef struct
{
@@ -589,6 +620,7 @@ typedef struct
typedef void* SpvModule;
typedef void* SpvRuntime;
typedef void* SpvWorkgroupMemory;
SPV_API SpvResult SpvInitModule(SpvModule* module, const SpvWord* source, SpvSize source_len, SpvModuleOptions options);
SPV_API void SpvDeinitModule(SpvModule module);
@@ -604,20 +636,31 @@ SPV_API SpvResult SpvFlushDescriptorSets(SpvRuntime runtime);
SPV_API SpvResult SpvAddSpecializationInfo(SpvRuntime runtime, SpvRuntimeSpecializationEntry entry, const SpvByte* data, SpvSize data_size);
SPV_API SpvResult SpvCopySpecializationConstantsFrom(SpvRuntime runtime, SpvRuntime other);
SPV_API SpvResult SpvApplySpecializationLayout(SpvRuntime runtime);
SPV_API SpvResult SpvApplySpecializationInvocationLayout(SpvRuntime runtime);
SPV_API SpvResult SpvSetDerivativeFromMemory(SpvRuntime runtime, SpvWord result, const SpvByte* dx, SpvSize dx_size, const SpvByte* dy, SpvSize dy_size);
SPV_API void SpvClearDerivative(SpvRuntime runtime, SpvWord result);
SPV_API SpvResult SpvCopyDerivative(SpvRuntime runtime, SpvWord dst, SpvWord src);
SPV_API SpvResult SpvPopulatePushConstants(SpvRuntime runtime, const SpvByte* data, SpvSize data_size);
SPV_API SpvResult SpvRefreshResultValueLayout(SpvRuntime runtime, SpvWord result);
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 SpvGetEntryPointByNameAndExecutionModel(SpvRuntime runtime, const char* name, SpvExecutionModel execution_model, SpvWord* result);
SPV_API SpvResult SpvSelectEntryPoint(SpvRuntime runtime, SpvWord entry_point_index);
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 SpvHasResultDecoration(SpvRuntime runtime, SpvWord result, SpvDecoration decoration);
SPV_API SpvResult SpvGetWorkgroupSize(SpvRuntime runtime, SpvWorkgroupSize* size);
SPV_API SpvResult SpvCreateWorkgroupMemory(SpvRuntime runtime, SpvWorkgroupMemory* workgroup_memory);
SPV_API void SpvDestroyWorkgroupMemory(SpvRuntime runtime, SpvWorkgroupMemory workgroup_memory);
SPV_API SpvResult SpvBindWorkgroupMemory(SpvRuntime runtime, SpvWorkgroupMemory workgroup_memory);
SPV_API SpvSize SpvGetWorkgroupMemoryCount(SpvWorkgroupMemory workgroup_memory);
SPV_API SpvResult SpvGetWorkgroupMemoryItem(SpvWorkgroupMemory workgroup_memory, SpvSize index, SpvWorkgroupMemoryItem* item);
SPV_API SpvResult SpvCallEntryPoint(SpvRuntime runtime, SpvWord entry_point_index);
SPV_API SpvResult SpvBeginEntryPoint(SpvRuntime runtime, SpvWord entry_point_index, SpvEntryPointStatus* status);
@@ -626,6 +669,7 @@ 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 SpvGetBuiltinResult(SpvRuntime runtime, SpvBuiltIn builtin, SpvWord* result);
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);
+4
View File
@@ -18,6 +18,8 @@ const ReflectionInfos = extern struct {
needs_derivatives: ffi.SpvCBool,
has_control_barriers: ffi.SpvCBool,
has_atomics: ffi.SpvCBool,
early_fragment_tests: ffi.SpvCBool,
};
fn toCResult(err: spv.Module.ModuleError) ffi.Result {
@@ -66,6 +68,8 @@ export fn SpvModuleGetReflectionInfos(module: *spv.Module) callconv(.c) Reflecti
.geometry_output = module.reflection_infos.geometry_output,
.needs_derivatives = if (module.reflection_infos.needs_derivatives) 1 else 0,
.has_control_barriers = if (module.reflection_infos.has_control_barriers) 1 else 0,
.has_atomics = if (module.reflection_infos.has_atomics) 1 else 0,
.early_fragment_tests = if (module.reflection_infos.early_fragment_tests) 1 else 0,
};
}
+103 -8
View File
@@ -18,6 +18,19 @@ const EntryPointStatus = enum(c_int) {
barrier = 1,
};
const WorkgroupSize = extern struct {
has_size: ffi.SpvCBool,
x: ffi.SpvCWord,
y: ffi.SpvCWord,
z: ffi.SpvCWord,
};
const WorkgroupMemoryItem = extern struct {
result: ffi.SpvCWord,
data: ?[*]u8,
size: ffi.SpvCSize,
};
const PrimitiveType = enum(c_int) {
bool = 0,
float = 1,
@@ -392,6 +405,10 @@ const RuntimeWrapper = struct {
image_api: ImageAPI,
};
const WorkgroupMemoryWrapper = struct {
memories: []spv.Runtime.WorkgroupMemory,
};
export fn SpvInitRuntime(rt: **RuntimeWrapper, module: *spv.Module, image_api: ImageAPI) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
@@ -482,6 +499,18 @@ export fn SpvCopySpecializationConstantsFrom(rt: *RuntimeWrapper, other: *const
return .Success;
}
export fn SpvApplySpecializationLayout(rt: *RuntimeWrapper) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
rt.rt.applySpecializationLayout(allocator) catch |err| return toCResult(err);
return .Success;
}
export fn SpvApplySpecializationInvocationLayout(rt: *RuntimeWrapper) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
rt.rt.applySpecializationInvocationLayout(allocator) catch |err| return toCResult(err);
return .Success;
}
export fn SpvSetDerivativeFromMemory(rt: *RuntimeWrapper, result: spv.SpvWord, dx: [*]const u8, dx_size: c_ulong, dy: [*]const u8, dy_size: c_ulong) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
rt.rt.setDerivativeFromMemory(allocator, result, dx[0..dx_size], dy[0..dy_size]) catch |err| return toCResult(err);
@@ -504,11 +533,26 @@ export fn SpvPopulatePushConstants(rt: *RuntimeWrapper, data: [*]const u8, data_
return .Success;
}
export fn SpvRefreshResultValueLayout(rt: *RuntimeWrapper, result: spv.SpvWord) callconv(.c) ffi.Result {
rt.rt.refreshResultValueLayout(result) 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;
}
export fn SpvGetEntryPointByNameAndExecutionModel(rt: *RuntimeWrapper, name: [*:0]const u8, execution_model: spv.spv.SpvExecutionModel, result: *spv.SpvWord) callconv(.c) ffi.Result {
result.* = rt.rt.getEntryPointByNameAndExecutionModel(std.mem.span(name), execution_model) catch |err| return toCResult(err);
return .Success;
}
export fn SpvSelectEntryPoint(rt: *RuntimeWrapper, entry_point: spv.SpvWord) callconv(.c) ffi.Result {
rt.rt.selectEntryPoint(entry_point) catch |err| return toCResult(err);
return .Success;
}
export fn SpvGetResultByLocation(rt: *RuntimeWrapper, location: spv.SpvWord, kind: LocationType, result: *spv.SpvWord) callconv(.c) ffi.Result {
result.* = rt.rt.getResultByLocation(location, switch (kind) {
.input => .input,
@@ -544,18 +588,64 @@ export fn SpvGetInputLocationMemorySize(rt: *RuntimeWrapper, location: spv.SpvWo
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,
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;
}
export fn SpvGetWorkgroupSize(rt: *RuntimeWrapper, size: *WorkgroupSize) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
if (rt.rt.getWorkgroupSize(allocator) catch |err| return toCResult(err)) |workgroup_size| {
size.* = .{
.has_size = 1,
.x = workgroup_size[0],
.y = workgroup_size[1],
.z = workgroup_size[2],
};
} else {
size.* = .{
.has_size = 0,
.x = 0,
.y = 0,
.z = 0,
};
}
return .Success;
}
export fn SpvCreateWorkgroupMemory(rt: *RuntimeWrapper, workgroup_memory: **WorkgroupMemoryWrapper) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
workgroup_memory.* = allocator.create(WorkgroupMemoryWrapper) catch return .OutOfMemory;
workgroup_memory.*.memories = rt.rt.createWorkgroupMemory(allocator) catch |err| {
allocator.destroy(workgroup_memory.*);
return toCResult(err);
};
return .Success;
}
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;
export fn SpvDestroyWorkgroupMemory(rt: *RuntimeWrapper, workgroup_memory: *WorkgroupMemoryWrapper) callconv(.c) void {
const allocator = std.heap.c_allocator;
rt.rt.destroyWorkgroupMemory(allocator, workgroup_memory.memories);
allocator.destroy(workgroup_memory);
}
export fn SpvBindWorkgroupMemory(rt: *RuntimeWrapper, workgroup_memory: *const WorkgroupMemoryWrapper) callconv(.c) ffi.Result {
rt.rt.bindWorkgroupMemory(workgroup_memory.memories) catch |err| return toCResult(err);
return .Success;
}
export fn SpvGetWorkgroupMemoryCount(workgroup_memory: *const WorkgroupMemoryWrapper) callconv(.c) ffi.SpvCSize {
return workgroup_memory.memories.len;
}
export fn SpvGetWorkgroupMemoryItem(workgroup_memory: *const WorkgroupMemoryWrapper, index: ffi.SpvCSize, item: *WorkgroupMemoryItem) callconv(.c) ffi.Result {
if (index >= workgroup_memory.memories.len) return .OutOfBounds;
const memory = workgroup_memory.memories[index];
item.* = .{
.result = memory.result,
.data = memory.bytes.ptr,
.size = memory.bytes.len,
};
return .Success;
}
export fn SpvCallEntryPoint(rt: *RuntimeWrapper, entry_point: spv.SpvWord) callconv(.c) ffi.Result {
@@ -607,6 +697,11 @@ export fn SpvReadBuiltIn(rt: *RuntimeWrapper, output: [*]u8, output_size: c_ulon
return .Success;
}
export fn SpvGetBuiltinResult(rt: *RuntimeWrapper, builtin: spv.spv.SpvBuiltIn, result: *spv.SpvWord) callconv(.c) ffi.Result {
result.* = rt.rt.getBuiltinResult(builtin) orelse return .NotFound;
return .Success;
}
export fn SpvWriteInput(rt: *RuntimeWrapper, input: [*]const u8, input_size: c_ulong, result: spv.SpvWord) callconv(.c) ffi.Result {
const allocator = std.heap.c_allocator;
rt.rt.writeInput(allocator, input[0..input_size], result) catch |err| return toCResult(err);