Add non-failing dispatch load function

This commit is contained in:
Robin Voetter
2021-12-08 23:48:49 +01:00
parent d1e949a434
commit d9a57859c6
2 changed files with 21 additions and 11 deletions

View File

@@ -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(..)`.

View File

@@ -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 {