zgpu

git clone git://git.electrosoup.com/zgpu
Log | Files | Refs | Submodules | README

commit 7b5344876542509f09488fb02e11c3513aee3164
parent 0632a496f0f5d313cfe07f3620c0dc81eec837f6
Author: Christian Ermann <christianermann@gmail.com>
Date:   Wed, 23 Apr 2025 18:49:42 -0700

Request and release Device

Diffstat:
Msrc/adapter.zig | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/device.zig | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.zig | 29+++++++++++++++++++++++++++++
3 files changed, 228 insertions(+), 0 deletions(-)

diff --git a/src/adapter.zig b/src/adapter.zig @@ -1,12 +1,73 @@ const std = @import("std"); const c = @import("c.zig").c; +const Device = @import("device.zig").Device; + +const RequestDeviceStatus = enum(u32) { + success = 0x00000000, + err = 0x00000001, + unknown = 0x00000002, +}; + +const RequestDeviceError = error{ + Error, + Unknown, +}; pub const Adapter = opaque { pub fn release(adapter: *Adapter) void { c.wgpuAdapterRelease(@ptrCast(adapter)); } + pub fn requestDevice( + adapter: *Adapter, + descriptor: *const Device.Descriptor, + ) !*Device { + const RequestDeviceResponse = struct { + status: RequestDeviceStatus, + device: ?*Device, + + pub fn callback( + status: RequestDeviceStatus, + device: ?*Device, + message: ?[*:0]const u8, + userdata: ?*anyopaque, + ) callconv(.C) void { + const self: *@This() = @alignCast(@ptrCast(userdata)); + switch (status) { + .success => {}, + else => { + std.log.err( + "failed to request device - {s}", + .{message.?}, + ); + }, + } + self.* = .{ + .status = status, + .device = device, + }; + } + }; + + var response: RequestDeviceResponse = undefined; + c.wgpuAdapterRequestDevice( + @ptrCast(adapter), + @ptrCast(descriptor), + @ptrCast(&RequestDeviceResponse.callback), + @ptrCast(&response), + ); + switch (response.status) { + .success => return response.device.?, + .err => { + return RequestDeviceError.Error; + }, + .unknown => { + return RequestDeviceError.Unknown; + }, + } + } + // enumerateFeatures(...) // getInfo(...) // getLimits(...) diff --git a/src/device.zig b/src/device.zig @@ -0,0 +1,138 @@ +const std = @import("std"); + +const c = @import("c.zig").c; +const ChainedStruct = @import("common.zig").ChainedStruct; + +pub const FeatureName = enum(u32) { + undefined = 0x00000000, + depth_clip_control = 0x00000001, + depth_32float_stencil_8 = 0x00000002, + timestamp_query = 0x00000003, + texture_compression_bc = 0x00000004, + texture_compression_etc2 = 0x00000005, + texture_compression_astc = 0x00000006, + indirect_first_instance = 0x00000007, + shader_f16 = 0x00000008, + rg11b10ufloat_renderable = 0x00000009, + bgra8unorm_storage = 0x0000000A, + float32_filterable = 0x0000000B, +}; + +pub const Limits = extern struct { + max_texture_dimension_1d: u32, + max_texture_dimension_2d: u32, + max_texture_dimension_3d: u32, + max_texture_array_layers: u32, + max_bind_groups: u32, + max_bind_groups_plus_vertex_buffers: u32, + max_bindings_per_bind_group: u32, + max_dynamic_uniform_buffers_per_pipeline_layout: u32, + max_dynamic_storage_buffers_per_pipeline_layout: u32, + max_sampled_textures_per_shader_stage: u32, + max_sampler_per_shader_stage: u32, + max_storage_buffers_per_shader_stage: u32, + max_storage_textures_per_shader_stage: u32, + max_uniform_buffers_per_shader_stage: u32, + max_uniform_buffer_binding_size: u64, + max_storage_buffer_binding_size: u64, + min_uniform_buffer_offset_alignment: u32, + min_storage_buffer_offset_alignmnet: u32, + max_vertex_buffers: u32, + max_buffer_size: u64, + max_vertex_attributes: u32, + max_vertex_buffer_array_stride: u32, + max_inter_stage_shader_components: u32, + max_inter_stage_shader_variables: u32, + max_color_attachments: u32, + max_color_attachment_bytes_per_sample: u32, + max_compute_workgroup_storage_size: u32, + max_compute_invocations_per_workgroup: u32, + max_compute_workgroup_size_x: u32, + max_compute_workgroup_size_y: u32, + max_compute_workgroup_size_z: u32, + max_compute_workgroups_per_dimension: u32, +}; + +pub const RequiredLimits = extern struct { + next: ?*const ChainedStruct = null, + limits: Limits, +}; + +pub const QueueDescriptor = extern struct { + next: ?*const ChainedStruct = null, + label: ?[*:0]const u8 = null, +}; + +pub const DeviceLostReason = enum(u32) { + unknown = 0x00000001, + destroyed = 0x00000002, +}; + +pub const DeviceLostCallback = fn ( + reason: DeviceLostReason, + message: ?[*:0]const u8, + userdata: ?*anyopaque, +) callconv(.C) void; + +pub const ErrorType = enum(u32) { + no_error = 0x00000000, + validation = 0x00000001, + out_of_memory = 0x00000002, + internal = 0x00000003, + unknown = 0x00000004, + device_lost = 0x00000005, +}; + +pub const ErrorCallback = fn ( + error_type: ErrorType, + message: ?[*:0]const u8, + userdata: ?*anyopaque, +) callconv(.C) void; + +pub const UncapturedErrorCallbackInfo = extern struct { + next: ?*const ChainedStruct = null, + callback: ?*const ErrorCallback, + userdata: ?*anyopaque, +}; + +pub const Device = opaque { + pub const Descriptor = extern struct { + next: ?*const ChainedStruct = null, + label: ?[*:0]const u8 = null, + required_feature_count: c_int, + required_features: ?[*]const FeatureName, + required_limits: ?*const RequiredLimits, + default_queue: QueueDescriptor, + device_lost_callback: ?*const DeviceLostCallback, + device_lost_userdata: ?*anyopaque, + uncaptured_error_callback_info: UncapturedErrorCallbackInfo, + }; + + pub fn release(device: *Device) void { + c.wgpuDeviceRelease(@ptrCast(device)); + } + + // createBindGroup + // createBindGroupLayout + // createBuffer + // createCommandEncoder + // createComputePipeline + // createComputePipelineAsync + // createPipelineLayout + // createQuerySet + // createRenderBundleEncoder + // createRenderPipeline + // createRenderPipelineAsync + // createSampler + // createShaderModule + // createTexture + // destroy + // enumerateFeatures + // getLimits + // getQueue + // hasFeature + // popErrorScope + // pushErrorScope + // setLabel + // reference +}; diff --git a/src/main.zig b/src/main.zig @@ -3,6 +3,7 @@ const std = @import("std"); const glfw = @import("glfw.zig"); const Instance = @import("instance.zig").Instance; const Logging = @import("logging.zig"); +const Device = @import("device.zig"); const Callback = @import("callback.zig").Callback; pub fn zgpu_log_callback(level: Logging.LogLevel, message: []const u8) void { @@ -23,6 +24,20 @@ pub fn zgpu_log_callback(level: Logging.LogLevel, message: []const u8) void { } } +fn zgpu_error_callback( + error_type: Device.ErrorType, + message: []const u8, +) void { + std.log.err("[wgpu - {}] {s}", .{ error_type, message }); +} + +fn zgpu_device_lost_callback( + reason: Device.DeviceLostReason, + message: []const u8, +) void { + std.log.err("[wgpu - {}] {s}", .{ reason, message }); +} + pub fn main() !void { try glfw.init(); defer glfw.terminate(); @@ -73,4 +88,18 @@ pub fn main() !void { .force_fallback_adapter = false, }); defer adapter.release(); + + const device = try adapter.requestDevice(&.{ + .required_feature_count = 0, + .required_features = null, + .required_limits = null, + .default_queue = .{}, + .device_lost_callback = Callback(zgpu_device_lost_callback), + .device_lost_userdata = null, + .uncaptured_error_callback_info = .{ + .callback = Callback(zgpu_error_callback), + .userdata = null, + }, + }); + defer device.release(); }