authorgravatar for mick@sayson.comMick Sayson <mick@sayson.com> 2026-07-08 16:05:43-07:00
committergravatar for alichraghi@noreply.codeberg.orgAli Cheraghi <alichraghi@noreply.codeberg.org> 2026-07-10 11:40:29+02:00
logc2e6731032b72c20b5caf2182883aaede9c1a5ea
tree3ac2dc6baa4823e2138b01b7d14bd2b226bfdd5d
parentef3040786e502ea82e87ffefb9570b4e88dff79b

Implement spirv optional_payload_ptr_set

This fixes functions that return non-primitive optional values. E.g. fn someFnWithOptional(x: f32) ?[2]f32 { if (x > 5) return null; return .{ x, x }; } Pieced together referencing airIsNull, and airUnwrapOptionalPtr. Tested that shaders in an external project are outputting the expected values

1 files changed, 34 insertions(+), 0 deletions(-)

src/codegen/spirv/CodeGen.zig+34
......@@ -4459,6 +4459,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
44594459
44604460 .optional_payload => try cg.airUnwrapOptional(inst),
44614461 .optional_payload_ptr => try cg.airUnwrapOptionalPtr(inst),
4462 .optional_payload_ptr_set => try cg.airSetOptionalPtr(inst),
44624463 .wrap_optional => try cg.airWrapOptional(inst),
44634464
44644465 .assembly => try cg.airAssembly(inst),
......@@ -8017,6 +8018,39 @@ fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
80178018 return try cg.accessChain(result_ty_id, operand_id, &.{0});
80188019}
80198020
8021fn airSetOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
8022 const zcu = cg.zcu;
8023 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
8024
8025 const ptr_ty = cg.typeOf(ty_op.operand);
8026 const ptr_id = try cg.resolve(ty_op.operand);
8027
8028 const optional_ty = ptr_ty.childType(zcu);
8029 const payload_ty = optional_ty.optionalChild(zcu);
8030 const result_ty = cg.typeOfIndex(inst);
8031
8032 if (optional_ty.optionalReprIsPayload(zcu)) {
8033 return try cg.bitCast(result_ty, ptr_ty, ptr_id);
8034 }
8035
8036 const storage_class = cg.storageClass(ptr_ty.ptrAddressSpace(zcu));
8037 const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect);
8038 const bool_ptr_ty_id = try cg.ptrType(bool_indirect_ty_id, storage_class);
8039 const result_ty_id = try cg.resolveType(result_ty, .direct);
8040
8041 const bool_ptr_id, const ret = switch (payload_ty.hasRuntimeBits(zcu)) {
8042 true => .{
8043 try cg.accessChain(bool_ptr_ty_id, ptr_id, &.{1}),
8044 try cg.accessChain(result_ty_id, ptr_id, &.{0}),
8045 },
8046 false => .{ ptr_id, try cg.bitCast(result_ty, ptr_ty, ptr_id) },
8047 };
8048
8049 try cg.store(.bool, bool_ptr_id, try cg.constBool(true, .direct), .{});
8050
8051 return ret;
8052}
8053
80208054fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
80218055 const zcu = cg.zcu;
80228056 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;