From a52c6e5f5c92ae0f83f919dd6fd088db0dce34db Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Fri, 13 Jan 2023 22:30:26 +0330 Subject: [PATCH] gpu: update interface to latest webgpu headers --- libs/gpu/build.zig | 2 -- libs/gpu/sdk.zig | 3 --- libs/gpu/src/buffer.zig | 10 ++++++++ libs/gpu/src/dawn.zig | 18 ++++++++++++++ libs/gpu/src/dawn_impl.zig | 41 ++++++++++++++++++++++++++----- libs/gpu/src/device.zig | 21 +++++++++++----- libs/gpu/src/external_texture.zig | 13 ++++++++++ libs/gpu/src/interface.zig | 17 +++++-------- libs/gpu/src/queue.zig | 5 ++++ libs/gpu/src/types.zig | 34 +++++++++++++++++++++++-- src/platform/native/Core.zig | 2 +- 11 files changed, 135 insertions(+), 31 deletions(-) diff --git a/libs/gpu/build.zig b/libs/gpu/build.zig index 41034166..268cded2 100644 --- a/libs/gpu/build.zig +++ b/libs/gpu/build.zig @@ -8,12 +8,10 @@ pub fn build(b: *std.build.Builder) !void { const mode = b.standardReleaseOptions(); const target = b.standardTargetOptions(.{}); const gpu_dawn = gpu_dawn_sdk.Sdk(.{ - .glfw = glfw, .glfw_include_dir = "libs/mach-glfw/upstream/glfw/include", .system_sdk = system_sdk, }); const gpu = gpu_sdk.Sdk(.{ - .glfw = glfw, .gpu_dawn = gpu_dawn, }); diff --git a/libs/gpu/sdk.zig b/libs/gpu/sdk.zig index 8dece138..5b638b5a 100644 --- a/libs/gpu/sdk.zig +++ b/libs/gpu/sdk.zig @@ -12,19 +12,16 @@ pub fn Sdk(comptime deps: anytype) type { } pub const Options = struct { - glfw_options: deps.glfw.Options = .{}, gpu_dawn_options: deps.gpu_dawn.Options = .{}, }; pub const pkg = std.build.Pkg{ .name = "gpu", .source = .{ .path = sdkPath("/src/main.zig") }, - .dependencies = &.{deps.glfw.pkg}, }; pub fn link(b: *std.build.Builder, step: *std.build.LibExeObjStep, options: Options) !void { if (step.target.toTarget().cpu.arch != .wasm32) { - try deps.glfw.link(b, step, options.glfw_options); try deps.gpu_dawn.link(b, step, options.gpu_dawn_options); step.addCSourceFile(sdkPath("/src/mach_dawn.cpp"), &.{"-std=c++17"}); step.addIncludePath(sdkPath("/src")); diff --git a/libs/gpu/src/buffer.zig b/libs/gpu/src/buffer.zig index 511975e1..0f5de96a 100644 --- a/libs/gpu/src/buffer.zig +++ b/libs/gpu/src/buffer.zig @@ -13,6 +13,12 @@ pub const Buffer = opaque { read_only_storage = 0x00000003, }; + pub const MapState = enum(u32) { + unmapped = 0x00000000, + pending = 0x00000001, + mapped = 0x00000002, + }; + pub const MapAsyncStatus = enum(u32) { success = 0x00000000, err = 0x00000001, @@ -69,6 +75,10 @@ pub const Buffer = opaque { Impl.bufferDestroy(buffer); } + pub inline fn getMapState(buffer: *Buffer) MapState { + return Impl.bufferGetMapState(buffer); + } + /// Default `offset_bytes`: 0 /// Default `len`: `gpu.whole_map_size` / `std.math.maxint(usize)` (whole range) pub inline fn getConstMappedRange( diff --git a/libs/gpu/src/dawn.zig b/libs/gpu/src/dawn.zig index f90bdca9..3f364d3b 100644 --- a/libs/gpu/src/dawn.zig +++ b/libs/gpu/src/dawn.zig @@ -1,4 +1,6 @@ const ChainedStruct = @import("types.zig").ChainedStruct; +const ChainedStructOut = @import("types.zig").ChainedStructOut; +const PowerPreference = @import("types.zig").PowerPreference; const Texture = @import("texture.zig").Texture; pub const Interface = @import("dawn_impl.zig").Interface; @@ -57,3 +59,19 @@ pub const TogglesDeviceDescriptor = extern struct { }; } }; + +const AdapterPropertiesPowerPreference = extern struct { + chain: ChainedStructOut = .{ + .next = null, + .s_type = .dawn_adapter_properties_power_preference, + }, + power_preference: PowerPreference = .undefined, +}; + +const BufferDescriptorErrorInfoFromWireClient = extern struct { + chain: ChainedStruct = .{ + .next = null, + .s_type = .dawn_buffer_descriptor_error_info_from_wire_client, + }, + out_of_memory: bool = false, +}; diff --git a/libs/gpu/src/dawn_impl.zig b/libs/gpu/src/dawn_impl.zig index 175c844e..82c69688 100644 --- a/libs/gpu/src/dawn_impl.zig +++ b/libs/gpu/src/dawn_impl.zig @@ -108,6 +108,10 @@ pub const Interface = struct { procs.bufferDestroy.?(@ptrCast(c.WGPUBuffer, buffer)); } + pub inline fn bufferGetMapState(buffer: *gpu.Buffer) gpu.Buffer.MapState { + return procs.bufferGetMapState.?(@ptrCast(c.WGPUBuffer, buffer)); + } + // TODO: dawn: return value not marked as nullable in dawn.json but in fact is. pub inline fn bufferGetConstMappedRange(buffer: *gpu.Buffer, offset: usize, size: usize) ?*const anyopaque { return procs.bufferGetConstMappedRange.?( @@ -455,8 +459,11 @@ pub const Interface = struct { ); } - pub inline fn deviceCreateErrorBuffer(device: *gpu.Device) *gpu.Buffer { - return @ptrCast(*gpu.Buffer, procs.deviceCreateErrorBuffer.?(@ptrCast(c.WGPUDevice, device))); + pub inline fn deviceCreateErrorBuffer(device: *gpu.Device, descriptor: *const gpu.Buffer.Descriptor) *gpu.Buffer { + return @ptrCast(*gpu.Buffer, procs.deviceCreateErrorBuffer.?( + @ptrCast(c.WGPUDevice, device), + @ptrCast(*const c.WGPUBufferDescriptor, descriptor), + )); } pub inline fn deviceCreateErrorExternalTexture(device: *gpu.Device) *gpu.ExternalTexture { @@ -556,6 +563,18 @@ pub const Interface = struct { ); } + pub inline fn forceLoss(device: *gpu.Device, reason: gpu.Device.LostReason, message: [*:0]const u8) void { + return procs.deviceForceLoss.?( + @ptrCast(c.WGPUDevice, device), + reason, + message, + ); + } + + pub inline fn deviceGetAdapter(device: *gpu.Device) *gpu.Adapter { + return procs.deviceGetAdapter.?(@ptrCast(c.WGPUDevice, device)); + } + pub inline fn deviceGetLimits(device: *gpu.Device, limits: *gpu.SupportedLimits) bool { return procs.deviceGetLimits.?( @ptrCast(c.WGPUDevice, device), @@ -582,10 +601,6 @@ pub const Interface = struct { ); } - pub inline fn deviceLoseForTesting(device: *gpu.Device) void { - procs.deviceLoseForTesting.?(@ptrCast(c.WGPUDevice, device)); - } - pub inline fn devicePopErrorScope(device: *gpu.Device, callback: gpu.ErrorCallback, userdata: ?*anyopaque) bool { return procs.devicePopErrorScope.?( @ptrCast(c.WGPUDevice, device), @@ -633,6 +648,10 @@ pub const Interface = struct { procs.deviceTick.?(@ptrCast(c.WGPUDevice, device)); } + pub inline fn deviceValidateTextureDescriptor(device: *gpu.Device, descriptor: *const gpu.Texture.Descriptor) void { + procs.deviceValidateTextureDescriptor(device, descriptor); + } + pub inline fn deviceReference(device: *gpu.Device) void { procs.deviceReference.?(@ptrCast(c.WGPUDevice, device)); } @@ -717,6 +736,16 @@ pub const Interface = struct { procs.querySetRelease.?(@ptrCast(c.WGPUQuerySet, query_set)); } + pub inline fn queueCopyExternalTextureForBrowser(queue: *gpu.Queue, source: *const gpu.ImageCopyExternalTexture, destination: *const gpu.ImageCopyTexture, copy_size: *const gpu.Extent3D, options: *const gpu.CopyTextureForBrowserOptions) void { + procs.queueCopyExternalTextureForBrowser.?( + @ptrCast(c.WGPUQueue, queue), + @ptrCast(*const c.ImageCopyExternalTexture, source), + @ptrCast(*const c.WGPUImageCopyTexture, destination), + @ptrCast(*const c.WGPUExtent3D, copy_size), + @ptrCast(*const c.WGPUCopyTextureForBrowserOptions, options), + ); + } + pub inline fn queueCopyTextureForBrowser(queue: *gpu.Queue, source: *const gpu.ImageCopyTexture, destination: *const gpu.ImageCopyTexture, copy_size: *const gpu.Extent3D, options: *const gpu.CopyTextureForBrowserOptions) void { procs.queueCopyTextureForBrowser.?( @ptrCast(c.WGPUQueue, queue), diff --git a/libs/gpu/src/device.zig b/libs/gpu/src/device.zig index 5d4f7bd9..0a2b2b48 100644 --- a/libs/gpu/src/device.zig +++ b/libs/gpu/src/device.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Adapter = @import("adapter.zig").Adapter; const Queue = @import("queue.zig").Queue; const BindGroup = @import("bind_group.zig").BindGroup; const BindGroupLayout = @import("bind_group_layout.zig").BindGroupLayout; @@ -124,8 +125,8 @@ pub const Device = opaque { Impl.deviceCreateComputePipelineAsync(device, descriptor, Helper.cCallback, if (Context == void) null else context); } - pub inline fn createErrorBuffer(device: *Device) *Buffer { - return Impl.deviceCreateErrorBuffer(device); + pub inline fn createErrorBuffer(device: *Device, descriptor: *const Buffer.Descriptor) *Buffer { + return Impl.deviceCreateErrorBuffer(device, descriptor); } pub inline fn createErrorExternalTexture(device: *Device) *ExternalTexture { @@ -236,6 +237,14 @@ pub const Device = opaque { return data; } + pub inline fn forceLoss(device: *Device, reason: LostReason, message: [*:0]const u8) void { + return Impl.deviceForceLoss(device, reason, message); + } + + pub inline fn getAdapter(device: *Device) *Adapter { + return Impl.deviceGetAdapter(device); + } + pub inline fn getLimits(device: *Device, limits: *SupportedLimits) bool { return Impl.deviceGetLimits(device, limits); } @@ -252,10 +261,6 @@ pub const Device = opaque { Impl.deviceInjectError(device, typ, message); } - pub inline fn loseForTesting(device: *Device) void { - Impl.deviceLoseForTesting(device); - } - pub inline fn popErrorScope( device: *Device, context: anytype, @@ -336,6 +341,10 @@ pub const Device = opaque { Impl.deviceTick(device); } + pub inline fn validateTextureDescriptor(device: *Device, descriptor: *const Texture.Descriptor) void { + Impl.deviceVlidateTextureDescriptor(device, descriptor); + } + pub inline fn reference(device: *Device) void { Impl.deviceReference(device); } diff --git a/libs/gpu/src/external_texture.zig b/libs/gpu/src/external_texture.zig index 2c6880b4..270e21d2 100644 --- a/libs/gpu/src/external_texture.zig +++ b/libs/gpu/src/external_texture.zig @@ -1,5 +1,7 @@ const ChainedStruct = @import("types.zig").ChainedStruct; const TextureView = @import("texture_view.zig").TextureView; +const Origin2D = @import("types.zig").Origin2D; +const Extent2D = @import("types.zig").Extent2D; const Impl = @import("interface.zig").Impl; pub const ExternalTexture = opaque { @@ -12,16 +14,27 @@ pub const ExternalTexture = opaque { chain: ChainedStruct = .{ .next = null, .s_type = .external_texture_binding_layout }, }; + const Rotation = enum(u32) { + rotate_0_degrees = 0x00000000, + rotate_90_degrees = 0x00000001, + rotate_180_degrees = 0x00000002, + rotate_270_degrees = 0x00000003, + }; + pub const Descriptor = extern struct { next_in_chain: ?*const ChainedStruct = null, label: ?[*:0]const u8 = null, plane0: *TextureView, plane1: ?*TextureView = null, + visible_origin: Origin2D, + visible_size: Extent2D, do_yuv_to_rgb_conversion_only: bool = false, yuv_to_rgb_conversion_matrix: ?*const [12]f32 = null, src_transform_function_parameters: *const [7]f32, dst_transform_function_parameters: *const [7]f32, gamut_conversion_matrix: *const [9]f32, + flip_y: bool, + rotation: Rotation, }; pub inline fn destroy(external_texture: *ExternalTexture) void { diff --git a/libs/gpu/src/interface.zig b/libs/gpu/src/interface.zig index 3b34269d..c0e4e7ae 100644 --- a/libs/gpu/src/interface.zig +++ b/libs/gpu/src/interface.zig @@ -87,7 +87,7 @@ pub fn Interface(comptime T: type) type { assertDecl(T, "deviceCreateCommandEncoder", fn (device: *gpu.Device, descriptor: ?*const gpu.CommandEncoder.Descriptor) callconv(.Inline) *gpu.CommandEncoder); assertDecl(T, "deviceCreateComputePipeline", fn (device: *gpu.Device, descriptor: *const gpu.ComputePipeline.Descriptor) callconv(.Inline) *gpu.ComputePipeline); assertDecl(T, "deviceCreateComputePipelineAsync", fn (device: *gpu.Device, descriptor: *const gpu.ComputePipeline.Descriptor, callback: gpu.CreateComputePipelineAsyncCallback, userdata: ?*anyopaque) callconv(.Inline) void); - assertDecl(T, "deviceCreateErrorBuffer", fn (device: *gpu.Device) callconv(.Inline) *gpu.Buffer); + assertDecl(T, "deviceCreateErrorBuffer", fn (device: *gpu.Device, descriptor: *const gpu.Buffer.Descriptor) callconv(.Inline) *gpu.Buffer); assertDecl(T, "deviceCreateErrorExternalTexture", fn (device: *gpu.Device) callconv(.Inline) *gpu.ExternalTexture); assertDecl(T, "deviceCreateErrorTexture", fn (device: *gpu.Device, descriptor: *const gpu.Texture.Descriptor) callconv(.Inline) *gpu.Texture); assertDecl(T, "deviceCreateExternalTexture", fn (device: *gpu.Device, external_texture_descriptor: *const gpu.ExternalTexture.Descriptor) callconv(.Inline) *gpu.ExternalTexture); @@ -108,7 +108,6 @@ pub fn Interface(comptime T: type) type { assertDecl(T, "deviceGetQueue", fn (device: *gpu.Device) callconv(.Inline) *gpu.Queue); assertDecl(T, "deviceHasFeature", fn (device: *gpu.Device, feature: gpu.FeatureName) callconv(.Inline) bool); assertDecl(T, "deviceInjectError", fn (device: *gpu.Device, typ: gpu.ErrorType, message: [*:0]const u8) callconv(.Inline) void); - assertDecl(T, "deviceLoseForTesting", fn (device: *gpu.Device) callconv(.Inline) void); assertDecl(T, "devicePopErrorScope", fn (device: *gpu.Device, callback: gpu.ErrorCallback, userdata: ?*anyopaque) callconv(.Inline) bool); assertDecl(T, "devicePushErrorScope", fn (device: *gpu.Device, filter: gpu.ErrorFilter) callconv(.Inline) void); assertDecl(T, "deviceSetDeviceLostCallback", fn (device: *gpu.Device, callback: ?gpu.Device.LostCallback, userdata: ?*anyopaque) callconv(.Inline) void); @@ -580,9 +579,9 @@ pub fn Export(comptime T: type) type { T.deviceCreateComputePipelineAsync(device, descriptor, callback, userdata); } - // WGPU_EXPORT WGPUBuffer wgpuDeviceCreateErrorBuffer(WGPUDevice device); - export fn wgpuDeviceCreateErrorBuffer(device: *gpu.Device) *gpu.Buffer { - return T.deviceCreateErrorBuffer(device); + // WGPU_EXPORT WGPUBuffer wgpuDeviceCreateErrorBuffer(WGPUDevice device, WGPUBufferDescriptor const * descriptor); + export fn wgpuDeviceCreateErrorBuffer(device: *gpu.Device, descriptor: *const gpu.Buffer.Descriptor) *gpu.Buffer { + return T.deviceCreateErrorBuffer(device, descriptor); } // WGPU_EXPORT WGPUExternalTexture wgpuDeviceCreateErrorExternalTexture(WGPUDevice device); @@ -675,11 +674,6 @@ pub fn Export(comptime T: type) type { T.deviceInjectError(device, typ, message); } - // WGPU_EXPORT void wgpuDeviceLoseForTesting(WGPUDevice device); - export fn wgpuDeviceLoseForTesting(device: *gpu.Device) void { - T.deviceLoseForTesting(device); - } - // WGPU_EXPORT bool wgpuDevicePopErrorScope(WGPUDevice device, WGPUErrorCallback callback, void * userdata); export fn wgpuDevicePopErrorScope(device: *gpu.Device, callback: gpu.ErrorCallback, userdata: ?*anyopaque) bool { return T.devicePopErrorScope(device, callback, userdata); @@ -1664,8 +1658,9 @@ pub const StubInterface = Interface(struct { unreachable; } - pub inline fn deviceCreateErrorBuffer(device: *gpu.Device) *gpu.Buffer { + pub inline fn deviceCreateErrorBuffer(device: *gpu.Device, descriptor: *const gpu.Buffer.Descriptor) *gpu.Buffer { _ = device; + _ = descriptor; unreachable; } diff --git a/libs/gpu/src/queue.zig b/libs/gpu/src/queue.zig index 28a05df0..7c9981fd 100644 --- a/libs/gpu/src/queue.zig +++ b/libs/gpu/src/queue.zig @@ -3,6 +3,7 @@ const CommandBuffer = @import("command_buffer.zig").CommandBuffer; const Buffer = @import("buffer.zig").Buffer; const Texture = @import("texture.zig").Texture; const ImageCopyTexture = @import("types.zig").ImageCopyTexture; +const ImageCopyExternalTexture = @import("types.zig").ImageCopyExternalTexture; const ChainedStruct = @import("types.zig").ChainedStruct; const Extent3D = @import("types.zig").Extent3D; const CopyTextureForBrowserOptions = @import("types.zig").CopyTextureForBrowserOptions; @@ -26,6 +27,10 @@ pub const Queue = opaque { label: ?[*:0]const u8 = null, }; + pub inline fn copyExternalTextureForBrowser(queue: *Queue, source: *const ImageCopyExternalTexture, destination: *const ImageCopyTexture, copy_size: *const Extent3D, options: *const CopyTextureForBrowserOptions) void { + Impl.queueCopyExternalTextureForBrowser(queue, source, destination, copy_size, options); + } + pub inline fn copyTextureForBrowser(queue: *Queue, source: *const ImageCopyTexture, destination: *const ImageCopyTexture, copy_size: *const Extent3D, options: *const CopyTextureForBrowserOptions) void { Impl.queueCopyTextureForBrowser(queue, source, destination, copy_size, options); } diff --git a/libs/gpu/src/types.zig b/libs/gpu/src/types.zig index 3fd3090f..a70ca249 100644 --- a/libs/gpu/src/types.zig +++ b/libs/gpu/src/types.zig @@ -1,6 +1,7 @@ const std = @import("std"); const testing = std.testing; const Texture = @import("texture.zig").Texture; +const ExternalTexture = @import("external_texture.zig").ExternalTexture; const TextureView = @import("texture_view.zig").TextureView; const Buffer = @import("buffer.zig").Buffer; const ShaderModule = @import("shader_module.zig").ShaderModule; @@ -209,14 +210,16 @@ pub const CullMode = enum(u32) { pub const ErrorFilter = enum(u32) { validation = 0x00000000, out_of_memory = 0x00000001, + internal = 0x00000002, }; pub const ErrorType = enum(u32) { no_error = 0x00000000, validation = 0x00000001, out_of_memory = 0x00000002, - unknown = 0x00000003, - device_lost = 0x00000004, + internal = 0x00000003, + unknown = 0x00000004, + device_lost = 0x00000005, }; pub const FeatureName = enum(u32) { @@ -229,11 +232,14 @@ pub const FeatureName = enum(u32) { texture_compression_etc2 = 0x00000006, texture_compression_astc = 0x00000007, indirect_first_instance = 0x00000008, + shader_f16 = 0x00000009, + rg11_b10_ufloat_renderable = 0x0000000A, dawn_shader_float16 = 0x000003e9, dawn_internal_usages = 0x000003ea, dawn_multi_planar_formats = 0x000003eb, dawn_native = 0x000003ec, chromium_experimental_dp4a = 0x000003ed, + timestamp_query_inside_passes = 0x000003EE, }; pub const FilterMode = enum(u32) { @@ -338,6 +344,8 @@ pub const SType = enum(u32) { dawn_encoder_internal_usage_descriptor = 0x000003EB, dawn_instance_descriptor = 0x000003EC, dawn_cache_device_descriptor = 0x000003ED, + dawn_adapter_properties_power_preference = 0x000003EE, + dawn_buffer_descriptor_error_info_from_wire_client = 0x000003EF, }; pub const StencilOperation = enum(u32) { @@ -495,6 +503,11 @@ pub const Color = extern struct { a: f64, }; +pub const Extent2D = extern struct { + width: u32, + height: u32 = 1, +}; + pub const Extent3D = extern struct { width: u32, height: u32 = 1, @@ -507,6 +520,7 @@ pub const Limits = extern struct { max_texture_dimension_3d: u32 = limit_u32_undef, max_texture_array_layers: u32 = limit_u32_undef, max_bind_groups: u32 = limit_u32_undef, + max_bindings_per_bind_group: u32 = limit_u32_undef, max_dynamic_uniform_buffers_per_pipeline_layout: u32 = limit_u32_undef, max_dynamic_storage_buffers_per_pipeline_layout: u32 = limit_u32_undef, max_sampled_textures_per_shader_stage: u32 = limit_u32_undef, @@ -519,11 +533,13 @@ pub const Limits = extern struct { min_uniform_buffer_offset_alignment: u32 = limit_u32_undef, min_storage_buffer_offset_alignment: u32 = limit_u32_undef, max_vertex_buffers: u32 = limit_u32_undef, + max_buffer_size: u32 = limit_u32_undef, max_vertex_attributes: u32 = limit_u32_undef, max_vertex_buffer_array_stride: u32 = limit_u32_undef, max_inter_stage_shader_components: u32 = limit_u32_undef, max_inter_stage_shader_variables: u32 = limit_u32_undef, max_color_attachments: u32 = limit_u32_undef, + max_color_attachment_bytes_per_sample: u32 = limit_u32_undef, max_compute_workgroup_storage_size: u32 = limit_u32_undef, max_compute_invocations_per_workgroup: u32 = limit_u32_undef, max_compute_workgroup_size_x: u32 = limit_u32_undef, @@ -532,6 +548,11 @@ pub const Limits = extern struct { max_compute_workgroups_per_dimension: u32 = limit_u32_undef, }; +pub const Origin2D = extern struct { + x: u32 = 0, + y: u32 = 0, +}; + pub const Origin3D = extern struct { x: u32 = 0, y: u32 = 0, @@ -546,6 +567,9 @@ pub const CompilationMessage = extern struct { line_pos: u64, offset: u64, length: u64, + utf16_line_pos: u64, + utf16_offset: u64, + utf16_length: u64, }; pub const ConstantEntry = extern struct { @@ -655,6 +679,12 @@ pub const ImageCopyBuffer = extern struct { buffer: *Buffer, }; +pub const ImageCopyExternalTexture = extern struct { + next_in_chain: ?*const ChainedStruct = null, + external_texture: *ExternalTexture, + origin: Origin3D, +}; + pub const ImageCopyTexture = extern struct { next_in_chain: ?*const ChainedStruct = null, texture: *Texture, diff --git a/src/platform/native/Core.zig b/src/platform/native/Core.zig index 0f4fa02b..ed988305 100644 --- a/src/platform/native/Core.zig +++ b/src/platform/native/Core.zig @@ -116,7 +116,7 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !*Core { } // Print which adapter we are going to use. - var props: gpu.Adapter.Properties = undefined; + var props = std.mem.zeroes(gpu.Adapter.Properties); response.adapter.getProperties(&props); if (props.backend_type == .null) { std.log.err("no backend found for {s} adapter", .{props.adapter_type.name()});