Vulkan 1.2.170 compatibility

This commit is contained in:
Robin Voetter
2021-02-16 15:26:22 +01:00
parent e7d6f9f012
commit 9f23e2e16d
4 changed files with 669 additions and 144 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -107,9 +107,21 @@ fn parseBitmaskType(ty: *xml.Element) !registry.Declaration {
.decl_type = .{.alias = .{.name = alias, .target = .other_type}}, .decl_type = .{.alias = .{.name = alias, .target = .other_type}},
}; };
} else { } else {
const flags_type = ty.getCharData("type") orelse return error.InvalidRegistry;
const bitwidth: u8 = if (mem.eql(u8, flags_type, "VkFlags"))
32
else if (mem.eql(u8, flags_type, "VkFlags64"))
64
else
return error.InvalidRegistry;
return registry.Declaration{ return registry.Declaration{
.name = ty.getCharData("name") orelse return error.InvalidRegistry, .name = ty.getCharData("name") orelse return error.InvalidRegistry,
.decl_type = .{.bitmask = .{.bits_enum = ty.getAttribute("requires")}}, .decl_type = .{.bitmask = .{
.bits_enum = ty.getAttribute("requires"),
.bitwidth = bitwidth,
}},
}; };
} }
} }
@@ -317,6 +329,11 @@ fn parseEnumFields(allocator: *Allocator, elem: *xml.Element) !registry.Enum {
return error.InvalidRegistry; return error.InvalidRegistry;
} }
const bitwidth = if (elem.getAttribute("bitwidth")) |bitwidth|
try std.fmt.parseInt(u8, bitwidth, 10)
else
32;
const fields = try allocator.alloc(registry.Enum.Field, elem.children.items.len); const fields = try allocator.alloc(registry.Enum.Field, elem.children.items.len);
var i: usize = 0; var i: usize = 0;
@@ -328,6 +345,7 @@ fn parseEnumFields(allocator: *Allocator, elem: *xml.Element) !registry.Enum {
return registry.Enum{ return registry.Enum{
.fields = allocator.shrink(fields, i), .fields = allocator.shrink(fields, i),
.bitwidth = bitwidth,
.is_bitmask = is_bitmask, .is_bitmask = is_bitmask,
}; };
} }
@@ -356,7 +374,7 @@ fn parseEnumField(field: *xml.Element) !registry.Enum.Field {
break :blk .{.int = try std.fmt.parseInt(i32, value, 10)}; break :blk .{.int = try std.fmt.parseInt(i32, value, 10)};
} }
} else if (field.getAttribute("bitpos")) |bitpos| { } else if (field.getAttribute("bitpos")) |bitpos| {
break :blk .{.bitpos = try std.fmt.parseInt(u5, bitpos, 10)}; break :blk .{.bitpos = try std.fmt.parseInt(u6, bitpos, 10)};
} else if (field.getAttribute("alias")) |alias| { } else if (field.getAttribute("alias")) |alias| {
break :blk .{.alias = .{.name = alias, .is_compat_alias = is_compat_alias}}; break :blk .{.alias = .{.name = alias, .is_compat_alias = is_compat_alias}};
} else { } else {

View File

@@ -71,7 +71,7 @@ pub const Container = struct {
pub const Enum = struct { pub const Enum = struct {
pub const Value = union(enum) { pub const Value = union(enum) {
bitpos: u5, // 1 << bitpos bitpos: u6, // 1 << bitpos
bit_vector: i32, // Combined flags & some vendor IDs bit_vector: i32, // Combined flags & some vendor IDs
int: i32, int: i32,
alias: struct { alias: struct {
@@ -86,11 +86,13 @@ pub const Enum = struct {
}; };
fields: []Field, fields: []Field,
bitwidth: u8,
is_bitmask: bool, is_bitmask: bool,
}; };
pub const Bitmask = struct { pub const Bitmask = struct {
bits_enum: ?[]const u8, bits_enum: ?[]const u8,
bitwidth: u8,
}; };
pub const Handle = struct { pub const Handle = struct {

View File

@@ -24,9 +24,9 @@ const preamble =
\\ .AAPCSVFP \\ .AAPCSVFP
\\ else \\ else
\\ .C; \\ .C;
\\pub fn FlagsMixin(comptime FlagsType: type) type { \\pub fn FlagsMixin(comptime FlagsType: type, comptime Int: type) type {
\\ return struct { \\ return struct {
\\ pub const IntType = Flags; \\ pub const IntType = Int;
\\ pub fn toInt(self: FlagsType) IntType { \\ pub fn toInt(self: FlagsType) IntType {
\\ return @bitCast(IntType, self); \\ return @bitCast(IntType, self);
\\ } \\ }
@@ -129,15 +129,16 @@ fn Renderer(comptime WriterType: type) type {
return struct { return struct {
const Self = @This(); const Self = @This();
const WriteError = WriterType.Error; const WriteError = WriterType.Error;
const RenderTypeInfoError = WriteError || error { const RenderTypeInfoError = WriteError || std.fmt.ParseIntError || error { OutOfMemory, InvalidRegistry };
OutOfMemory,
};
const BitflagName = struct { const BitflagName = struct {
/// Name without FlagBits, so VkSurfaceTransformFlagBitsKHR /// Name without FlagBits, so VkSurfaceTransformFlagBitsKHR
/// becomes VkSurfaceTransform /// becomes VkSurfaceTransform
base_name: []const u8, base_name: []const u8,
/// Optional flag bits revision, used in places like VkAccessFlagBits2KHR
revision: ?[]const u8,
/// Optional tag of the flag /// Optional tag of the flag
tag: ?[]const u8, tag: ?[]const u8,
}; };
@@ -225,8 +226,8 @@ fn Renderer(comptime WriterType: type) type {
while (true) { while (true) {
const rest = field_it.rest(); const rest = field_it.rest();
const field_segment = field_it.next() orelse return error.InvalidRegistry;
const enum_segment = enum_it.next() orelse return rest; const enum_segment = enum_it.next() orelse return rest;
const field_segment = field_it.next() orelse return error.FieldNameEqualsEnumName;
if (!eqlIgnoreCase(enum_segment, field_segment)) { if (!eqlIgnoreCase(enum_segment, field_segment)) {
return rest; return rest;
@@ -234,16 +235,51 @@ fn Renderer(comptime WriterType: type) type {
} }
} }
fn extractBitflagName(self: Self, name: []const u8) ?BitflagName { fn extractBitflagFieldName(self: Self, bitflag_name: BitflagName, field_name: []const u8) ![]const u8 {
const tag = self.id_renderer.getAuthorTag(name); var flag_it = id_render.SegmentIterator.init(bitflag_name.base_name);
const base_name = if (tag) |tag_name| name[0 .. name.len - tag_name.len] else name; var field_it = id_render.SegmentIterator.init(field_name);
if (!mem.endsWith(u8, base_name, "FlagBits")) { while (true) {
const rest = field_it.rest();
const field_segment = field_it.next() orelse return error.InvalidRegistry;
const flag_segment = flag_it.next() orelse {
if (bitflag_name.revision) |revision| {
if (mem.eql(u8, revision, field_segment))
return field_it.rest();
}
return rest;
};
if (!eqlIgnoreCase(flag_segment, field_segment)) {
return rest;
}
}
}
fn extractBitflagName(self: Self, name: []const u8) !?BitflagName {
const tag = self.id_renderer.getAuthorTag(name);
const tagless_name = if (tag) |tag_name| name[0 .. name.len - tag_name.len] else name;
const maybe_last_number = mem.lastIndexOfAny(u8, tagless_name, "0123456789");
const base_name = if (maybe_last_number) |last_number|
tagless_name[0 .. last_number]
else
tagless_name;
const maybe_flag_bits_index = mem.lastIndexOf(u8, base_name, "FlagBits");
if (maybe_flag_bits_index == null) {
return null; return null;
} else if (maybe_flag_bits_index != base_name.len - "FlagBits".len) {
// It is unlikely that a type that is not a flag bit would contain FlagBits,
// and more likely that we have missed something if FlagBits isn't the last
// part of base_name
return error.InvalidRegistry;
} }
return BitflagName{ return BitflagName{
.base_name = base_name[0 .. base_name.len - "FlagBits".len], .base_name = base_name[0 .. base_name.len - "FlagBits".len],
.revision = if (maybe_last_number) |last_number| tagless_name[last_number..] else null,
.tag = tag, .tag = tag,
}; };
} }
@@ -333,7 +369,7 @@ fn Renderer(comptime WriterType: type) type {
} }
}, },
.name => |name| { .name => |name| {
if (self.extractBitflagName(param.param_type.name) != null or self.isFlags(param.param_type.name)) { if ((try self.extractBitflagName(param.param_type.name)) != null or self.isFlags(param.param_type.name)) {
return .bitflags; return .bitflags;
} }
}, },
@@ -495,9 +531,10 @@ fn Renderer(comptime WriterType: type) type {
if (builtin_types.get(name)) |zig_name| { if (builtin_types.get(name)) |zig_name| {
try self.writer.writeAll(zig_name); try self.writer.writeAll(zig_name);
return; return;
} else if (self.extractBitflagName(name)) |bitflag_name| { } else if (try self.extractBitflagName(name)) |bitflag_name| {
try self.writeIdentifierFmt("{s}Flags{s}", .{ try self.writeIdentifierFmt("{s}Flags{s}{s}", .{
trimVkNamespace(bitflag_name.base_name), trimVkNamespace(bitflag_name.base_name),
@as([]const u8, if (bitflag_name.revision) |revision| revision else ""),
@as([]const u8, if (bitflag_name.tag) |tag| tag else "") @as([]const u8, if (bitflag_name.tag) |tag| tag else "")
}); });
return; return;
@@ -534,9 +571,10 @@ fn Renderer(comptime WriterType: type) type {
blk: { blk: {
if (param.param_type == .name) { if (param.param_type == .name) {
if (self.extractBitflagName(param.param_type.name)) |bitflag_name| { if (try self.extractBitflagName(param.param_type.name)) |bitflag_name| {
try self.writeIdentifierFmt("{s}Flags{s}", .{ try self.writeIdentifierFmt("{s}Flags{s}{s}", .{
trimVkNamespace(bitflag_name.base_name), trimVkNamespace(bitflag_name.base_name),
@as([]const u8, if (bitflag_name.revision) |revision| revision else ""),
@as([]const u8, if (bitflag_name.tag) |tag| tag else "") @as([]const u8, if (bitflag_name.tag) |tag| tag else "")
}); });
try self.writer.writeAll(".IntType"); try self.writer.writeAll(".IntType");
@@ -720,24 +758,48 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll("_,};\n"); try self.writer.writeAll("_,};\n");
} }
fn bitmaskFlagsType(bitwidth: u8) ![]const u8 {
return switch (bitwidth) {
32 => "Flags",
64 => "Flags64",
else => return error.InvalidRegistry,
};
}
fn renderUsingFlagsMixin(self: *Self, name: []const u8, bitwidth: u8) !void {
const flags_type = switch (bitwidth) {
32 => "Flags",
64 => "Flags64",
else => return error.InvalidRegistry,
};
try self.writer.writeAll("pub usingnamespace FlagsMixin(");
try self.renderName(name);
try self.writer.print(", {s});\n", .{ flags_type });
}
fn renderBitmaskBits(self: *Self, name: []const u8, bits: reg.Enum) !void { fn renderBitmaskBits(self: *Self, name: []const u8, bits: reg.Enum) !void {
try self.writer.writeAll("pub const "); try self.writer.writeAll("pub const ");
try self.renderName(name); try self.renderName(name);
try self.writer.writeAll(" = packed struct {"); try self.writer.writeAll(" = packed struct {");
const bitflag_name = (try self.extractBitflagName(name)) orelse return error.InvalidRegistry;
const flags_type = try bitmaskFlagsType(bits.bitwidth);
if (bits.fields.len == 0) { if (bits.fields.len == 0) {
try self.writer.writeAll("_reserved_bits: Flags = 0,"); try self.writer.print("_reserved_bits: {s} = 0,", .{ flags_type });
} else { } else {
var flags_by_bitpos = [_]?[]const u8{null} ** 32; var flags_by_bitpos = [_]?[]const u8{null} ** 64;
for (bits.fields) |field| { for (bits.fields) |field| {
if (field.value == .bitpos) { if (field.value == .bitpos) {
flags_by_bitpos[field.value.bitpos] = field.name; flags_by_bitpos[field.value.bitpos] = field.name;
} }
} }
for (flags_by_bitpos) |opt_flag_name, bitpos| { for (flags_by_bitpos[0.. bits.bitwidth]) |maybe_flag_name, bitpos| {
if (opt_flag_name) |flag_name| { if (maybe_flag_name) |flag_name| {
try self.renderEnumFieldName(name, flag_name); const field_name = try self.extractBitflagFieldName(bitflag_name, flag_name);
try self.writeIdentifierWithCase(.snake, field_name);
} else { } else {
try self.writer.print("_reserved_bit_{}", .{bitpos}); try self.writer.print("_reserved_bit_{}", .{bitpos});
} }
@@ -751,7 +813,7 @@ fn Renderer(comptime WriterType: type) type {
} }
try self.writer.writeAll("pub usingnamespace FlagsMixin("); try self.writer.writeAll("pub usingnamespace FlagsMixin(");
try self.renderName(name); try self.renderName(name);
try self.writer.writeAll(");\n};\n"); try self.writer.print(", {s});\n}};\n", .{ flags_type });
} }
fn renderBitmask(self: *Self, name: []const u8, bitmask: reg.Bitmask) !void { fn renderBitmask(self: *Self, name: []const u8, bitmask: reg.Bitmask) !void {
@@ -759,18 +821,22 @@ fn Renderer(comptime WriterType: type) type {
// The bits structure is generated by renderBitmaskBits, but that wont // The bits structure is generated by renderBitmaskBits, but that wont
// output flags with no associated bits type. // output flags with no associated bits type.
const flags_type = try bitmaskFlagsType(bitmask.bitwidth);
try self.writer.writeAll("pub const "); try self.writer.writeAll("pub const ");
try self.renderName(name); try self.renderName(name);
try self.writer.writeAll( try self.writer.print(
\\ = packed struct { \\ = packed struct {{
\\_reserved_bits: Flags = 0, \\_reserved_bits: {s} = 0,
\\pub usingnamespace FlagsMixin( \\pub usingnamespace FlagsMixin(
, .{ flags_type }
); );
try self.renderName(name); try self.renderName(name);
try self.writer.writeAll( try self.writer.print(
\\); \\, {s});
\\}; \\}};
\\ \\
, .{ flags_type }
); );
} }
} }
@@ -786,7 +852,7 @@ fn Renderer(comptime WriterType: type) type {
fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void { fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void {
if (alias.target == .other_command) { if (alias.target == .other_command) {
return; return;
} else if (self.extractBitflagName(name) != null) { } else if ((try self.extractBitflagName(name)) != null) {
// Don't make aliases of the bitflag names, as those are replaced by just the flags type // Don't make aliases of the bitflag names, as those are replaced by just the flags type
return; return;
} }