Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub fn build(b: *std.Build) void {

const zdawn = b.addLibrary(.{
.name = "zdawn",
.use_llvm = true,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
Expand Down Expand Up @@ -143,6 +144,7 @@ pub fn build(b: *std.Build) void {

const tests = b.addTest(.{
.name = "zgpu-tests",
.use_llvm = true,
.root_module = b.createModule(.{
.root_source_file = b.path("src/zgpu.zig"),
.target = target,
Expand Down
2 changes: 1 addition & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.name = .zgpu,
.fingerprint = 0x670ebe04e453a19e,
.version = "0.12.0-dev",
.minimum_zig_version = "0.14.0",
.minimum_zig_version = "0.15.1",
.paths = .{
"build.zig",
"build.zig.zon",
Expand Down
24 changes: 12 additions & 12 deletions src/wgpu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1273,62 +1273,62 @@ pub const CreateComputePipelineAsyncCallback = *const fn (
pipeline: ComputePipeline,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const CreateRenderPipelineAsyncCallback = *const fn (
status: CreatePipelineAsyncStatus,
pipeline: RenderPipeline,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const ErrorCallback = *const fn (
err_type: ErrorType,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const LoggingCallback = *const fn (
log_type: LoggingType,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const DeviceLostCallback = *const fn (
reason: DeviceLostReason,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const RequestAdapterCallback = *const fn (
status: RequestAdapterStatus,
adapter: Adapter,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const RequestDeviceCallback = *const fn (
status: RequestDeviceStatus,
device: Device,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const BufferMapCallback = *const fn (
status: BufferMapAsyncStatus,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const QueueWorkDoneCallback = *const fn (
status: QueueWorkDoneStatus,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const CompilationInfoCallback = *const fn (
status: CompilationInfoRequestStatus,
info: *const CompilationInfo,
userdata: ?*anyopaque,
) callconv(.C) void;
) callconv(.c) void;

pub const Adapter = *opaque {
pub fn createDevice(adapter: Adapter, descriptor: DeviceDescriptor) Device {
Expand Down Expand Up @@ -2238,7 +2238,7 @@ pub const Queue = *opaque {
queue: Queue,
callback: QueueWorkDoneCallback,
userdata: ?*anyopaque,
) callconv(.C) void,
) callconv(.c) void,
.{ .name = "wgpuQueueOnSubmittedWorkDone" },
);
oswd(queue, callback, userdata);
Expand All @@ -2249,7 +2249,7 @@ pub const Queue = *opaque {
signal_value: u64,
callback: QueueWorkDoneCallback,
userdata: ?*anyopaque,
) callconv(.C) void,
) callconv(.c) void,
.{ .name = "wgpuQueueOnSubmittedWorkDone" },
);
oswd(queue, signal_value, callback, userdata);
Expand Down
45 changes: 24 additions & 21 deletions src/zgpu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub const GraphicsContext = struct {
adapter: wgpu.Adapter,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void {
) callconv(.c) void {
_ = message;
const response = @as(*Response, @ptrCast(@alignCast(userdata)));
response.status = status;
Expand Down Expand Up @@ -197,7 +197,7 @@ pub const GraphicsContext = struct {
device: wgpu.Device,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void {
) callconv(.c) void {
_ = message;
const response = @as(*Response, @ptrCast(@alignCast(userdata)));
response.status = status;
Expand Down Expand Up @@ -374,7 +374,7 @@ pub const GraphicsContext = struct {
gctx.uniformsNextStagingBuffer();
}

fn uniformsMappedCallback(status: wgpu.BufferMapAsyncStatus, userdata: ?*anyopaque) callconv(.C) void {
fn uniformsMappedCallback(status: wgpu.BufferMapAsyncStatus, userdata: ?*anyopaque) callconv(.c) void {
const usb = @as(*UniformsStagingBuffer, @ptrCast(@alignCast(userdata)));
assert(usb.slice == null);
if (status == .success) {
Expand Down Expand Up @@ -471,19 +471,22 @@ pub const GraphicsContext = struct {
defer stage_commands.release();

// TODO: We support up to 32 command buffers for now. Make it more robust.
var command_buffers = std.BoundedArray(wgpu.CommandBuffer, 32).init(0) catch unreachable;
command_buffers.append(stage_commands) catch unreachable;
command_buffers.appendSlice(commands) catch unreachable;
var buffer: [32]wgpu.CommandBuffer = undefined;
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The buffer is left uninitialized (undefined). While this works with FixedBufferAllocator, it's better practice to initialize it with .{} for clarity and to avoid potential issues with future Zig versions that may have stricter safety checks.

Suggested change
var buffer: [32]wgpu.CommandBuffer = undefined;
var buffer: [32]wgpu.CommandBuffer = .{};

Copilot uses AI. Check for mistakes.
var fb_allocator = std.heap.FixedBufferAllocator.init(@ptrCast(&buffer));

var command_buffers = std.ArrayList(wgpu.CommandBuffer).initCapacity(fb_allocator.allocator(), 32) catch unreachable;
command_buffers.append(fb_allocator.allocator(), stage_commands) catch unreachable;
command_buffers.appendSlice(fb_allocator.allocator(), commands) catch unreachable;

gctx.queue.onSubmittedWorkDone(0, gpuWorkDone, @ptrCast(&gctx.stats.gpu_frame_number));
gctx.queue.submit(command_buffers.slice());
gctx.queue.submit(command_buffers.items);

gctx.stats.tick(gctx.window_provider.getTime());

gctx.uniformsNextStagingBuffer();
}

fn gpuWorkDone(status: wgpu.QueueWorkDoneStatus, userdata: ?*anyopaque) callconv(.C) void {
fn gpuWorkDone(status: wgpu.QueueWorkDoneStatus, userdata: ?*anyopaque) callconv(.c) void {
const gpu_frame_number: *u64 = @ptrCast(@alignCast(userdata));
gpu_frame_number.* += 1;
if (status != .success) {
Expand Down Expand Up @@ -632,7 +635,7 @@ pub const GraphicsContext = struct {
pipeline: wgpu.RenderPipeline,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void {
) callconv(.c) void {
const op = @as(*AsyncCreateOpRender, @ptrCast(@alignCast(userdata)));
if (status == .success) {
op.result.* = op.gctx.render_pipeline_pool.addResource(
Expand Down Expand Up @@ -693,7 +696,7 @@ pub const GraphicsContext = struct {
pipeline: wgpu.ComputePipeline,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void {
) callconv(.c) void {
const op = @as(*AsyncCreateOpCompute, @ptrCast(@alignCast(userdata)));
if (status == .success) {
op.result.* = op.gctx.compute_pipeline_pool.addResource(
Expand Down Expand Up @@ -1762,29 +1765,29 @@ fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime ReturnT
const args_meta = @typeInfo(@TypeOf(args)).@"struct".fields;

const FnType = switch (args_meta.len) {
0 => *const fn (@TypeOf(obj), objc.SEL) callconv(.C) ReturnType,
1 => *const fn (@TypeOf(obj), objc.SEL, args_meta[0].type) callconv(.C) ReturnType,
0 => *const fn (@TypeOf(obj), objc.SEL) callconv(.c) ReturnType,
1 => *const fn (@TypeOf(obj), objc.SEL, args_meta[0].type) callconv(.c) ReturnType,
2 => *const fn (
@TypeOf(obj),
objc.SEL,
args_meta[0].type,
args_meta[1].type,
) callconv(.C) ReturnType,
) callconv(.c) ReturnType,
3 => *const fn (
@TypeOf(obj),
objc.SEL,
args_meta[0].type,
args_meta[1].type,
args_meta[2].type,
) callconv(.C) ReturnType,
) callconv(.c) ReturnType,
4 => *const fn (
@TypeOf(obj),
objc.SEL,
args_meta[0].type,
args_meta[1].type,
args_meta[2].type,
args_meta[3].type,
) callconv(.C) ReturnType,
) callconv(.c) ReturnType,
else => @compileError("[zgpu] Unsupported number of args"),
};

Expand All @@ -1798,7 +1801,7 @@ fn logUnhandledError(
err_type: wgpu.ErrorType,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void {
) callconv(.c) void {
_ = userdata;
switch (err_type) {
.no_error => std.log.info("[zgpu] No error: {?s}", .{message}),
Expand Down Expand Up @@ -1855,14 +1858,14 @@ fn formatToShaderFormat(format: wgpu.TextureFormat) []const u8 {
};
}

usingnamespace if (emscripten) struct {
// Missing symbols
var wgpuDeviceTickWarnPrinted: bool = false;
pub export fn wgpuDeviceTick() void {
var wgpuDeviceTickWarnPrinted: bool = false;

pub fn wgpuDeviceTick() void {
if (emscripten) {
if (!wgpuDeviceTickWarnPrinted) {
std.log.warn("wgpuDeviceTick(): this fn should be avoided! RequestAnimationFrame() is advised for smooth rendering in browser.", .{});
wgpuDeviceTickWarnPrinted = true;
}
emscripten_sleep(1);
}
} else struct {};
}
Loading