improving GLSL_std450 support
Build / build (push) Successful in 38s
Test / build (push) Successful in 1m5s

This commit is contained in:
2026-06-10 19:15:39 +02:00
parent 11be3ea41d
commit c868a4481b
6 changed files with 998 additions and 272 deletions
+17
View File
@@ -439,6 +439,21 @@ typedef struct
SpvBool use_simd_vectors_specializations; SpvBool use_simd_vectors_specializations;
} SpvModuleOptions; } SpvModuleOptions;
typedef struct
{
SpvWord local_size_x;
SpvWord local_size_y;
SpvWord local_size_z;
SpvWord geometry_invocations;
SpvWord geometry_output_count;
SpvWord geometry_input;
SpvWord geometry_output;
SpvBool needs_derivatives;
SpvBool has_control_barriers;
} SpvModuleReflectionInfos;
typedef struct typedef struct
{ {
SpvWord id; SpvWord id;
@@ -507,6 +522,8 @@ typedef void* SpvRuntime;
SPV_API SpvResult SpvInitModule(SpvModule* module, const SpvWord* source, SpvSize source_len, SpvModuleOptions options); SPV_API SpvResult SpvInitModule(SpvModule* module, const SpvWord* source, SpvSize source_len, SpvModuleOptions options);
SPV_API void SpvDeinitModule(SpvModule module); SPV_API void SpvDeinitModule(SpvModule module);
SPV_API SpvModuleReflectionInfos SpvModuleGetReflectionInfos(SpvModule module);
SPV_API SpvResult SpvInitRuntime(SpvRuntime* runtime, SpvModule module, SpvImageAPI image_api); SPV_API SpvResult SpvInitRuntime(SpvRuntime* runtime, SpvModule module, SpvImageAPI image_api);
SPV_API void SpvDeinitRuntime(SpvRuntime runtime); SPV_API void SpvDeinitRuntime(SpvRuntime runtime);
+28
View File
@@ -6,6 +6,20 @@ const Options = extern struct {
use_simd_vectors_specializations: ffi.SpvCBool, use_simd_vectors_specializations: ffi.SpvCBool,
}; };
const ReflectionInfos = extern struct {
local_size_x: ffi.SpvCWord,
local_size_y: ffi.SpvCWord,
local_size_z: ffi.SpvCWord,
geometry_invocations: ffi.SpvCWord,
geometry_output_count: ffi.SpvCWord,
geometry_input: ffi.SpvCWord,
geometry_output: ffi.SpvCWord,
needs_derivatives: ffi.SpvCBool,
has_control_barriers: ffi.SpvCBool,
};
fn toCResult(err: spv.Module.ModuleError) ffi.Result { fn toCResult(err: spv.Module.ModuleError) ffi.Result {
return switch (err) { return switch (err) {
spv.Module.ModuleError.InvalidSpirV => ffi.Result.InvalidSpirV, spv.Module.ModuleError.InvalidSpirV => ffi.Result.InvalidSpirV,
@@ -40,3 +54,17 @@ export fn SpvDeinitModule(module: *spv.Module) callconv(.c) void {
module.deinit(allocator); module.deinit(allocator);
allocator.destroy(module); allocator.destroy(module);
} }
export fn SpvModuleGetReflectionInfos(module: *spv.Module) callconv(.c) ReflectionInfos {
return .{
.local_size_x = module.reflection_infos.local_size_x,
.local_size_y = module.reflection_infos.local_size_y,
.local_size_z = module.reflection_infos.local_size_z,
.geometry_invocations = module.reflection_infos.geometry_invocations,
.geometry_output_count = module.reflection_infos.geometry_output_count,
.geometry_input = module.reflection_infos.geometry_input,
.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,
};
}
+1 -1
View File
@@ -4,7 +4,7 @@ pub const GLSLstd450Version: u32 = 100;
pub const GLSLstd450Revision: u32 = 3; pub const GLSLstd450Revision: u32 = 3;
pub const GLSLOp = enum(u32) { pub const GLSLOp = enum(u32) {
Bad = 0, Bad = 0, // Don't use
Round = 1, Round = 1,
RoundEven = 2, RoundEven = 2,
Trunc = 3, Trunc = 3,
File diff suppressed because it is too large Load Diff
+16 -12
View File
@@ -42,6 +42,20 @@ pub const ModuleError = error{
OutOfMemory, OutOfMemory,
}; };
pub const ReflectionInfos = struct {
local_size_x: SpvWord,
local_size_y: SpvWord,
local_size_z: SpvWord,
geometry_invocations: SpvWord,
geometry_output_count: SpvWord,
geometry_input: SpvWord,
geometry_output: SpvWord,
needs_derivatives: bool,
has_control_barriers: bool,
};
options: ModuleOptions, options: ModuleOptions,
it: WordIterator, it: WordIterator,
@@ -66,20 +80,13 @@ results: []Result,
entry_points: std.ArrayList(SpvEntryPoint), entry_points: std.ArrayList(SpvEntryPoint),
capabilities: std.EnumSet(spv.SpvCapability), capabilities: std.EnumSet(spv.SpvCapability),
local_size_x: SpvWord,
local_size_y: SpvWord,
local_size_z: SpvWord,
geometry_invocations: SpvWord,
geometry_output_count: SpvWord,
geometry_input: SpvWord,
geometry_output: SpvWord,
input_locations: [lib.SPIRV_MAX_INPUT_LOCATIONS][4]SpvWord, input_locations: [lib.SPIRV_MAX_INPUT_LOCATIONS][4]SpvWord,
output_locations: [lib.SPIRV_MAX_OUTPUT_LOCATIONS][4]SpvWord, output_locations: [lib.SPIRV_MAX_OUTPUT_LOCATIONS][4]SpvWord,
bindings: std.ArrayList(BindingEntry), bindings: std.ArrayList(BindingEntry),
builtins: std.EnumMap(spv.SpvBuiltIn, SpvWord), builtins: std.EnumMap(spv.SpvBuiltIn, SpvWord),
reflection_infos: ReflectionInfos,
pub fn init(allocator: std.mem.Allocator, source: []const SpvWord, options: ModuleOptions) ModuleError!Self { pub fn init(allocator: std.mem.Allocator, source: []const SpvWord, options: ModuleOptions) ModuleError!Self {
var self: Self = std.mem.zeroInit(Self, .{ var self: Self = std.mem.zeroInit(Self, .{
.options = options, .options = options,
@@ -88,9 +95,6 @@ pub fn init(allocator: std.mem.Allocator, source: []const SpvWord, options: Modu
.entry_points = std.ArrayList(SpvEntryPoint).empty, .entry_points = std.ArrayList(SpvEntryPoint).empty,
.bindings = std.ArrayList(BindingEntry).empty, .bindings = std.ArrayList(BindingEntry).empty,
.capabilities = std.EnumSet(spv.SpvCapability).initEmpty(), .capabilities = std.EnumSet(spv.SpvCapability).initEmpty(),
.local_size_x = 1,
.local_size_y = 1,
.local_size_z = 1,
}); });
errdefer allocator.free(self.code); errdefer allocator.free(self.code);
errdefer self.bindings.deinit(allocator); errdefer self.bindings.deinit(allocator);
+25 -15
View File
@@ -135,18 +135,19 @@ pub const SetupDispatcher = block: {
.ConstantComposite = opConstantComposite, .ConstantComposite = opConstantComposite,
.ConstantFalse = opConstantFalse, .ConstantFalse = opConstantFalse,
.ConstantTrue = opConstantTrue, .ConstantTrue = opConstantTrue,
.ControlBarrier = opControlBarrier,
.ConvertFToS = autoSetupConstant, .ConvertFToS = autoSetupConstant,
.ConvertFToU = autoSetupConstant, .ConvertFToU = autoSetupConstant,
.ConvertPtrToU = autoSetupConstant, .ConvertPtrToU = autoSetupConstant,
.ConvertSToF = autoSetupConstant, .ConvertSToF = autoSetupConstant,
.ConvertUToF = autoSetupConstant, .ConvertUToF = autoSetupConstant,
.ConvertUToPtr = autoSetupConstant, .ConvertUToPtr = autoSetupConstant,
.DPdx = autoSetupConstant, .DPdx = opDerivativeSetup,
.DPdxCoarse = autoSetupConstant, .DPdxCoarse = opDerivativeSetup,
.DPdxFine = autoSetupConstant, .DPdxFine = opDerivativeSetup,
.DPdy = autoSetupConstant, .DPdy = opDerivativeSetup,
.DPdyCoarse = autoSetupConstant, .DPdyCoarse = opDerivativeSetup,
.DPdyFine = autoSetupConstant, .DPdyFine = opDerivativeSetup,
.Fwidth = autoSetupConstant, .Fwidth = autoSetupConstant,
.FwidthCoarse = autoSetupConstant, .FwidthCoarse = autoSetupConstant,
.FwidthFine = autoSetupConstant, .FwidthFine = autoSetupConstant,
@@ -275,7 +276,7 @@ pub const SetupDispatcher = block: {
}; };
/// Not an EnumMap as it is way too slow for this purpose /// Not an EnumMap as it is way too slow for this purpose
pub var runtime_dispatcher = [_]?OpCodeFunc{null} ** spv.SpvOpMaxValue; pub var runtime_dispatcher: [spv.SpvOpMaxValue]?OpCodeFunc = @splat(null);
pub fn initRuntimeDispatcher() void { pub fn initRuntimeDispatcher() void {
// zig fmt: off // zig fmt: off
@@ -691,7 +692,7 @@ fn BitEngine(comptime T: PrimitiveType, comptime Op: BitOp) type {
const target_type = (try rt.results[try rt.it.next()].getVariant()).Type; const target_type = (try rt.results[try rt.it.next()].getVariant()).Type;
const dst = try rt.results[try rt.it.next()].getValue(); const dst = try rt.results[try rt.it.next()].getValue();
var ops = [_]?*Value{null} ** max_operator_count; var ops: [max_operator_count]?*Value = @splat(null);
ops[0] = try rt.results[try rt.it.next()].getValue(); ops[0] = try rt.results[try rt.it.next()].getValue();
if (comptime getOperatorsCount() >= 2) ops[1] = try rt.results[try rt.it.next()].getValue(); if (comptime getOperatorsCount() >= 2) ops[1] = try rt.results[try rt.it.next()].getValue();
@@ -2620,6 +2621,10 @@ fn opCapability(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!voi
rt.mod.capabilities.insert(try rt.it.nextAs(spv.SpvCapability)); rt.mod.capabilities.insert(try rt.it.nextAs(spv.SpvCapability));
} }
fn opControlBarrierSetup(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
rt.mod.reflection_infos.has_control_barriers = true;
}
fn opControlBarrier(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { fn opControlBarrier(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
_ = rt.it.skip(); // execution scope _ = rt.it.skip(); // execution scope
_ = rt.it.skip(); // memory scope _ = rt.it.skip(); // memory scope
@@ -3594,6 +3599,11 @@ fn opDecorationGroup(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeErro
_ = rt.it.skip(); _ = rt.it.skip();
} }
fn opDerivativeSetup(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
try autoSetupConstant(allocator, word_count, rt);
rt.mod.reflection_infos.needs_derivatives = true;
}
fn opGroupDecorate(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void { fn opGroupDecorate(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
const decoration_group = try rt.it.next(); const decoration_group = try rt.it.next();
@@ -3731,22 +3741,22 @@ fn opExecutionMode(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!
switch (mode) { switch (mode) {
.LocalSize => { .LocalSize => {
rt.mod.local_size_x = try rt.it.next(); rt.mod.reflection_infos.local_size_x = try rt.it.next();
rt.mod.local_size_y = try rt.it.next(); rt.mod.reflection_infos.local_size_y = try rt.it.next();
rt.mod.local_size_z = try rt.it.next(); rt.mod.reflection_infos.local_size_z = try rt.it.next();
}, },
.Invocations => rt.mod.geometry_invocations = try rt.it.next(), .Invocations => rt.mod.reflection_infos.geometry_invocations = try rt.it.next(),
.OutputVertices => rt.mod.geometry_output_count = try rt.it.next(), .OutputVertices => rt.mod.reflection_infos.geometry_output_count = try rt.it.next(),
.InputPoints, .InputPoints,
.InputLines, .InputLines,
.Triangles, .Triangles,
.InputLinesAdjacency, .InputLinesAdjacency,
.InputTrianglesAdjacency, .InputTrianglesAdjacency,
=> rt.mod.geometry_input = @intFromEnum(mode), => rt.mod.reflection_infos.geometry_input = @intFromEnum(mode),
.OutputPoints, .OutputPoints,
.OutputLineStrip, .OutputLineStrip,
.OutputTriangleStrip, .OutputTriangleStrip,
=> rt.mod.geometry_output = @intFromEnum(mode), => rt.mod.reflection_infos.geometry_output = @intFromEnum(mode),
else => {}, else => {},
} }
} }