Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove "enumerate" functions whitelist #160

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 34 additions & 44 deletions src/vulkan/render.zig
Original file line number Diff line number Diff line change
Expand Up @@ -192,48 +192,29 @@ const dispatch_override_functions = std.StaticStringMap(CommandDispatchType).ini
.{ "vkCreateInstance", .base },
});

// Functions that return an array of objects via a count and data pointer.
const enumerate_functions = std.StaticStringMap(void).initComptime(.{
.{"vkEnumeratePhysicalDevices"},
.{"vkEnumeratePhysicalDeviceGroups"},
.{"vkGetPhysicalDeviceQueueFamilyProperties"},
.{"vkGetPhysicalDeviceQueueFamilyProperties2"},
.{"vkEnumerateInstanceLayerProperties"},
.{"vkEnumerateInstanceExtensionProperties"},
.{"vkEnumerateDeviceLayerProperties"},
.{"vkEnumerateDeviceExtensionProperties"},
.{"vkGetImageSparseMemoryRequirements"},
.{"vkGetImageSparseMemoryRequirements2"},
.{"vkGetDeviceImageSparseMemoryRequirements"},
.{"vkGetPhysicalDeviceSparseImageFormatProperties"},
.{"vkGetPhysicalDeviceSparseImageFormatProperties2"},
.{"vkGetPhysicalDeviceToolProperties"},
.{"vkGetPipelineCacheData"},

.{"vkGetPhysicalDeviceSurfaceFormatsKHR"},
.{"vkGetPhysicalDeviceSurfaceFormats2KHR"},
.{"vkGetPhysicalDeviceSurfacePresentModesKHR"},

.{"vkGetSwapchainImagesKHR"},
.{"vkGetPhysicalDevicePresentRectanglesKHR"},

.{"vkGetPhysicalDeviceCalibrateableTimeDomainsKHR"},
});

// Given one of the above commands, returns the type of the array elements
// (and performs some basic verification that the command has the expected signature).
fn getEnumerateFunctionDataType(command: reg.Command) !reg.TypeInfo {
// If the given function returns an array (e.g. `vkEnumeratePhysicalDevices()`),
// returns the type of the array elements.
fn getEnumerateFunctionDataType(name: []const u8, command: reg.Command) ?reg.TypeInfo {
if (command.params.len < 2) {
return error.InvalidRegistry;
return null;
}
const count_param = command.params[command.params.len - 2];
if (!count_param.is_buffer_len) {
return error.InvalidRegistry;
}
const data_param = command.params[command.params.len - 1];
if (!(count_param.is_buffer_len and data_param.is_optional)) {
return null;
}

// Uses a bool out-parameter for an "incomplete" result, and so would need a
// special case implementation.
if (mem.eql(u8, name, "vkGetFaultData")) {
return null;
}

// TODO: Extra validation.

Comment on lines +203 to +214
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some thoughts:

  • Did you consider checking the mutability of the output parameter? That should be something like param_type.pointer_is_mutable, or simply use classifyParam and check out_pointer (I think). Additionally, you could check that the size param has class mut_buffer_len
  • Did you consider checking whether the successcodes includes VK_INCOMPLETE?

Maybe this would be enough and then we don't need to bother with the scripts and stuff

return switch (data_param.param_type) {
.pointer => |pointer| pointer.child.*,
else => error.InvalidRegistry,
else => null,
};
}

Expand Down Expand Up @@ -1456,8 +1437,8 @@ fn Renderer(comptime WriterType: type) type {
// for newer versions of vulkan can still invoke extension behavior on older
// implementations.
try self.renderWrapper(decl.name, command);
if (enumerate_functions.has(decl.name)) {
try self.renderWrapperAlloc(decl.name, command);
if (getEnumerateFunctionDataType(decl.name, command)) |data_type| {
try self.renderWrapperAlloc(decl.name, command, data_type);
}
}

Expand Down Expand Up @@ -1565,8 +1546,8 @@ fn Renderer(comptime WriterType: type) type {
}

try self.renderProxyCommand(decl.name, command, dispatch_handle);
if (enumerate_functions.has(decl.name)) {
try self.renderProxyCommandAlloc(decl.name, command, dispatch_handle);
if (getEnumerateFunctionDataType(decl.name, command)) |data_type| {
try self.renderProxyCommandAlloc(decl.name, command, dispatch_handle, data_type);
}
}

Expand Down Expand Up @@ -1636,7 +1617,13 @@ fn Renderer(comptime WriterType: type) type {
return std.mem.concat(self.allocator, u8, &.{ wrapped_name[0..base_len], "Alloc", tag });
}

fn renderProxyCommandAlloc(self: *Self, wrapped_name: []const u8, command: reg.Command, dispatch_handle: []const u8) !void {
fn renderProxyCommandAlloc(
self: *Self,
wrapped_name: []const u8,
command: reg.Command,
dispatch_handle: []const u8,
data_type: reg.TypeInfo,
) !void {
const returns_vk_result = command.return_type.* == .name and mem.eql(u8, command.return_type.name, "VkResult");

const name = try self.makeAllocWrapperName(wrapped_name);
Expand All @@ -1646,7 +1633,6 @@ fn Renderer(comptime WriterType: type) type {
return error.InvalidRegistry;
}
const params = command.params[0 .. command.params.len - 2];
const data_type = try getEnumerateFunctionDataType(command);

try self.writer.writeAll("pub const ");
try self.renderErrorSetName(name);
Expand Down Expand Up @@ -1982,7 +1968,12 @@ fn Renderer(comptime WriterType: type) type {
try self.renderTypeInfo(data_type);
}

fn renderWrapperAlloc(self: *Self, wrapped_name: []const u8, command: reg.Command) !void {
fn renderWrapperAlloc(
self: *Self,
wrapped_name: []const u8,
command: reg.Command,
data_type: reg.TypeInfo,
) !void {
const returns_vk_result = command.return_type.* == .name and mem.eql(u8, command.return_type.name, "VkResult");

const name = try self.makeAllocWrapperName(wrapped_name);
Expand All @@ -1992,7 +1983,6 @@ fn Renderer(comptime WriterType: type) type {
return error.InvalidRegistry;
}
const params = command.params[0 .. command.params.len - 2];
const data_type = try getEnumerateFunctionDataType(command);

if (returns_vk_result) {
try self.writer.writeAll("pub const ");
Expand Down