authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-07-05 11:18:26+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-07-05 11:18:26+03:30
logde1adf89ef1a50d9ac6e8fcbab258c257c9a32e4
tree00a55652b1fd00837d178e7896fff05944c33e60
parent16c4ed275d0254ce7ba0bd1daa60f9ec4b39e316

spirv: emit Block-decorated interface types for union push/storage/uniform vars


1 files changed, 72 insertions(+), 3 deletions(-)

src/codegen/spirv/CodeGen.zig+72-3
...@@ -625,6 +625,49 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id {...@@ -625,6 +625,49 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id {
625 });625 });
626 break :id id;626 break :id id;
627 },627 },
628 .@"union" => id: {
629 const union_obj = zcu.typeToUnion(ty).?;
630 if (union_obj.layout == .@"packed") return cg.resolveType(ty, .indirect);
631
632 const layout = cg.unionLayout(ty);
633 if (!layout.has_payload) return cg.resolveType(ty, .indirect);
634
635 const id = cg.allocId();
636 if (is_block_root) try cg.decorate(id, .block);
637
638 var member_types: [4]Id = undefined;
639 const u8_id = try cg.resolveType(.u8, .direct);
640 if (layout.tag_size != 0) {
641 const tag_ty: Type = .fromInterned(union_obj.enum_tag_type);
642 try cg.decorateMember(id, layout.tag_index, .{ .offset = .{
643 .byte_offset = @intCast(ty.unionGetLayout(zcu).tagOffset()),
644 } });
645 member_types[layout.tag_index] = try cg.layoutType(tag_ty, false);
646 }
647 if (layout.payload_size != 0) {
648 try cg.decorateMember(id, layout.payload_index, .{ .offset = .{
649 .byte_offset = @intCast(ty.unionGetLayout(zcu).payloadOffset()),
650 } });
651 member_types[layout.payload_index] = try cg.layoutType(layout.payload_ty, false);
652 }
653 if (layout.payload_padding_size != 0) {
654 const len_id = try cg.constInt(.u32, layout.payload_padding_size);
655 const arr_id = try cg.arrayType(len_id, u8_id);
656 try cg.decorate(arr_id, .{ .array_stride = .{ .array_stride = 1 } });
657 member_types[layout.payload_padding_index] = arr_id;
658 }
659 if (layout.padding_size != 0) {
660 const len_id = try cg.constInt(.u32, layout.padding_size);
661 const arr_id = try cg.arrayType(len_id, u8_id);
662 try cg.decorate(arr_id, .{ .array_stride = .{ .array_stride = 1 } });
663 member_types[layout.padding_index] = arr_id;
664 }
665 try cg.sections.globals.emit(gpa, .OpTypeStruct, .{
666 .id_result = id,
667 .id_ref = member_types[0..layout.total_fields],
668 });
669 break :id id;
670 },
628 .array => id: {671 .array => id: {
629 const elem_ty = ty.childType(zcu);672 const elem_ty = ty.childType(zcu);
630 const elem_ty_id = try cg.layoutType(elem_ty, false);673 const elem_ty_id = try cg.layoutType(elem_ty, false);
...@@ -1883,8 +1926,13 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {...@@ -1883,8 +1926,13 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
18831926
1884 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);1927 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
1885 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class);1928 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class);
1886 if (nav_ty.zigTypeTag(zcu) == .@"struct" and cg.needsLayout(nav.resolved.?.@"addrspace", nav_ty)) {1929 switch (nav_ty.zigTypeTag(zcu)) {
1887 try cg.block_var_ids.put(gpa, spv_decl.result_id, {});1930 .@"struct", .@"union" => {
1931 if (cg.needsLayout(nav.resolved.?.@"addrspace", nav_ty)) {
1932 try cg.block_var_ids.put(gpa, spv_decl.result_id, {});
1933 }
1934 },
1935 else => {},
1888 }1936 }
1889 if (decl_ptr_ty_id == ty_id) return spv_decl.result_id;1937 if (decl_ptr_ty_id == ty_id) return spv_decl.result_id;
1890 switch (target.os.tag) {1938 switch (target.os.tag) {
...@@ -4175,7 +4223,7 @@ fn needsLayout(cg: *CodeGen, as: std.lang.AddressSpace, pointee_ty: Type) bool {...@@ -4175,7 +4223,7 @@ fn needsLayout(cg: *CodeGen, as: std.lang.AddressSpace, pointee_ty: Type) bool {
4175 else => return false,4223 else => return false,
4176 }4224 }
4177 return switch (pointee_ty.zigTypeTag(cg.zcu)) {4225 return switch (pointee_ty.zigTypeTag(cg.zcu)) {
4178 .@"struct", .array => true,4226 .@"struct", .@"union", .array => true,
4179 .spirv => pointee_ty.isSpirvRuntimeArray(cg.zcu),4227 .spirv => pointee_ty.isSpirvRuntimeArray(cg.zcu),
4180 else => false,4228 else => false,
4181 };4229 };
...@@ -6905,6 +6953,16 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {...@@ -6905,6 +6953,16 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
6905 return try cg.load(field_ty, pl_ptr_id, .{});6953 return try cg.load(field_ty, pl_ptr_id, .{});
6906 }6954 }
69076955
6956 switch (zcu.getTarget().os.tag) {
6957 .vulkan, .opengl => {
6958 // Logical addressing forbids OpBitcast on pointers. Load the
6959 // payload as its type and bitcast the value instead.
6960 const payload_id = try cg.load(layout.payload_ty, pl_ptr_id, .{});
6961 return try cg.bitCast(field_ty, layout.payload_ty, payload_id);
6962 },
6963 else => {},
6964 }
6965
6908 const field_ty_id = try cg.resolveType(field_ty, .indirect);6966 const field_ty_id = try cg.resolveType(field_ty, .indirect);
6909 const active_pl_ptr_ty_id = try cg.ptrType(field_ty_id, .function);6967 const active_pl_ptr_ty_id = try cg.ptrType(field_ty_id, .function);
6910 const active_pl_ptr_id = cg.allocId();6968 const active_pl_ptr_id = cg.allocId();
...@@ -7023,6 +7081,17 @@ fn structFieldPtr(...@@ -7023,6 +7081,17 @@ fn structFieldPtr(
7023 return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index});7081 return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index});
7024 }7082 }
70257083
7084 switch (zcu.getTarget().os.tag) {
7085 .vulkan, .opengl => {
7086 // Logical addressing forbids OpBitcast on pointers. If the field
7087 // type is structurally identical to the payload type (dedup will
7088 // unify them) the access chain typed as the field type is valid.
7089 if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr;
7090 return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index});
7091 },
7092 else => {},
7093 }
7094
7026 const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);7095 const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);
7027 const pl_ptr_ty_id = try cg.ptrType(layout_payload_ty_id, storage_class);7096 const pl_ptr_ty_id = try cg.ptrType(layout_payload_ty_id, storage_class);
7028 const pl_ptr_id = blk: {7097 const pl_ptr_id = blk: {