From 9c45afca2ed3b9bc743fdcdab8c0b25aebf7c6bf Mon Sep 17 00:00:00 2001 From: bluesillybeard Date: Wed, 10 Apr 2024 17:06:43 -0600 Subject: [PATCH] Add extension function metadata for #112 --- generator/vulkan/render.zig | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/generator/vulkan/render.zig b/generator/vulkan/render.zig index d730758..a8841c1 100644 --- a/generator/vulkan/render.zig +++ b/generator/vulkan/render.zig @@ -1035,13 +1035,80 @@ fn Renderer(comptime WriterType: type) type { \\ const Info = struct { \\ name: [:0]const u8, \\ version: u32, + \\ instance_functions: InstanceCommandFlags, + \\ device_functions: DeviceCommandFlags, \\ }; ); + // The commands in an extension are not pre-sorted based on if they are instance or device functions. + var instance_commands = std.ArrayList([]const u8).init(self.allocator); + defer instance_commands.deinit(); + var device_commands = std.ArrayList([]const u8).init(self.allocator); + defer device_commands.deinit(); for (self.registry.extensions) |ext| { try self.writer.writeAll("pub const "); try self.writeIdentifierWithCase(.snake, trimVkNamespace(ext.name)); try self.writer.writeAll("= Info {\n"); try self.writer.print(".name = \"{s}\", .version = {},", .{ ext.name, ext.version }); + // collect extension functions + for(ext.requires) |require| { + for(require.commands) |command_name| { + const decl = self.resolveDeclaration(command_name) orelse continue; + // If the target type does not exist, it was likely an empty enum - + // assume spec is correct and that this was not a function alias. + const decl_type = self.resolveAlias(decl) catch continue; + const command = switch (decl_type) { + .command => |cmd| cmd, + else => continue, + }; + const class = classifyCommandDispatch(command_name, command); + switch (class) { + // Vulkan extensions cannot add base functions. + .base => continue, + // TODO: some extensions have multiple separate requirements. + // For example, "VK_KHR_push_descriptor" depends on either "VK_VERSION_1_1" or "VK_KHR_descriptor_update_template", + // which causes the same function to be mentioned twice; once for each requirement. + // For now, duplicate functions are just removed, + // However in the future it might be worth exposing these separate requirements somehow. + .instance => { + var duplicate = false; + for(instance_commands.items) |cmd| { + if(std.mem.eql(u8, cmd, command_name)) { + duplicate = true; + } + } + if(!duplicate) try instance_commands.append(command_name); + }, + .device => { + var duplicate = false; + for(device_commands.items) |cmd| { + if(std.mem.eql(u8, cmd, command_name)) { + duplicate = true; + } + } + if(!duplicate) try device_commands.append(command_name); + }, + } + } + } + // and write them out + try self.writer.writeAll(".instance_functions = .{\n"); + for(instance_commands.items) |command_name| { + try self.writer.writeAll("."); + try self.writeIdentifierWithCase(.camel, trimVkNamespace(command_name)); + try self.writer.writeAll(" = true, \n"); + } + try self.writer.writeAll("},\n"); + instance_commands.clearRetainingCapacity(); + + try self.writer.writeAll(".device_functions = .{\n"); + for(device_commands.items) |command_name| { + try self.writer.writeAll("."); + try self.writeIdentifierWithCase(.camel, trimVkNamespace(command_name)); + try self.writer.writeAll(" = true, \n"); + } + try self.writer.writeAll("},\n"); + device_commands.clearRetainingCapacity(); + try self.writer.writeAll("};\n"); } try self.writer.writeAll("};\n");