From cb0cdaab3690b83973d0b5a39cddde7c85619e3d Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 21 Mar 2026 22:30:39 +0100 Subject: [PATCH] reworking opBitcast, fixing some glsl functions --- src/GLSL_std_450/opcodes.zig | 64 +++++++++++++++++++++++------------- src/Value.zig | 20 +++++++++++ src/opcodes.zig | 35 +++++--------------- 3 files changed, 69 insertions(+), 50 deletions(-) diff --git a/src/GLSL_std_450/opcodes.zig b/src/GLSL_std_450/opcodes.zig index 4c22a0f..982157d 100644 --- a/src/GLSL_std_450/opcodes.zig +++ b/src/GLSL_std_450/opcodes.zig @@ -80,6 +80,7 @@ pub fn initRuntimeDispatcher() void { runtime_dispatcher[@intFromEnum(ext.GLSLOp.Exp2)] = MathEngine(.Float, .Exp2).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.FAbs)] = MathEngine(.Float, .FAbs).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.FMax)] = MathEngine(.Float, .FMax).opDoubleOperators; + runtime_dispatcher[@intFromEnum(ext.GLSLOp.FSign)] = MathEngine(.Float, .FSign).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Floor)] = MathEngine(.Float, .Floor).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Length)] = opLength; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Log)] = MathEngine(.Float, .Log).opSingleOperator; @@ -87,6 +88,7 @@ pub fn initRuntimeDispatcher() void { runtime_dispatcher[@intFromEnum(ext.GLSLOp.Normalize)] = opNormalize; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Round)] = MathEngine(.Float, .Round).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.SAbs)] = MathEngine(.SInt, .SAbs).opSingleOperator; + runtime_dispatcher[@intFromEnum(ext.GLSLOp.SSign)] = MathEngine(.SInt, .SSign).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Sin)] = MathEngine(.Float, .Sin).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Sqrt)] = MathEngine(.Float, .Sqrt).opSingleOperator; runtime_dispatcher[@intFromEnum(ext.GLSLOp.Tan)] = MathEngine(.Float, .Tan).opSingleOperator; @@ -94,6 +96,14 @@ pub fn initRuntimeDispatcher() void { // zig fmt: on } +fn isFloatOrF32Vector(comptime T: type) bool { + return switch (@typeInfo(T)) { + .float => true, + .vector => |vec| vec.child == f32, + else => false, + }; +} + fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type { return struct { fn opSingleOperator(_: std.mem.Allocator, target_type_id: SpvWord, id: SpvWord, _: SpvWord, rt: *Runtime) RuntimeError!void { @@ -105,23 +115,31 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type { const operator = struct { fn operation(comptime TT: type, x: TT) RuntimeError!TT { - return switch (Op) { - .Ceil => @ceil(x), - .Cos => @cos(x), - .Exp => @exp(x), - .Exp2 => @exp2(x), - .FAbs => @abs(x), - .Floor => @floor(x), - .Log => @log(x), - .Log2 => @log2(x), - .Round => @round(x), - .SAbs => if (comptime @typeInfo(TT) == .int) @intCast(@abs(x)) else return RuntimeError.InvalidSpirV, - .Sin => @sin(x), - .Sqrt => @sqrt(x), - .Tan => @tan(x), - .Trunc => @trunc(x), - else => RuntimeError.InvalidSpirV, - }; + if (comptime isFloatOrF32Vector(TT)) { + return switch (Op) { + .Ceil => @ceil(x), + .Cos => @cos(x), + .Exp => @exp(x), + .Exp2 => @exp2(x), + .FAbs => @abs(x), + .FSign => std.math.sign(x), + .Floor => @floor(x), + .Log => @log(x), + .Log2 => @log2(x), + .Round => @round(x), + .Sin => @sin(x), + .Sqrt => @sqrt(x), + .Tan => @tan(x), + .Trunc => @trunc(x), + else => return RuntimeError.InvalidSpirV, + }; + } else { + return switch (Op) { + .SAbs => @intCast(@abs(x)), + .SSign => std.math.sign(x), + else => RuntimeError.InvalidSpirV, + }; + } } fn applyScalar(bit_count: SpvWord, d: *Value, s: *const Value) RuntimeError!void { @@ -150,13 +168,13 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type { .Vector3f32 => |*d| d.* = try operator.operation(@Vector(3, f32), src.Vector3f32), .Vector2f32 => |*d| d.* = try operator.operation(@Vector(2, f32), src.Vector2f32), - //.Vector4i32 => |*d| d.* = try operator.operation(@Vector(4, i32), src.Vector4i32), - //.Vector3i32 => |*d| d.* = try operator.operation(@Vector(3, i32), src.Vector3i32), - //.Vector2i32 => |*d| d.* = try operator.operation(@Vector(2, i32), src.Vector2i32), + .Vector4i32 => |*d| d.* = try operator.operation(@Vector(4, i32), src.Vector4i32), + .Vector3i32 => |*d| d.* = try operator.operation(@Vector(3, i32), src.Vector3i32), + .Vector2i32 => |*d| d.* = try operator.operation(@Vector(2, i32), src.Vector2i32), - //.Vector4u32 => |*d| d.* = try operator.operation(@Vector(4, u32), src.Vector4u32), - //.Vector3u32 => |*d| d.* = try operator.operation(@Vector(3, u32), src.Vector3u32), - //.Vector2u32 => |*d| d.* = try operator.operation(@Vector(2, u32), src.Vector2u32), + .Vector4u32 => |*d| d.* = try operator.operation(@Vector(4, u32), src.Vector4u32), + .Vector3u32 => |*d| d.* = try operator.operation(@Vector(3, u32), src.Vector3u32), + .Vector2u32 => |*d| d.* = try operator.operation(@Vector(2, u32), src.Vector2u32), else => return RuntimeError.InvalidSpirV, } diff --git a/src/Value.zig b/src/Value.zig index d6cc4ce..6c6065a 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -441,6 +441,26 @@ pub const Value = union(Type) { return 0; } + pub fn getPlainMemorySize(self: *const Self) RuntimeError!usize { + return switch (self.*) { + .Bool => 1, + .Int => |i| @divExact(i.bit_count, 8), + .Float => |f| @divExact(f.bit_count, 8), + .Vector4f32, .Vector4i32, .Vector4u32 => 4 * 4, + .Vector3f32, .Vector3i32, .Vector3u32 => 3 * 4, + .Vector2f32, .Vector2i32, .Vector2u32 => 2 * 4, + .Vector, .Matrix, .Array, .Structure => |values| blk: { + var size: usize = 0; + for (values) |v| { + size += try v.getPlainMemorySize(); + } + break :blk size; + }, + .RuntimeArray => |arr| arr.getLen(), + else => return RuntimeError.InvalidValueType, + }; + } + pub fn flushPtr(self: *Self, allocator: std.mem.Allocator) RuntimeError!void { switch (self.*) { .Pointer => |*p| { diff --git a/src/opcodes.zig b/src/opcodes.zig index 498f175..17b1d9d 100644 --- a/src/opcodes.zig +++ b/src/opcodes.zig @@ -931,10 +931,6 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type { d[i] = try operation(ElemT, v[i]); } } - - inline fn applySIMDVectorf32(comptime N: usize, d: *@Vector(N, f32), v: *const @Vector(N, f32)) RuntimeError!void { - try applySIMDVector(f32, N, d, v); - } }; switch (dst.*) { @@ -1010,34 +1006,19 @@ fn autoSetupConstant(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) Run _ = try setupConstant(allocator, rt); } -fn opBitcast(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { +fn opBitcast(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { _ = rt.it.skip(); const to_value = try rt.results[try rt.it.next()].getValue(); const from_value = try rt.results[try rt.it.next()].getValue(); - const caster = struct { - /// Asumes that values passed are primitives ints or floats - fn cast(to: *Value, from: *const Value) RuntimeError!void { - const from_bytes: u64 = switch (from.*) { - .Float => |f| @bitCast(f.value.float64), - .Int => |i| i.value.uint64, - else => return RuntimeError.InvalidSpirV, - }; + var arena: std.heap.ArenaAllocator = .init(allocator); + defer arena.deinit(); + const local_allocator = arena.allocator(); - switch (to.*) { - .Float => |*f| f.value.float64 = @bitCast(from_bytes), - .Int => |*i| i.value.uint64 = from_bytes, - else => return RuntimeError.InvalidSpirV, - } - } - }; - - switch (to_value.*) { - .Int, .Float => try caster.cast(to_value, from_value), - .Vector => |vec| for (vec, from_value.Vector) |*t, *f| try caster.cast(t, f), - // TODO: vectors specializations - else => return RuntimeError.InvalidSpirV, - } + const size = try to_value.getPlainMemorySize(); + const bytes = local_allocator.alloc(u8, size) catch return RuntimeError.OutOfMemory; + _ = try from_value.read(bytes); + _ = try to_value.write(bytes); } fn copyValue(dst: *Value, src: *const Value) void {