diff --git a/generator/main.zig b/generator/main.zig index 822471a..bbae7f2 100644 --- a/generator/main.zig +++ b/generator/main.zig @@ -91,5 +91,5 @@ pub fn main() !void { test "main" { _ = @import("xml.zig"); - _ = @import("spec-c-parse.zig"); + _ = @import("registry/c-parse.zig"); } diff --git a/generator/registry.zig b/generator/registry.zig index 7637f96..4070805 100644 --- a/generator/registry.zig +++ b/generator/registry.zig @@ -120,7 +120,7 @@ pub const Foreign = struct { pub const Feature = struct { name: []const u8, - number: []const u8, + level: FeatureLevel, // from 'number' requires: []Require, }; @@ -130,12 +130,18 @@ pub const Extension = struct { device, }; + pub const Promotion = union(enum) { + none: void, + feature: FeatureLevel, + extension: []const u8, + }; + name: []const u8, number: u31, version: u32, extension_type: ?ExtensionType, depends: []const []const u8, // Other extensions - promoted_to: ?[]const u8, + promoted_to: Promotion, platform: ?[]const u8, requires: []Require, }; @@ -150,6 +156,11 @@ pub const Require = struct { extends: []EnumExtension, types: []const []const u8, commands: []const []const u8, - required_feature: ?[]const u8, + required_feature_level: ?FeatureLevel, required_extension: ?[]const u8, }; + +pub const FeatureLevel = struct { + major: u32, + minor: u32, +}; diff --git a/generator/registry/parse.zig b/generator/registry/parse.zig index 385fdef..9614ac1 100644 --- a/generator/registry/parse.zig +++ b/generator/registry/parse.zig @@ -463,7 +463,10 @@ fn parseFeatures(allocator: *Allocator, root: *xml.Element) ![]registry.Feature fn parseFeature(allocator: *Allocator, feature: *xml.Element) !registry.Feature { const name = feature.getAttribute("name") orelse return error.InvalidRegistry; - const number = feature.getAttribute("number") orelse return error.InvalidRegistry; + const feature_level = blk: { + const number = feature.getAttribute("number") orelse return error.InvalidRegistry; + break :blk try splitFeatureLevel(number, "."); + }; var requires = try allocator.alloc(registry.Require, feature.children.count()); var i: usize = 0; @@ -475,7 +478,7 @@ fn parseFeature(allocator: *Allocator, feature: *xml.Element) !registry.Feature return registry.Feature{ .name = name, - .number = number, + .level = feature_level, .requires = allocator.shrink(requires, i) }; } @@ -566,11 +569,20 @@ fn parseRequire(allocator: *Allocator, require: *xml.Element, extnumber: ?u31) ! } } + const required_feature_level = blk: { + const feature_level = require.getAttribute("feature") orelse break :blk null; + if (!mem.startsWith(u8, feature_level, "VK_VERSION_")) { + return error.InvalidRegistry; + } + + break :blk try splitFeatureLevel(feature_level["VK_VERSION_".len ..], "_"); + }; + return registry.Require{ .extends = extends, .types = types, .commands = commands, - .required_feature = require.getAttribute("feature"), + .required_feature_level = required_feature_level, .required_extension = require.getAttribute("extension"), }; } @@ -615,9 +627,19 @@ fn parseExtension(allocator: *Allocator, extension: *xml.Element) !?registry.Ext const name = extension.getAttribute("name") orelse return error.InvalidRegistry; const platform = extension.getAttribute("platform"); - const promoted_to = extension.getAttribute("promotedto"); const version = try findExtVersion(extension); + const promoted_to: registry.Extension.Promotion = blk: { + const promotedto = extension.getAttribute("promotedto") orelse break :blk .none; + if (mem.startsWith(u8, promotedto, "VK_VERSION_")) { + const feature_level = try splitFeatureLevel(promotedto["VK_VERSION_".len ..], "_"); + + break :blk .{.feature = feature_level}; + } + + break :blk .{.extension = promotedto}; + }; + const number = blk: { const number_str = extension.getAttribute("number") orelse return error.InvalidRegistry; break :blk try std.fmt.parseInt(u31, number_str, 10); @@ -658,3 +680,18 @@ fn parseExtension(allocator: *Allocator, extension: *xml.Element) !?registry.Ext .requires = allocator.shrink(requires, i) }; } + +fn splitFeatureLevel(ver: []const u8, split: []const u8) !registry.FeatureLevel { + var it = mem.split(ver, split); + + const major = it.next() orelse return error.InvalidFeatureLevel; + const minor = it.next() orelse return error.InvalidFeatureLevel; + if (it.next() != null) { + return error.InvalidFeatureLevel; + } + + return registry.FeatureLevel{ + .major = try std.fmt.parseInt(u32, major, 10), + .minor = try std.fmt.parseInt(u32, minor, 10), + }; +}