authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-06-14 21:05:28+03:30
committergravatar for alichraghi@noreply.codeberg.orgAli Cheraghi <alichraghi@noreply.codeberg.org> 2026-06-18 13:38:58+02:00
logc9ca79fb487f934b001b4d947e8c8808b4062cb2
tree77d0fd7e1f38fdde7918af18a3e44bef9bc8d34f
parentc6d178f93de5922163b51cedbf05023623558c6b

std.spirv: add Scope, MemorySemantics, and barrier primitives

Exposes OpControlBarrier and OpMemoryBarrier so compute kernels do not need to hand-roll inline asm for workgroup synchronisation. Scope and MemorySemantics mirror the SPIRV-Headers unified1 grammar bit-for-bit; workgroupBarrier() matches the semantics of GLSL barrier(). Co-authored-by: Quint Daenen <quint@daenen.email>

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

lib/std/spirv.zig+63
...@@ -19,3 +19,66 @@ pub extern const local_invocation_id: @Vector(3, u32) addrspace(.input);...@@ -19,3 +19,66 @@ pub extern const local_invocation_id: @Vector(3, u32) addrspace(.input);
19pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input);19pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input);
20pub extern const vertex_index: u32 addrspace(.input);20pub extern const vertex_index: u32 addrspace(.input);
21pub extern const instance_index: u32 addrspace(.input);21pub extern const instance_index: u32 addrspace(.input);
22
23pub const Scope = enum(u32) {
24 cross_device = 0,
25 device = 1,
26 workgroup = 2,
27 subgroup = 3,
28 invocation = 4,
29 queue_family = 5,
30 shader_call_khr = 6,
31};
32
33pub const MemorySemantics = packed struct(u32) {
34 _reserved_bit_0: bool = false,
35 acquire: bool = false,
36 release: bool = false,
37 acquire_release: bool = false,
38 sequentially_consistent: bool = false,
39 _reserved_bit_5: bool = false,
40 uniform_memory: bool = false,
41 subgroup_memory: bool = false,
42 workgroup_memory: bool = false,
43 cross_workgroup_memory: bool = false,
44 atomic_counter_memory: bool = false,
45 image_memory: bool = false,
46 output_memory: bool = false,
47 make_available: bool = false,
48 make_visible: bool = false,
49 @"volatile": bool = false,
50 _reserved: u16 = 0,
51
52 pub const none: MemorySemantics = .{};
53};
54
55pub fn controlBarrier(
56 comptime execution: Scope,
57 comptime memory: Scope,
58 comptime semantics: MemorySemantics,
59) void {
60 asm volatile (
61 \\OpControlBarrier %exec %mem %sem
62 :
63 : [exec] "" (@as(u32, @intFromEnum(execution))),
64 [mem] "" (@as(u32, @intFromEnum(memory))),
65 [sem] "" (@as(u32, @bitCast(semantics))),
66 );
67}
68
69pub fn memoryBarrier(comptime memory: Scope, comptime semantics: MemorySemantics) void {
70 asm volatile (
71 \\OpMemoryBarrier %mem %sem
72 :
73 : [mem] "" (@as(u32, @intFromEnum(memory))),
74 [sem] "" (@as(u32, @bitCast(semantics))),
75 );
76}
77
78pub fn workgroupBarrier() void {
79 controlBarrier(
80 .workgroup,
81 .workgroup,
82 .{ .acquire_release = true, .workgroup_memory = true },
83 );
84}