From d9a57859c640a5698385c0774b6656fbd963c22d Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 8 Dec 2021 23:48:49 +0100 Subject: [PATCH] Add non-failing dispatch load function --- README.md | 8 +++++--- generator/vulkan/render.zig | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 34c08a1..1196262 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,11 @@ Wrappers are generated according to the following rules: * As of yet, there is no specific handling of enumeration style commands or other commands which accept slices. Furthermore, each wrapper contains a function to load each function pointer member when passed either `PfnGetInstanceProcAddr` or `PfnGetDeviceProcAddr`, which attempts to load each member as function pointer and casts it to the appropriate type. These functions are loaded literally, and any wrongly named member or member with a wrong function pointer type will result in problems. -* For `BaseWrapper`, this function has signature `fn load(loader: anytype) !Self`, where the type of `loader` must resemble `PfnGetInstanceProcAddr` (with optionally having a different calling convention). -* For `InstanceWrapper`, this function has signature `fn load(instance: Instance, loader: anytype) !Self`, where the type of `loader` must resemble `PfnGetInstanceProcAddr`. -* For `DeviceWrapper`, this function has signature `fn load(device: Device, loader: anytype) !Self`, where the type of `loader` must resemble `PfnGetDeviceProcAddr`. +* For `BaseWrapper`, this function has signature `fn load(loader: anytype) error{CommandFailure}!Self`, where the type of `loader` must resemble `PfnGetInstanceProcAddr` (with optionally having a different calling convention). +* For `InstanceWrapper`, this function has signature `fn load(instance: Instance, loader: anytype) error{CommandFailure}!Self`, where the type of `loader` must resemble `PfnGetInstanceProcAddr`. +* For `DeviceWrapper`, this function has signature `fn load(device: Device, loader: anytype) error{CommandFailure}!Self`, where the type of `loader` must resemble `PfnGetDeviceProcAddr`. + +By default, wrapper `load` functions return `error.CommandLoadFailure` if a call to the loader resulted in `null`. If this behaviour is not desired, one can use `loadNoFail`. This function accepts the same parameters as `load`, but does not return an error any function pointer fails to load and sets its value to `undefined` instead. It is at the programmer's discretion not to invoke invalid functions, which can be tested for by checking whether the required core and extension versions the function requires are supported. One can access the underlying unwrapped C functions by doing `wrapper.dispatch.vkFuncYouWant(..)`. diff --git a/generator/vulkan/render.zig b/generator/vulkan/render.zig index 23f060b..b87b932 100644 --- a/generator/vulkan/render.zig +++ b/generator/vulkan/render.zig @@ -1053,26 +1053,34 @@ fn Renderer(comptime WriterType: type) type { .device => "device: Device, loader: anytype", }; - const loader_first_param = switch (dispatch_type) { - .base => ".null_handle, ", - .instance => "instance, ", - .device => "device, ", + const loader_first_arg = switch (dispatch_type) { + .base => "Instance.null_handle", + .instance => "instance", + .device => "device", }; @setEvalBranchQuota(2000); try self.writer.print( - \\pub fn load({s}) !Self {{ + \\pub fn load({[params]s}) error{{CommandLoadFailure}}!Self {{ \\ var self: Self = undefined; \\ inline for (std.meta.fields(Dispatch)) |field| {{ \\ const name = @ptrCast([*:0]const u8, field.name ++ "\x00"); - \\ const cmd_ptr = loader({s}name) orelse return error.CommandLoadFailure; + \\ const cmd_ptr = loader({[first_arg]s}, name) orelse return error.CommandLoadFailure; \\ @field(self.dispatch, field.name) = @ptrCast(field.field_type, cmd_ptr); \\ }} \\ return self; \\}} - \\ - , .{ params, loader_first_param }); + \\pub fn loadNoFail({[params]s}) Self {{ + \\ var self: Self = undefined; + \\ inline for (std.meta.fields(Dispatch)) |field| {{ + \\ const name = @ptrCast([*:0]const u8, field.name ++ "\x00"); + \\ const cmd_ptr = loader({[first_arg]s}, name) orelse undefined; + \\ @field(self.dispatch, field.name) = @ptrCast(field.field_type, cmd_ptr); + \\ }} + \\ return self; + \\}} + , .{ .params = params, .first_arg = loader_first_arg }); } fn derefName(name: []const u8) []const u8 {