forked from mirror/vulkan-zig
fix parsing issues with vk 1.3.278
This change introduced len/optional attributes for arrays. Previously, we assumed that these would only occur on pointers, but now, this information is also available for arrays. This adapts the registery and parsing code to also parse these properly. No modifications are made to the rendering part as of yet, since these partially filled arrays cannot be cleanly represented in Zig.
This commit is contained in:
@@ -386,6 +386,8 @@ fn parseDeclaration(allocator: Allocator, xctok: *XmlCTokenizer, ptrs_optional:
|
|||||||
inner_type.* = .{
|
inner_type.* = .{
|
||||||
.array = .{
|
.array = .{
|
||||||
.size = array_size,
|
.size = array_size,
|
||||||
|
.valid_size = .all, // Refined later
|
||||||
|
.is_optional = true,
|
||||||
.child = child,
|
.child = child,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -305,19 +305,37 @@ fn parsePointerMeta(fields: Fields, type_info: *registry.TypeInfo, elem: *xml.El
|
|||||||
if (elem.getAttribute("len")) |lens| {
|
if (elem.getAttribute("len")) |lens| {
|
||||||
var it = mem.split(u8, lens, ",");
|
var it = mem.split(u8, lens, ",");
|
||||||
var current_type_info = type_info;
|
var current_type_info = type_info;
|
||||||
while (current_type_info.* == .pointer) {
|
|
||||||
// TODO: Check altlen
|
|
||||||
const size = if (it.next()) |len_str| blk: {
|
|
||||||
const size_optional = lenToPointer(fields, len_str);
|
|
||||||
current_type_info.pointer.is_optional = size_optional[1];
|
|
||||||
break :blk size_optional[0];
|
|
||||||
} else .many;
|
|
||||||
current_type_info.pointer.size = size;
|
|
||||||
|
|
||||||
current_type_info = current_type_info.pointer.child;
|
while (true) switch (current_type_info.*) {
|
||||||
len_attribute_depth += 1;
|
.pointer => |*ptr| {
|
||||||
|
if (it.next()) |len_str| {
|
||||||
|
ptr.size, ptr.is_optional = lenToPointer(fields, len_str);
|
||||||
|
} else {
|
||||||
|
ptr.size = .many;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_type_info = ptr.child;
|
||||||
|
len_attribute_depth += 1;
|
||||||
|
},
|
||||||
|
.array => |*arr| {
|
||||||
|
if (it.next()) |len_str| {
|
||||||
|
const size, _ = lenToPointer(fields, len_str);
|
||||||
|
arr.valid_size = switch (size) {
|
||||||
|
.one => .all,
|
||||||
|
.many => .many,
|
||||||
|
.other_field => |field| .{ .other_field = field },
|
||||||
|
.zero_terminated => .zero_terminated,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
arr.valid_size = .all;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_type_info = arr.child;
|
||||||
|
len_attribute_depth += 1;
|
||||||
|
},
|
||||||
|
else => break,
|
||||||
|
};
|
||||||
|
|
||||||
if (it.next()) |_| {
|
if (it.next()) |_| {
|
||||||
// There are more elements in the `len` attribute than there are pointers
|
// There are more elements in the `len` attribute than there are pointers
|
||||||
// Something probably went wrong
|
// Something probably went wrong
|
||||||
@@ -331,28 +349,28 @@ fn parsePointerMeta(fields: Fields, type_info: *registry.TypeInfo, elem: *xml.El
|
|||||||
if (elem.getAttribute("optional")) |optionals| {
|
if (elem.getAttribute("optional")) |optionals| {
|
||||||
var it = mem.split(u8, optionals, ",");
|
var it = mem.split(u8, optionals, ",");
|
||||||
var current_type_info = type_info;
|
var current_type_info = type_info;
|
||||||
while (current_type_info.* == .pointer) {
|
while (true) switch (current_type_info.*) {
|
||||||
|
inline .pointer, .array => |*info| {
|
||||||
if (it.next()) |optional_str| {
|
if (it.next()) |optional_str| {
|
||||||
|
|
||||||
// The pointer may have already been marked as optional due to its `len` attribute.
|
// The pointer may have already been marked as optional due to its `len` attribute.
|
||||||
var is_already_optional = false;
|
const is_already_optional = current_depth < len_attribute_depth and info.is_optional;
|
||||||
if (current_depth < len_attribute_depth)
|
info.is_optional = is_already_optional or mem.eql(u8, optional_str, "true");
|
||||||
is_already_optional = current_type_info.pointer.is_optional;
|
|
||||||
|
|
||||||
current_type_info.pointer.is_optional =
|
|
||||||
is_already_optional or mem.eql(u8, optional_str, "true");
|
|
||||||
} else {
|
} else {
|
||||||
// There is no information for this pointer, probably incorrect.
|
// There is no information for this pointer, probably incorrect.
|
||||||
// Currently there is one definition where this is the case, VkCudaLaunchInfoNV.
|
// Currently there is one definition where this is the case, VkCudaLaunchInfoNV.
|
||||||
|
|
||||||
// We work around these by assuming that they are optional, so that in the case
|
// We work around these by assuming that they are optional, so that in the case
|
||||||
// that they are, we can assign null to them.
|
// that they are, we can assign null to them.
|
||||||
// See https://github.com/Snektron/vulkan-zig/issues/109
|
// See https://github.com/Snektron/vulkan-zig/issues/109
|
||||||
current_type_info.pointer.is_optional = true;
|
info.is_optional = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_type_info = current_type_info.pointer.child;
|
current_type_info = info.child;
|
||||||
current_depth += 1;
|
current_depth += 1;
|
||||||
}
|
},
|
||||||
|
else => break,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,8 +123,10 @@ pub const Command = struct {
|
|||||||
pub const Pointer = struct {
|
pub const Pointer = struct {
|
||||||
pub const PointerSize = union(enum) {
|
pub const PointerSize = union(enum) {
|
||||||
one,
|
one,
|
||||||
many, // The length is given by some complex expression, possibly involving another field
|
/// The length is given by some complex expression, possibly involving another field
|
||||||
other_field: []const u8, // The length is given by some other field or parameter
|
many,
|
||||||
|
/// The length is given by some other field or parameter
|
||||||
|
other_field: []const u8,
|
||||||
zero_terminated,
|
zero_terminated,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -140,7 +142,26 @@ pub const Array = struct {
|
|||||||
alias: []const u8, // Field size is given by an api constant
|
alias: []const u8, // Field size is given by an api constant
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ArrayValidSize = union(enum) {
|
||||||
|
/// All elements are valid.
|
||||||
|
all,
|
||||||
|
/// The length is given by some complex expression, possibly involving another field
|
||||||
|
many,
|
||||||
|
/// The length is given by some complex expression, possibly involving another field
|
||||||
|
other_field: []const u8,
|
||||||
|
/// The valid elements are terminated by a 0, or by the bounds of the array.
|
||||||
|
zero_terminated,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This is the total size of the array
|
||||||
size: ArraySize,
|
size: ArraySize,
|
||||||
|
/// The number of items that are actually filled with valid values
|
||||||
|
valid_size: ArrayValidSize,
|
||||||
|
/// Some members may indicate than an array is optional. This happens with
|
||||||
|
/// VkPhysicalDeviceHostImageCopyPropertiesEXT::optimalTilingLayoutUUID for example.
|
||||||
|
/// The spec is not entirely clear about what this means, but presumably it should
|
||||||
|
/// be filled with all zeroes.
|
||||||
|
is_optional: bool,
|
||||||
child: *TypeInfo,
|
child: *TypeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user