authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-08-25 21:55:19+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-08-26 08:13:06+03:30
log591b2a47f79fa07e87d3b625320135de8446a274
treefd3bdbf644552665d34841fd31774fa5c158acad
parent21575a44837861c0c9a7b2b42904afb0933995ea

spirv: emit descriptor arrays for uniform and storage buffers


1 files changed, 25 insertions(+), 13 deletions(-)

src/codegen/spirv/CodeGen.zig+25-13
...@@ -617,7 +617,8 @@ pub fn structType(...@@ -617,7 +617,8 @@ pub fn structType(
617617
618/// Returns the layout-decorated variant of `ty` for use inside a Vulkan/OpenGL618/// Returns the layout-decorated variant of `ty` for use inside a Vulkan/OpenGL
619/// interface block. Vulkan forbids nested Block decorations, so recursive calls619/// interface block. Vulkan forbids nested Block decorations, so recursive calls
620/// always pass `false`.620/// pass `false`, except through an array, whose elements are each a
621/// block of their own.
621///622///
622/// This is distinct from `resolveType` because SPIR-V forbids such decorations623/// This is distinct from `resolveType` because SPIR-V forbids such decorations
623/// on the pointee of a Function-scope variable.624/// on the pointee of a Function-scope variable.
...@@ -695,26 +696,30 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id {...@@ -695,26 +696,30 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id {
695 },696 },
696 .array => id: {697 .array => id: {
697 const elem_ty = ty.childType(zcu);698 const elem_ty = ty.childType(zcu);
698 const elem_ty_id = try cg.layoutType(elem_ty, false);699 const elem_ty_id = try cg.layoutType(elem_ty, is_block_root);
699 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(zcu)) orelse700 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(zcu)) orelse
700 return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)});701 return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)});
701 const id = try cg.arrayType(try cg.constInt(.u32, total_len), elem_ty_id);702 const id = try cg.arrayType(try cg.constInt(.u32, total_len), elem_ty_id);
702 if (elem_ty.hasRuntimeBits(zcu)) try cg.decorate(id, .{703 if (!is_block_root and elem_ty.hasRuntimeBits(zcu)) {
703 .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) },704 try cg.decorate(id, .{
704 });705 .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) },
706 });
707 }
705 break :id id;708 break :id id;
706 },709 },
707 .spirv => if (ty.isSpirvRuntimeArray(zcu)) id: {710 .spirv => if (ty.isSpirvRuntimeArray(zcu)) id: {
708 const elem_ty = ty.childType(zcu);711 const elem_ty = ty.childType(zcu);
709 const elem_ty_id = try cg.layoutType(elem_ty, false);712 const elem_ty_id = try cg.layoutType(elem_ty, is_block_root);
710 const id = cg.allocId();713 const id = cg.allocId();
711 try cg.sections.globals.emit(gpa, .OpTypeRuntimeArray, .{714 try cg.sections.globals.emit(gpa, .OpTypeRuntimeArray, .{
712 .id_result = id,715 .id_result = id,
713 .element_type = elem_ty_id,716 .element_type = elem_ty_id,
714 });717 });
715 if (elem_ty.hasRuntimeBits(zcu)) try cg.decorate(id, .{718 if (!is_block_root and elem_ty.hasRuntimeBits(zcu)) {
716 .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) },719 try cg.decorate(id, .{
717 });720 .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) },
721 });
722 }
718 break :id id;723 break :id id;
719 } else return cg.resolveType(ty, .indirect),724 } else return cg.resolveType(ty, .indirect),
720 else => return cg.resolveType(ty, .indirect),725 else => return cg.resolveType(ty, .indirect),
...@@ -955,11 +960,18 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {...@@ -955,11 +960,18 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
955 switch (target.os.tag) {960 switch (target.os.tag) {
956 .vulkan, .opengl => {961 .vulkan, .opengl => {
957 switch (storage_class) {962 switch (storage_class) {
958 .uniform, .push_constant, .storage_buffer, .physical_storage_buffer => {963 .uniform,
964 .push_constant,
965 .storage_buffer,
966 .physical_storage_buffer,
967 => {
959 if (ty.hasRuntimeBits(zcu)) {968 if (ty.hasRuntimeBits(zcu)) {
960 try cg.decorate(ptr_ty_id, .{969 if (!ty.isSpirvRuntimeArray(zcu)) {
961 .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) },970 try cg.decorate(
962 });971 ptr_ty_id,
972 .{ .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) } },
973 );
974 }
963 if (!cg.needsLayout(as, ty)) try cg.decorateLayout(ty, ty_id);975 if (!cg.needsLayout(as, ty)) try cg.decorateLayout(ty, ty_id);
964 }976 }
965 if (key.is_const and storage_class == .storage_buffer) {977 if (key.is_const and storage_class == .storage_buffer) {