master
1const std = @import("std.zig");
2
3pub const position_in = @extern(*addrspace(.input) @Vector(4, f32), .{ .name = "position" });
4pub const position_out = @extern(*addrspace(.output) @Vector(4, f32), .{ .name = "position" });
5pub const point_size_in = @extern(*addrspace(.input) f32, .{ .name = "point_size" });
6pub const point_size_out = @extern(*addrspace(.output) f32, .{ .name = "point_size" });
7pub extern const invocation_id: u32 addrspace(.input);
8pub extern const frag_coord: @Vector(4, f32) addrspace(.input);
9pub extern const point_coord: @Vector(2, f32) addrspace(.input);
10// TODO: direct/indirect values
11// pub extern const front_facing: bool addrspace(.input);
12// TODO: runtime array
13// pub extern const sample_mask;
14pub extern var frag_depth: f32 addrspace(.output);
15pub extern const num_workgroups: @Vector(3, u32) addrspace(.input);
16pub extern const workgroup_size: @Vector(3, u32) addrspace(.input);
17pub extern const workgroup_id: @Vector(3, u32) addrspace(.input);
18pub extern const local_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);
21pub extern const instance_index: u32 addrspace(.input);
22
23/// Forms the main linkage for `input` and `output` address spaces.
24/// `ptr` must be a reference to variable or struct field.
25pub fn location(comptime ptr: anytype, comptime loc: u32) void {
26 asm volatile (
27 \\OpDecorate %ptr Location $loc
28 :
29 : [ptr] "" (ptr),
30 [loc] "c" (loc),
31 );
32}
33
34/// Forms the main linkage for `input` and `output` address spaces.
35/// `ptr` must be a reference to variable or struct field.
36pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void {
37 asm volatile (
38 \\OpDecorate %ptr DescriptorSet $set
39 \\OpDecorate %ptr Binding $bind
40 :
41 : [ptr] "" (ptr),
42 [set] "c" (set),
43 [bind] "c" (bind),
44 );
45}
46
47pub const ExecutionMode = union(Tag) {
48 /// Sets origin of the framebuffer to the upper-left corner
49 origin_upper_left,
50 /// Sets origin of the framebuffer to the lower-left corner
51 origin_lower_left,
52 /// Indicates that the fragment shader writes to `frag_depth`,
53 /// replacing the fixed-function depth value.
54 depth_replacing,
55 /// Indicates that per-fragment tests may assume that
56 /// any `frag_depth` built in-decorated value written by the shader is
57 /// greater-than-or-equal to the fragment’s interpolated depth value
58 depth_greater,
59 /// Indicates that per-fragment tests may assume that
60 /// any `frag_depth` built in-decorated value written by the shader is
61 /// less-than-or-equal to the fragment’s interpolated depth value
62 depth_less,
63 /// Indicates that per-fragment tests may assume that
64 /// any `frag_depth` built in-decorated value written by the shader is
65 /// the same as the fragment’s interpolated depth value
66 depth_unchanged,
67 /// Indicates the workgroup size in the x, y, and z dimensions.
68 local_size: LocalSize,
69
70 pub const Tag = enum(u32) {
71 origin_upper_left = 7,
72 origin_lower_left = 8,
73 depth_replacing = 12,
74 depth_greater = 14,
75 depth_less = 15,
76 depth_unchanged = 16,
77 local_size = 17,
78 };
79
80 pub const LocalSize = struct { x: u32, y: u32, z: u32 };
81};
82
83/// Declare the mode entry point executes in.
84pub fn executionMode(comptime entry_point: anytype, comptime mode: ExecutionMode) void {
85 const cc = @typeInfo(@TypeOf(entry_point)).@"fn".calling_convention;
86 switch (mode) {
87 .origin_upper_left,
88 .origin_lower_left,
89 .depth_replacing,
90 .depth_greater,
91 .depth_less,
92 .depth_unchanged,
93 => {
94 if (cc != .spirv_fragment) {
95 @compileError(
96 \\invalid execution mode '
97 ++ @tagName(mode) ++
98 \\' for function with '
99 ++ @tagName(cc) ++
100 \\' calling convention
101 );
102 }
103 asm volatile (
104 \\OpExecutionMode %entry_point $mode
105 :
106 : [entry_point] "" (entry_point),
107 [mode] "c" (@intFromEnum(mode)),
108 );
109 },
110 .local_size => |size| {
111 if (cc != .spirv_kernel) {
112 @compileError(
113 \\invalid execution mode 'local_size' for function with '
114 ++ @tagName(cc) ++
115 \\' calling convention
116 );
117 }
118 asm volatile (
119 \\OpExecutionMode %entry_point LocalSize $x $y $z
120 :
121 : [entry_point] "" (entry_point),
122 [x] "c" (size.x),
123 [y] "c" (size.y),
124 [z] "c" (size.z),
125 );
126 },
127 }
128}