From ac58b7d33eff8e6748b6bb1c296f18cc6ae6d5a6 Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Fri, 2 Feb 2024 17:48:40 +0330 Subject: [PATCH] std: add gpu namespace --- lib/std/gpu.zig | 192 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/std/std.zig | 3 + 2 files changed, 195 insertions(+) create mode 100644 lib/std/gpu.zig diff --git a/lib/std/gpu.zig b/lib/std/gpu.zig new file mode 100644 index 000000000000..0c998c86c222 --- /dev/null +++ b/lib/std/gpu.zig @@ -0,0 +1,192 @@ +const std = @import("std.zig"); +const comptimePrint = std.fmt.comptimePrint; + +/// Will make `ptr` contain the location of the current invocation within the +/// global workgroup. Each component is equal to the index of the local workgroup +/// multiplied by the size of the local workgroup plus `localInvocationId`. +/// `ptr` must be a reference to variable or struct field. +pub fn globalInvocationId(comptime ptr: *addrspace(.input) @Vector(3, u32)) void { + asm volatile ( + \\OpDecorate %ptr BuiltIn GlobalInvocationId + : + : [ptr] "" (ptr), + ); +} + +/// Will make that variable contain the location of the current cluster +/// culling, task, mesh, or compute shader invocation within the local +/// workgroup. Each component ranges from zero through to the size of the +/// workgroup in that dimension minus one. +/// `ptr` must be a reference to variable or struct field. +pub fn localInvocationId(comptime ptr: *addrspace(.input) @Vector(3, u32)) void { + asm volatile ( + \\OpDecorate %ptr BuiltIn LocalInvocationId + : + : [ptr] "" (ptr), + ); +} + +/// Output vertex position from a `Vertex` entrypoint +/// `ptr` must be a reference to variable or struct field. +pub fn position(comptime ptr: *addrspace(.output) @Vector(4, f32)) void { + asm volatile ( + \\OpDecorate %ptr BuiltIn Position + : + : [ptr] "" (ptr), + ); +} + +/// Will make `ptr` contain the index of the vertex that is +/// being processed by the current vertex shader invocation. +/// `ptr` must be a reference to variable or struct field. +pub fn vertexIndex(comptime ptr: *addrspace(.input) u32) void { + asm volatile ( + \\OpDecorate %ptr BuiltIn VertexIndex + : + : [ptr] "" (ptr), + ); +} + +/// Output fragment depth from a `Fragment` entrypoint +/// `ptr` must be a reference to variable or struct field. +pub fn fragmentCoord(comptime ptr: *addrspace(.input) @Vector(4, f32)) void { + asm volatile ( + \\OpDecorate %ptr BuiltIn FragCoord + : + : [ptr] "" (ptr), + ); +} + +/// Output fragment depth from a `Fragment` entrypoint +/// `ptr` must be a reference to variable or struct field. +pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void { + asm volatile ( + \\OpDecorate %ptr BuiltIn FragDepth + : + : [ptr] "" (ptr), + ); +} + +/// Forms the main linkage for `input` and `output` address spaces. +/// `ptr` must be a reference to variable or struct field. +pub fn location(comptime ptr: anytype, comptime loc: u32) void { + const code = comptimePrint("OpDecorate %ptr Location {}", .{loc}); + asm volatile (code + : + : [ptr] "" (ptr), + ); +} + +/// Forms the main linkage for `input` and `output` address spaces. +/// `ptr` must be a reference to variable or struct field. +pub fn binding(comptime ptr: anytype, comptime group: u32, comptime bind: u32) void { + const code = comptimePrint( + \\OpDecorate %ptr DescriptorSet {} + \\OpDecorate %ptr Binding {} + , .{ group, bind }); + asm volatile (code + : + : [ptr] "" (ptr), + ); +} + +pub const Origin = enum(u32) { + /// Increase toward the right and downward + upper_left = 7, + /// Increase toward the right and upward + lower_left = 8, +}; + +/// The coordinates appear to originate in the specified `origin`. +/// Only valid with the `Fragment` calling convention. +pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void { + const origin_enum = switch (origin) { + .upper_left => .OriginUpperLeft, + .lower_left => .OriginLowerLeft, + }; + asm volatile ("OpExecutionMode %entry_point " ++ @tagName(origin_enum) + : + : [entry_point] "" (entry_point), + ); +} + +pub const DepthMode = enum(u32) { + /// Declares that this entry point dynamically writes the + /// `fragmentDepth` built in-decorated variable. + replacing = 12, + /// Indicates that per-fragment tests may assume that + /// any `fragmentDepth` built in-decorated value written by the shader is + /// greater-than-or-equal to the fragment’s interpolated depth value + greater = 14, + /// Indicates that per-fragment tests may assume that + /// any `fragmentDepth` built in-decorated value written by the shader is + /// less-than-or-equal to the fragment’s interpolated depth value + less = 15, + /// Indicates that per-fragment tests may assume that + /// any `fragmentDepth` built in-decorated value written by the shader is + /// the same as the fragment’s interpolated depth value + unchanged = 16, +}; + +/// Only valid with the `Fragment` calling convention. +pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void { + const code = comptimePrint("OpExecutionMode %entry_point {}", .{@intFromEnum(mode)}); + asm volatile (code + : + : [entry_point] "" (entry_point), + ); +} + +/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions. +/// Only valid with the `GLCompute` or `Kernel` calling conventions. +pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { + const code = comptimePrint("OpExecutionMode %entry_point LocalSize {} {} {}", .{ + size[0], + size[1], + size[2], + }); + asm volatile (code + : + : [entry_point] "" (entry_point), + ); +} + +/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions. +/// Only valid with the `GLCompute` or `Kernel` calling conventions. +pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { + const code = comptimePrint("OpExecutionMode %entry_point LocalSizeHint {} {} {}", .{ + size[0], + size[1], + size[2], + }); + asm volatile (code + : + : [entry_point] "" (entry_point), + ); +} + +/// Same as `kernelWorkgroupSize` but with runtime-known sizes +pub fn workgroupSizeId(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { + const code = comptimePrint("OpExecutionMode %entry_point LocalSize {} {} {}", .{ + size[0], + size[1], + size[2], + }); + asm volatile (code + : + : [entry_point] "" (entry_point), + ); +} + +/// Same as `kernelWorkgroupSizeHint` but with runtime-known sizes +pub fn workgroupSizeHintId(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { + const code = comptimePrint("OpExecutionMode %entry_point LocalSizeHint {} {} {}", .{ + size[0], + size[1], + size[2], + }); + asm volatile (code + : + : [entry_point] "" (entry_point), + ); +} diff --git a/lib/std/std.zig b/lib/std/std.zig index 66e30c4b4ee1..9f249c2a6227 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -104,6 +104,9 @@ pub const fmt = @import("fmt.zig"); /// File system-related functionality. pub const fs = @import("fs.zig"); +/// GPU programming helpers. +pub const gpu = @import("gpu.zig"); + /// Fast hashing functions (i.e. not cryptographically secure). pub const hash = @import("hash.zig"); pub const hash_map = @import("hash_map.zig");