From 4ddb82ec2cdc9e68fdc6b938cb0c95d7a7342bb1 Mon Sep 17 00:00:00 2001 From: Subo2002 Date: Mon, 24 Aug 2026 17:49:49 +0100 Subject: [PATCH 1/2] Added missing local workgroup sizes to spirv_mesh's SpirvMeshOptions and associated decorations --- lib/std/lang.zig | 3 +++ src/InternPool.zig | 12 +++++++++--- src/Sema.zig | 3 +++ src/link/SpirV.zig | 4 ++++ test/cases/callconv_spirv.zig | 2 +- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/std/lang.zig b/lib/std/lang.zig index 1c47d2d8919dd40b950d389c98a88d26c3e4dcb4..7402e9f094ded1419d8cf8529d0f7f48333e0ce4 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -545,6 +545,9 @@ pub const CallingConvention = union(enum(u8)) { stage_output: StageOutput = .output_triangles, max_primitives: u32 = 1, max_vertices: u32 = 3, + x: u32, + y: u32, + z: u32, }; /// Returns the array of `std.Target.Cpu.Arch` to which this `CallingConvention` applies. diff --git a/src/InternPool.zig b/src/InternPool.zig index 96af077d99935e56e6290ca47b544b6e6bd076fc..cb74519a78e3b852aba36950ab7681e8ca9e13b5 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -5186,7 +5186,7 @@ pub const Tag = enum(u8) { param_comptime_bits: ?[]u32, param_noalias_bits: ?[]u32, spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 }, - spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 }, + spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32, x: u32, y: u32, z: u32 }, param_types: []Index, }, .config = .{ @@ -9104,6 +9104,9 @@ pub fn getFuncType( .spirv_mesh => |mesh| extra.appendSliceAssumeCapacity(.{&.{ mesh.max_primitives, mesh.max_vertices, + mesh.x, + mesh.y, + mesh.z, }}), else => {}, }; @@ -12591,10 +12594,10 @@ const PackedCallingConvention = packed struct(u18) { }; } - fn extraLen(cc: PackedCallingConvention) u2 { + fn extraLen(cc: PackedCallingConvention) u3 { return switch (cc.tag) { .spirv_kernel, .spirv_task => 3, - .spirv_mesh => 2, + .spirv_mesh => 5, else => 0, }; } @@ -12650,6 +12653,9 @@ const PackedCallingConvention = packed struct(u18) { .stage_output = @fromBackingInt(@intCast(cc.extra)), .max_primitives = trailing[0], .max_vertices = trailing[1], + .x = trailing[2], + .y = trailing[3], + .z = trailing[4], }, else => comptime unreachable, }, diff --git a/src/Sema.zig b/src/Sema.zig index 3bef560c7a1bab9caf91761bae10526c178aaa49..b7b4349ab564bfad5d5f269e6b73e509bcc02895 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8777,6 +8777,9 @@ fn checkReturnTypeAndCallConv( if (mesh.max_vertices == 0 or mesh.max_primitives == 0) { return sema.fail(block, callconv_src, "mesh shader 'max_vertices' and 'max_primitives' must be at least 1", .{}); } + if (mesh.x == 0 or mesh.y == 0 or mesh.z == 0) { + return sema.fail(block, callconv_src, "mesh shader workgroup dimensions must be at least 1", .{}); + } if (!target.cpu.has(.spirv, .mesh_shading_ext)) { return sema.fail(block, callconv_src, "calling convention '{t}' requires the 'mesh_shading_ext' feature", .{@"callconv"}); } diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 3129a511da65dee9d42447994d782f294b1dfb08..30b020985091d2b62bcb0358da3ff90d61f2b69d 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -757,6 +757,10 @@ fn emitEntryPoints( .entry_point = final_id, .mode = .{ .output_primitives_ext = .{ .primitive_count = mesh.max_primitives } }, }); + try execution_modes_section.emit(gpa, .OpExecutionMode, .{ + .entry_point = final_id, + .mode = .{ .local_size = .{ .x_size = mesh.x, .y_size = mesh.y, .z_size = mesh.z } }, + }); try execution_modes_section.emit(gpa, .OpExecutionMode, .{ .entry_point = final_id, .mode = switch (mesh.stage_output) { diff --git a/test/cases/callconv_spirv.zig b/test/cases/callconv_spirv.zig index 25be9d0c27a7493811da50525ce5de0bf696c001..0d30666e4f6594655239ff46199d290ba5103e65 100644 --- a/test/cases/callconv_spirv.zig +++ b/test/cases/callconv_spirv.zig @@ -2,7 +2,7 @@ export fn vert() callconv(.spirv_vertex) void {} export fn frag() callconv(.{ .spirv_fragment = .{ .depth_assumption = .greater } }) void {} export fn comp() callconv(.{ .spirv_kernel = .{ .x = 8, .y = 8, .z = 1 } }) void {} export fn task() callconv(.{ .spirv_task = .{ .x = 1, .y = 1, .z = 1 } }) void {} -export fn mesh() callconv(.{ .spirv_mesh = .{ .stage_output = .output_lines, .max_primitives = 1, .max_vertices = 2 } }) void {} +export fn mesh() callconv(.{ .spirv_mesh = .{ .stage_output = .output_lines, .max_primitives = 1, .max_vertices = 2, .x = 1, .y = 1, .z = 1 } }) void {} // compile // output_mode=Obj -- 2.54.0 From 25890f9080337a0e5968d92369ea221127611ca4 Mon Sep 17 00:00:00 2001 From: Subo2002 Date: Mon, 24 Aug 2026 23:28:31 +0100 Subject: [PATCH 2/2] callconv_spirv_on_unsupported_platform test was missing initiailization for the new x, y, z fields and so failing the wrong way --- .../compile_errors/callconv_spirv_on_unsupported_platform.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig index 1c41095021ad498dce4178d67556f1eb7b45e8d4..1eb4fee387f27948dae6582b1a06eabeaab99849 100644 --- a/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig +++ b/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig @@ -1,7 +1,7 @@ const F1 = fn () callconv(.{ .spirv_fragment = .{} }) void; const F2 = fn () callconv(.spirv_vertex) void; const F3 = fn () callconv(.{ .spirv_task = .{ .x = 1, .y = 1, .z = 1 } }) void; -const F4 = fn () callconv(.{ .spirv_mesh = .{} }) void; +const F4 = fn () callconv(.{ .spirv_mesh = .{ .x = 1, .y = 1, .z = 1 } }) void; export fn entry1() void { const a: F1 = undefined; _ = a; -- 2.54.0