From 9479fe480ab7fe348e7b0701629db3ebdbd8dabc Mon Sep 17 00:00:00 2001 From: bluesillybeard Date: Fri, 26 Apr 2024 21:56:38 -0600 Subject: [PATCH] Add feature info --- generator/vulkan/render.zig | 107 +++++++++++++++++++++++++++++------- 1 file changed, 87 insertions(+), 20 deletions(-) diff --git a/generator/vulkan/render.zig b/generator/vulkan/render.zig index 18720d0..54e3f51 100644 --- a/generator/vulkan/render.zig +++ b/generator/vulkan/render.zig @@ -469,6 +469,7 @@ fn Renderer(comptime WriterType: type) type { try self.renderCommandPtrs(); try self.renderExtensionInfo(); + try self.renderFeatureInfo(); try self.renderWrappers(); } @@ -1040,9 +1041,9 @@ fn Renderer(comptime WriterType: type) type { \\ }; ); // 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); + var instance_commands = std.BufSet.init(self.allocator); defer instance_commands.deinit(); - var device_commands = std.ArrayList([]const u8).init(self.allocator); + var device_commands = std.BufSet.init(self.allocator); defer device_commands.deinit(); for (self.registry.extensions) |ext| { try self.writer.writeAll("pub const "); @@ -1065,38 +1066,104 @@ fn Renderer(comptime WriterType: type) type { // Vulkan extensions cannot add base functions. .base => return error.InvalidRegistry, .instance => { - try instance_commands.append(command_name); + try instance_commands.insert(command_name); }, .device => { - try device_commands.append(command_name); + try device_commands.insert(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(".instance_functions = "); + try self.renderCommandFlags(&instance_commands); + instance_commands.hash_map.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(".device_functions = "); + try self.renderCommandFlags(&device_commands); + device_commands.hash_map.clearRetainingCapacity(); try self.writer.writeAll("};\n"); } try self.writer.writeAll("};\n"); } + fn renderFeatureInfo(self: *Self) !void { + try self.writer.writeAll( + \\pub const feature_info = struct { + \\ const Info = struct { + \\ base_functions: BaseCommandFlags, + \\ instance_functions: InstanceCommandFlags, + \\ device_functions: DeviceCommandFlags, + \\ }; + ); + // The commands in a feature level are not pre-sorted based on if they are instance or device functions. + var base_commands = std.BufSet.init(self.allocator); + defer base_commands.deinit(); + var instance_commands = std.BufSet.init(self.allocator); + defer instance_commands.deinit(); + var device_commands = std.BufSet.init(self.allocator); + defer device_commands.deinit(); + for (self.registry.features) |feature| { + try self.writer.writeAll("pub const "); + try self.writeIdentifierWithCase(.snake, trimVkNamespace(feature.name)); + try self.writer.writeAll("= Info {\n"); + // collect feature information + for (feature.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) { + .base => { + try base_commands.insert(command_name); + }, + .instance => { + try instance_commands.insert(command_name); + }, + .device => { + try device_commands.insert(command_name); + }, + } + } + } + // and write them out + // clear command lists for next iteration + try self.writer.writeAll(".base_functions = "); + try self.renderCommandFlags(&base_commands); + base_commands.hash_map.clearRetainingCapacity(); + + try self.writer.writeAll(".instance_functions = "); + try self.renderCommandFlags(&instance_commands); + instance_commands.hash_map.clearRetainingCapacity(); + + try self.writer.writeAll(".device_functions = "); + try self.renderCommandFlags(&device_commands); + device_commands.hash_map.clearRetainingCapacity(); + + try self.writer.writeAll("};\n"); + } + + try self.writer.writeAll("};\n"); + } + + fn renderCommandFlags(self: *Self, commands: *const std.BufSet) !void { + try self.writer.writeAll(".{\n"); + var iterator = commands.iterator(); + while (iterator.next()) |command_name| { + try self.writer.writeAll("."); + try self.writeIdentifierWithCase(.camel, trimVkNamespace(command_name.*)); + try self.writer.writeAll(" = true, \n"); + } + try self.writer.writeAll("},\n"); + } + fn renderWrappers(self: *Self) !void { try self.writer.writeAll( \\pub fn CommandFlagsMixin(comptime CommandFlags: type) type {