forked from mirror/vulkan-zig
Registry: Commands
This commit is contained in:
@@ -5,6 +5,17 @@ const Allocator = mem.Allocator;
|
|||||||
const SegmentedList = std.SegmentedList;
|
const SegmentedList = std.SegmentedList;
|
||||||
const StringHashMap = std.StringHashMap;
|
const StringHashMap = std.StringHashMap;
|
||||||
|
|
||||||
|
fn count(haystack: []const u8, needle: u8) usize {
|
||||||
|
var total: usize = 0;
|
||||||
|
for (haystack) |elem| {
|
||||||
|
if (elem == needle) {
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
pub const Registry = struct {
|
pub const Registry = struct {
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
|
|
||||||
@@ -12,6 +23,7 @@ pub const Registry = struct {
|
|||||||
bitmasks: StringHashMap(BitmaskInfo),
|
bitmasks: StringHashMap(BitmaskInfo),
|
||||||
handles: StringHashMap(HandleInfo),
|
handles: StringHashMap(HandleInfo),
|
||||||
structs: StringHashMap(StructInfo),
|
structs: StringHashMap(StructInfo),
|
||||||
|
commands: StringHashMap(CommandInfo),
|
||||||
|
|
||||||
extensions: SegmentedList(ExtensionInfo, 0),
|
extensions: SegmentedList(ExtensionInfo, 0),
|
||||||
|
|
||||||
@@ -28,6 +40,7 @@ pub const Registry = struct {
|
|||||||
.bitmasks = StringHashMap(BitmaskInfo).init(allocator),
|
.bitmasks = StringHashMap(BitmaskInfo).init(allocator),
|
||||||
.handles = StringHashMap(HandleInfo).init(allocator),
|
.handles = StringHashMap(HandleInfo).init(allocator),
|
||||||
.structs = StringHashMap(StructInfo).init(allocator),
|
.structs = StringHashMap(StructInfo).init(allocator),
|
||||||
|
.commands = StringHashMap(CommandInfo).init(allocator),
|
||||||
.extensions = undefined
|
.extensions = undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,6 +57,7 @@ pub const Registry = struct {
|
|||||||
self.bitmasks.deinit();
|
self.bitmasks.deinit();
|
||||||
self.handles.deinit();
|
self.handles.deinit();
|
||||||
self.structs.deinit();
|
self.structs.deinit();
|
||||||
|
self.commands.deinit();
|
||||||
|
|
||||||
// Copy to stack so that the arena doesn't destroy itself
|
// Copy to stack so that the arena doesn't destroy itself
|
||||||
var arena = self.arena;
|
var arena = self.arena;
|
||||||
@@ -106,6 +120,35 @@ pub const Registry = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std.debug.warn("Commands:\n", .{});
|
||||||
|
var it = self.commands.iterator();
|
||||||
|
while (it.next()) |kv| {
|
||||||
|
std.debug.warn(" fn {}(\n", .{kv.key});
|
||||||
|
|
||||||
|
var param_it = kv.value.parameters.iterator(0);
|
||||||
|
while (param_it.next()) |param| {
|
||||||
|
std.debug.warn(" {}: {},\n", .{param.name, param.type_info});
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.warn(" ) {}\n", .{kv.value.return_type});
|
||||||
|
|
||||||
|
if (kv.value.success_codes.len > 0) {
|
||||||
|
std.debug.warn(" Success codes:\n", .{});
|
||||||
|
for (kv.value.success_codes) |code| {
|
||||||
|
std.debug.warn(" {}\n", .{code});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kv.value.error_codes.len > 0) {
|
||||||
|
std.debug.warn(" Error codes:\n", .{});
|
||||||
|
for (kv.value.error_codes) |code| {
|
||||||
|
std.debug.warn(" {}\n", .{code});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std.debug.warn("Extensions:\n", .{});
|
std.debug.warn("Extensions:\n", .{});
|
||||||
var it = self.extensions.iterator(0);
|
var it = self.extensions.iterator(0);
|
||||||
@@ -151,10 +194,7 @@ const TypeInfo = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stars) |ptr_text| {
|
if (stars) |ptr_text| {
|
||||||
var npointers: usize = 0;
|
const npointers = count(ptr_text, '*');
|
||||||
for (ptr_text) |c| {
|
|
||||||
if (c == '*') npointers += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_info.pointers = allocator.alloc(TypeInfo.Pointer, npointers) catch unreachable;
|
type_info.pointers = allocator.alloc(TypeInfo.Pointer, npointers) catch unreachable;
|
||||||
|
|
||||||
@@ -236,19 +276,33 @@ const TypeInfo = struct {
|
|||||||
const StructInfo = struct {
|
const StructInfo = struct {
|
||||||
const Member = struct {
|
const Member = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
type_info: TypeInfo,
|
type_info: TypeInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
members: std.SegmentedList(Member, 0),
|
members: SegmentedList(Member, 0),
|
||||||
aliases: std.SegmentedList([]const u8, 0),
|
aliases: SegmentedList([]const u8, 0),
|
||||||
|
|
||||||
fn init(allocator: *Allocator) StructInfo {
|
fn init(allocator: *Allocator) StructInfo {
|
||||||
return .{
|
return .{
|
||||||
.members = std.SegmentedList(Member, 0).init(allocator),
|
.members = SegmentedList(Member, 0).init(allocator),
|
||||||
.aliases = std.SegmentedList([]const u8, 0).init(allocator)
|
.aliases = SegmentedList([]const u8, 0).init(allocator)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fromXml(allocator: *Allocator, elem: *xml.Element) StructInfo {
|
||||||
|
var s = StructInfo.init(allocator);
|
||||||
|
|
||||||
|
var members = elem.findChildrenByTag("member");
|
||||||
|
while (members.next()) |member| {
|
||||||
|
const member_name = member.getCharData("name").?;
|
||||||
|
const type_info = TypeInfo.fromXml(allocator, member);
|
||||||
|
|
||||||
|
s.addMember(member_name, type_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
fn addMember(self: *StructInfo, name: []const u8, type_info: TypeInfo) void {
|
fn addMember(self: *StructInfo, name: []const u8, type_info: TypeInfo) void {
|
||||||
self.members.push(.{.name = name, .type_info = type_info}) catch unreachable;
|
self.members.push(.{.name = name, .type_info = type_info}) catch unreachable;
|
||||||
}
|
}
|
||||||
@@ -258,6 +312,73 @@ const StructInfo = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CommandInfo = struct {
|
||||||
|
const Parameter = struct {
|
||||||
|
name: []const u8,
|
||||||
|
type_info: TypeInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
parameters: SegmentedList(Parameter, 0),
|
||||||
|
return_type: []const u8, // Return type is always plain
|
||||||
|
success_codes: []const []const u8,
|
||||||
|
error_codes: []const []const u8,
|
||||||
|
aliases: SegmentedList([]const u8, 0),
|
||||||
|
|
||||||
|
fn init(allocator: *Allocator, return_type: []const u8) CommandInfo {
|
||||||
|
return .{
|
||||||
|
.parameters = SegmentedList(Parameter, 0).init(allocator),
|
||||||
|
.return_type = return_type,
|
||||||
|
.success_codes = &[_][]u8{},
|
||||||
|
.error_codes = &[_][]u8{},
|
||||||
|
.aliases = SegmentedList([]const u8, 0).init(allocator)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fromXml(allocator: *Allocator, elem: *xml.Element) CommandInfo {
|
||||||
|
const return_type = elem.findChildByTag("proto").?.getCharData("type").?;
|
||||||
|
var cmd = CommandInfo.init(allocator, return_type);
|
||||||
|
|
||||||
|
if (elem.getAttribute("successcodes")) |codes| {
|
||||||
|
cmd.success_codes = CommandInfo.splitResultCodes(allocator, codes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem.getAttribute("errorcodes")) |codes| {
|
||||||
|
cmd.error_codes = CommandInfo.splitResultCodes(allocator, codes);
|
||||||
|
}
|
||||||
|
|
||||||
|
var parameters = elem.findChildrenByTag("param");
|
||||||
|
while (parameters.next()) |param| {
|
||||||
|
const param_name = param.getCharData("name").?;
|
||||||
|
const type_info = TypeInfo.fromXml(allocator, param);
|
||||||
|
|
||||||
|
cmd.addParameter(param_name, type_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn splitResultCodes(allocator: *Allocator, text: []const u8) []const []const u8 {
|
||||||
|
const ncodes = 1 + count(text, ',');
|
||||||
|
const codes = allocator.alloc([]const u8, ncodes) catch unreachable;
|
||||||
|
|
||||||
|
var it = mem.separate(text, ",");
|
||||||
|
|
||||||
|
for (codes) |*code, i| {
|
||||||
|
code.* = it.next().?;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addParameter(self: *CommandInfo, name: []const u8, type_info: TypeInfo) void {
|
||||||
|
self.parameters.push(.{.name = name, .type_info = type_info}) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addAlias(self: *CommandInfo, alias: []const u8) void {
|
||||||
|
self.aliases.push(alias) catch unreachable;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const HandleInfo = union(enum) {
|
const HandleInfo = union(enum) {
|
||||||
Dispatchable,
|
Dispatchable,
|
||||||
NonDispatchable,
|
NonDispatchable,
|
||||||
@@ -304,12 +425,12 @@ const EnumInfo = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
variants: std.SegmentedList(Variant, 0),
|
variants: SegmentedList(Variant, 0),
|
||||||
|
|
||||||
fn init(allocator: *Allocator, kind: Kind) EnumInfo {
|
fn init(allocator: *Allocator, kind: Kind) EnumInfo {
|
||||||
return .{
|
return .{
|
||||||
.kind = kind,
|
.kind = kind,
|
||||||
.variants = std.SegmentedList(Variant, 0).init(allocator)
|
.variants = SegmentedList(Variant, 0).init(allocator)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +506,8 @@ pub fn generate(backing_allocator: *Allocator, root: *xml.Element) *Registry {
|
|||||||
var registry = Registry.init(backing_allocator) catch unreachable;
|
var registry = Registry.init(backing_allocator) catch unreachable;
|
||||||
|
|
||||||
processTypes(registry, root);
|
processTypes(registry, root);
|
||||||
processEnumInfos(registry, root);
|
processEnums(registry, root);
|
||||||
|
processCommands(registry, root);
|
||||||
processFeatures(registry, root);
|
processFeatures(registry, root);
|
||||||
processExtensions(registry, root);
|
processExtensions(registry, root);
|
||||||
|
|
||||||
@@ -440,20 +562,11 @@ fn processStructType(registry: *Registry, ty: *xml.Element) void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var s = StructInfo.init(®istry.arena.allocator);
|
const s = StructInfo.fromXml(®istry.arena.allocator, ty);
|
||||||
|
|
||||||
var members = ty.findChildrenByTag("member");
|
|
||||||
while (members.next()) |member| {
|
|
||||||
const member_name = member.getCharData("name").?;
|
|
||||||
const type_info = TypeInfo.fromXml(®istry.arena.allocator, member);
|
|
||||||
|
|
||||||
s.addMember(member_name, type_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (registry.structs.put(name, s) catch unreachable) |_| unreachable;
|
if (registry.structs.put(name, s) catch unreachable) |_| unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processEnumInfos(registry: *Registry, root: *xml.Element) void {
|
fn processEnums(registry: *Registry, root: *xml.Element) void {
|
||||||
var it = root.findChildrenByTag("enums");
|
var it = root.findChildrenByTag("enums");
|
||||||
while (it.next()) |enums| {
|
while (it.next()) |enums| {
|
||||||
const name = enums.getAttribute("name").?;
|
const name = enums.getAttribute("name").?;
|
||||||
@@ -464,6 +577,22 @@ fn processEnumInfos(registry: *Registry, root: *xml.Element) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn processCommands(registry: *Registry, root: *xml.Element) void {
|
||||||
|
var commands = root.findChildByTag("commands").?;
|
||||||
|
var command_it = commands.findChildrenByTag("command");
|
||||||
|
while (command_it.next()) |elem| {
|
||||||
|
if (elem.getAttribute("alias")) |alias| {
|
||||||
|
const name = elem.getAttribute("name").?;
|
||||||
|
var cmd = ®istry.commands.get(alias).?.value;
|
||||||
|
cmd.addAlias(name);
|
||||||
|
} else {
|
||||||
|
const name = elem.findChildByTag("proto").?.getCharData("name").?;
|
||||||
|
const command = CommandInfo.fromXml(®istry.arena.allocator, elem);
|
||||||
|
if (registry.commands.put(name, command) catch unreachable) |_| unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn processExtensions(registry: *Registry, root: *xml.Element) void {
|
fn processExtensions(registry: *Registry, root: *xml.Element) void {
|
||||||
var extensions = root.findChildByTag("extensions").?;
|
var extensions = root.findChildByTag("extensions").?;
|
||||||
var ext_it = extensions.findChildrenByTag("extension");
|
var ext_it = extensions.findChildrenByTag("extension");
|
||||||
|
|||||||
Reference in New Issue
Block a user