commit 7b5344876542509f09488fb02e11c3513aee3164
parent 0632a496f0f5d313cfe07f3620c0dc81eec837f6
Author: Christian Ermann <christianermann@gmail.com>
Date: Wed, 23 Apr 2025 18:49:42 -0700
Request and release Device
Diffstat:
| M | src/adapter.zig | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/device.zig | | | 138 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | src/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();
}