Fix a whole bunch of issues exposed by ziglang/zig#9191

This also includes a workaround for the fact that @"type" refers to the builtin
and not to a variable called "type". See ziglang/zig#2897.
This commit is contained in:
Robin Voetter
2021-06-24 02:11:36 +02:00
parent b63533d95b
commit b3c71d69ea
10 changed files with 82 additions and 75 deletions

View File

@@ -34,7 +34,7 @@ pub const ResourceGenStep = struct {
return self; return self;
} }
fn renderPath(self: *ResourceGenStep, path: []const u8, writer: anytype) void { fn renderPath(path: []const u8, writer: anytype) void {
const separators = &[_]u8{ std.fs.path.sep_windows, std.fs.path.sep_posix }; const separators = &[_]u8{ std.fs.path.sep_windows, std.fs.path.sep_posix };
var i: usize = 0; var i: usize = 0;
while (std.mem.indexOfAnyPos(u8, path, i, separators)) |j| { while (std.mem.indexOfAnyPos(u8, path, i, separators)) |j| {
@@ -55,7 +55,7 @@ pub const ResourceGenStep = struct {
var writer = self.resources.writer(); var writer = self.resources.writer();
writer.print("pub const {s} = @embedFile(\"", .{name}) catch unreachable; writer.print("pub const {s} = @embedFile(\"", .{name}) catch unreachable;
self.renderPath(shader_out_path, writer); renderPath(shader_out_path, writer);
writer.writeAll("\");\n") catch unreachable; writer.writeAll("\");\n") catch unreachable;
} }

View File

@@ -123,7 +123,7 @@ pub const GraphicsContext = struct {
self.vki = try InstanceDispatch.load(self.instance, c.glfwGetInstanceProcAddress); self.vki = try InstanceDispatch.load(self.instance, c.glfwGetInstanceProcAddress);
errdefer self.vki.destroyInstance(self.instance, null); errdefer self.vki.destroyInstance(self.instance, null);
self.surface = try createSurface(self.vki, self.instance, window); self.surface = try createSurface(self.instance, window);
errdefer self.vki.destroySurfaceKHR(self.instance, self.surface, null); errdefer self.vki.destroySurfaceKHR(self.instance, self.surface, null);
const candidate = try pickPhysicalDevice(self.vki, self.instance, allocator, self.surface); const candidate = try pickPhysicalDevice(self.vki, self.instance, allocator, self.surface);
@@ -182,7 +182,7 @@ pub const Queue = struct {
} }
}; };
fn createSurface(vki: InstanceDispatch, instance: vk.Instance, window: *c.GLFWwindow) !vk.SurfaceKHR { fn createSurface(instance: vk.Instance, window: *c.GLFWwindow) !vk.SurfaceKHR {
var surface: vk.SurfaceKHR = undefined; var surface: vk.SurfaceKHR = undefined;
if (c.glfwCreateWindowSurface(instance, window, null, &surface) != .success) { if (c.glfwCreateWindowSurface(instance, window, null, &surface) != .success) {
return error.SurfaceInitFailed; return error.SurfaceInitFailed;

View File

@@ -78,7 +78,7 @@ pub fn main() !void {
const render_pass = try createRenderPass(&gc, swapchain); const render_pass = try createRenderPass(&gc, swapchain);
defer gc.vkd.destroyRenderPass(gc.dev, render_pass, null); defer gc.vkd.destroyRenderPass(gc.dev, render_pass, null);
var pipeline = try createPipeline(&gc, extent, pipeline_layout, render_pass); var pipeline = try createPipeline(&gc, pipeline_layout, render_pass);
defer gc.vkd.destroyPipeline(gc.dev, pipeline, null); defer gc.vkd.destroyPipeline(gc.dev, pipeline, null);
var framebuffers = try createFramebuffers(&gc, allocator, render_pass, swapchain); var framebuffers = try createFramebuffers(&gc, allocator, render_pass, swapchain);
@@ -104,7 +104,7 @@ pub fn main() !void {
defer gc.vkd.freeMemory(gc.dev, memory, null); defer gc.vkd.freeMemory(gc.dev, memory, null);
try gc.vkd.bindBufferMemory(gc.dev, buffer, memory, 0); try gc.vkd.bindBufferMemory(gc.dev, buffer, memory, 0);
try uploadVertices(&gc, pool, buffer, memory); try uploadVertices(&gc, pool, buffer);
var cmdbufs = try createCommandBuffers( var cmdbufs = try createCommandBuffers(
&gc, &gc,
@@ -157,7 +157,7 @@ pub fn main() !void {
try swapchain.waitForAllFences(); try swapchain.waitForAllFences();
} }
fn uploadVertices(gc: *const GraphicsContext, pool: vk.CommandPool, buffer: vk.Buffer, memory: vk.DeviceMemory) !void { fn uploadVertices(gc: *const GraphicsContext, pool: vk.CommandPool, buffer: vk.Buffer) !void {
const staging_buffer = try gc.vkd.createBuffer(gc.dev, .{ const staging_buffer = try gc.vkd.createBuffer(gc.dev, .{
.flags = .{}, .flags = .{},
.size = @sizeOf(@TypeOf(vertices)), .size = @sizeOf(@TypeOf(vertices)),
@@ -368,7 +368,6 @@ fn createRenderPass(gc: *const GraphicsContext, swapchain: Swapchain) !vk.Render
fn createPipeline( fn createPipeline(
gc: *const GraphicsContext, gc: *const GraphicsContext,
extent: vk.Extent2D,
layout: vk.PipelineLayout, layout: vk.PipelineLayout,
render_pass: vk.RenderPass, render_pass: vk.RenderPass,
) !vk.Pipeline { ) !vk.Pipeline {

View File

@@ -2,6 +2,41 @@ const std = @import("std");
const mem = std.mem; const mem = std.mem;
const Allocator = mem.Allocator; const Allocator = mem.Allocator;
pub fn isZigPrimitiveType(name: []const u8) bool {
if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) {
for (name[1..]) |c| {
switch (c) {
'0'...'9' => {},
else => return false,
}
}
return true;
}
const primitives = [_][]const u8{ "void", "comptime_float", "comptime_int", "bool", "isize", "usize", "f16", "f32", "f64", "f128", "c_longdouble", "noreturn", "type", "anyerror", "c_short", "c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_longlong", "c_ulonglong" };
for (primitives) |reserved| {
if (mem.eql(u8, reserved, name)) {
return true;
}
}
return false;
}
fn needZigEscape(name: []const u8) bool {
return !std.zig.fmt.isValidId(name) or isZigPrimitiveType(name);
}
pub fn writeIdentifier(out: anytype, id: []const u8) !void {
// https://github.com/ziglang/zig/issues/2897
if (isZigPrimitiveType(id)) {
try out.print("{s}_", .{id});
} else {
try out.print("{}", .{std.zig.fmtId(id)});
}
}
pub const CaseStyle = enum { pub const CaseStyle = enum {
snake, snake,
screaming_snake, screaming_snake,
@@ -138,14 +173,10 @@ pub const IdRenderer = struct {
} }
} }
pub fn render(self: IdRenderer, out: anytype, id: []const u8) !void {
try out.print("{}", .{std.zig.fmtId(id)});
}
pub fn renderFmt(self: *IdRenderer, out: anytype, comptime fmt: []const u8, args: anytype) !void { pub fn renderFmt(self: *IdRenderer, out: anytype, comptime fmt: []const u8, args: anytype) !void {
self.text_cache.items.len = 0; self.text_cache.items.len = 0;
try std.fmt.format(self.text_cache.writer(), fmt, args); try std.fmt.format(self.text_cache.writer(), fmt, args);
try out.print("{}", .{std.zig.fmtId(self.text_cache.items)}); try writeIdentifier(out, self.text_cache.items);
} }
pub fn renderWithCase(self: *IdRenderer, out: anytype, case_style: CaseStyle, id: []const u8) !void { pub fn renderWithCase(self: *IdRenderer, out: anytype, case_style: CaseStyle, id: []const u8) !void {
@@ -162,7 +193,7 @@ pub const IdRenderer = struct {
.camel => try self.renderCamel(false, adjusted_id, tag), .camel => try self.renderCamel(false, adjusted_id, tag),
} }
try out.print("{}", .{std.zig.fmtId(self.text_cache.items)}); try writeIdentifier(out, self.text_cache.items);
} }
pub fn getAuthorTag(self: IdRenderer, id: []const u8) ?[]const u8 { pub fn getAuthorTag(self: IdRenderer, id: []const u8) ?[]const u8 {

View File

@@ -1,6 +1,5 @@
pub const generateVk = @import("vulkan/generator.zig").generate; pub const generateVk = @import("vulkan/generator.zig").generate;
pub const VkGenerateStep = @import("vulkan/build_integration.zig").GenerateStep; pub const VkGenerateStep = @import("vulkan/build_integration.zig").GenerateStep;
pub const generateSpirv = @import("spirv/generator.zig").generate;
pub const ShaderCompileStep = @import("build_integration.zig").ShaderCompileStep; pub const ShaderCompileStep = @import("build_integration.zig").ShaderCompileStep;
test "main" { test "main" {

View File

@@ -5,7 +5,6 @@ const usage = "Usage: {s} [-h|--help] <spec xml path> <output zig source>\n";
pub fn main() !void { pub fn main() !void {
const stderr = std.io.getStdErr(); const stderr = std.io.getStdErr();
const stdout = std.io.getStdOut();
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit(); defer arena.deinit();

View File

@@ -514,7 +514,7 @@ pub fn parseVersion(xctok: *XmlCTokenizer) ![4][]const u8 {
return error.InvalidVersion; return error.InvalidVersion;
} }
const name = try xctok.expect(.name); _ = try xctok.expect(.name);
const vk_make_version = try xctok.expect(.type_name); const vk_make_version = try xctok.expect(.type_name);
if (!mem.eql(u8, vk_make_version.text, "VK_MAKE_API_VERSION")) { if (!mem.eql(u8, vk_make_version.text, "VK_MAKE_API_VERSION")) {
return error.NotVersion; return error.NotVersion;

View File

@@ -171,7 +171,7 @@ pub const Generator = struct {
if (e.is_bitmask and seen_bits.get(decl.name) == null) if (e.is_bitmask and seen_bits.get(decl.name) == null)
continue; continue;
}, },
else => {} else => {},
} }
self.registry.decls[i] = decl; self.registry.decls[i] = decl;
i += 1; i += 1;

View File

@@ -74,7 +74,7 @@ fn parseTypes(allocator: *Allocator, out: []registry.Declaration, types_elem: *x
} else if (mem.eql(u8, category, "funcpointer")) { } else if (mem.eql(u8, category, "funcpointer")) {
break :blk try parseFuncPointer(allocator, ty); break :blk try parseFuncPointer(allocator, ty);
} else if (mem.eql(u8, category, "enum")) { } else if (mem.eql(u8, category, "enum")) {
break :blk (try parseEnumAlias(allocator, ty)) orelse continue; break :blk (try parseEnumAlias(ty)) orelse continue;
} }
continue; continue;
@@ -297,7 +297,7 @@ fn parsePointerMeta(fields: Fields, type_info: *registry.TypeInfo, elem: *xml.El
} }
} }
fn parseEnumAlias(allocator: *Allocator, elem: *xml.Element) !?registry.Declaration { fn parseEnumAlias(elem: *xml.Element) !?registry.Declaration {
if (elem.getAttribute("alias")) |alias| { if (elem.getAttribute("alias")) |alias| {
const name = elem.getAttribute("name") orelse return error.InvalidRegistry; const name = elem.getAttribute("name") orelse return error.InvalidRegistry;
return registry.Declaration{ return registry.Declaration{

View File

@@ -40,7 +40,7 @@ const preamble =
\\ return fromInt(toInt(lhs) & toInt(rhs)); \\ return fromInt(toInt(lhs) & toInt(rhs));
\\ } \\ }
\\ pub fn complement(self: FlagsType) FlagsType { \\ pub fn complement(self: FlagsType) FlagsType {
\\ return fromInt(~toInt(lhs)); \\ return fromInt(~toInt(self));
\\ } \\ }
\\ pub fn subtract(lhs: FlagsType, rhs: FlagsType) FlagsType { \\ pub fn subtract(lhs: FlagsType, rhs: FlagsType) FlagsType {
\\ return fromInt(toInt(lhs) & toInt(rhs.complement())); \\ return fromInt(toInt(lhs) & toInt(rhs.complement()));
@@ -214,7 +214,7 @@ fn Renderer(comptime WriterType: type) type {
} }
fn writeIdentifier(self: Self, id: []const u8) !void { fn writeIdentifier(self: Self, id: []const u8) !void {
try self.id_renderer.render(self.writer, id); try id_render.writeIdentifier(self.writer, id);
} }
fn writeIdentifierWithCase(self: *Self, case: CaseStyle, id: []const u8) !void { fn writeIdentifierWithCase(self: *Self, case: CaseStyle, id: []const u8) !void {
@@ -242,7 +242,7 @@ fn Renderer(comptime WriterType: type) type {
} }
} }
fn extractBitflagFieldName(self: Self, bitflag_name: BitflagName, field_name: []const u8) ![]const u8 { fn extractBitflagFieldName(bitflag_name: BitflagName, field_name: []const u8) ![]const u8 {
var flag_it = id_render.SegmentIterator.init(bitflag_name.base_name); var flag_it = id_render.SegmentIterator.init(bitflag_name.base_name);
var field_it = id_render.SegmentIterator.init(field_name); var field_it = id_render.SegmentIterator.init(field_name);
@@ -295,16 +295,6 @@ fn Renderer(comptime WriterType: type) type {
return mem.endsWith(u8, base_name, "Flags"); return mem.endsWith(u8, base_name, "Flags");
} }
fn containerHasField(self: Self, container: *const reg.Container, field_name: []const u8) bool {
for (container.fields) |field| {
if (mem.eql(u8, field, field_name)) {
return true;
}
}
return false;
}
fn isInOutPointer(self: Self, ptr: reg.Pointer) !bool { fn isInOutPointer(self: Self, ptr: reg.Pointer) !bool {
if (ptr.child.* != .name) { if (ptr.child.* != .name) {
return false; return false;
@@ -373,7 +363,7 @@ fn Renderer(comptime WriterType: type) type {
} }
}, },
.name => |name| { .name => |name| {
if ((try self.extractBitflagName(param.param_type.name)) != null or self.isFlags(param.param_type.name)) { if ((try self.extractBitflagName(name)) != null or self.isFlags(name)) {
return .bitflags; return .bitflags;
} }
}, },
@@ -387,7 +377,7 @@ fn Renderer(comptime WriterType: type) type {
return .other; return .other;
} }
fn classifyCommandDispatch(self: Self, name: []const u8, command: reg.Command) CommandDispatchType { fn classifyCommandDispatch(name: []const u8, command: reg.Command) CommandDispatchType {
const device_handles = std.ComptimeStringMap(void, .{ const device_handles = std.ComptimeStringMap(void, .{
.{ "VkDevice", {} }, .{ "VkDevice", {} },
.{ "VkCommandBuffer", {} }, .{ "VkCommandBuffer", {} },
@@ -710,37 +700,6 @@ fn Renderer(comptime WriterType: type) type {
try self.writeIdentifierWithCase(.snake, try self.extractEnumFieldName(name, field_name)); try self.writeIdentifierWithCase(.snake, try self.extractEnumFieldName(name, field_name));
} }
fn renderEnumerationValue(self: *Self, enum_name: []const u8, enumeration: reg.Enum, value: reg.Enum.Value) !void {
var current_value = value;
var maybe_alias_of: ?[]const u8 = null;
while (true) {
switch (current_value) {
.int => |int| try self.writer.print(" = {}, ", .{int}),
.bitpos => |pos| try self.writer.print(" = 1 << {}, ", .{pos}),
.bit_vector => |bv| try self.writer.print("= 0x{X}, ", .{bv}),
.alias => |alias| {
// Find the alias
current_value = for (enumeration.fields) |field| {
if (mem.eql(u8, field.name, alias.name)) {
maybe_alias_of = field.name;
break field.value;
}
} else return error.InvalidRegistry; // There is no alias
continue;
},
}
break;
}
if (maybe_alias_of) |alias_of| {
try self.writer.writeAll("// alias of ");
try self.renderEnumFieldName(enum_name, alias_of);
try self.writer.writeByte('\n');
}
}
fn renderEnumeration(self: *Self, name: []const u8, enumeration: reg.Enum) !void { fn renderEnumeration(self: *Self, name: []const u8, enumeration: reg.Enum) !void {
if (enumeration.is_bitmask) { if (enumeration.is_bitmask) {
try self.renderBitmaskBits(name, enumeration); try self.renderBitmaskBits(name, enumeration);
@@ -749,17 +708,37 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll("pub const "); try self.writer.writeAll("pub const ");
try self.renderName(name); try self.renderName(name);
try self.writer.writeAll(" = extern enum(i32) {"); try self.writer.writeAll(" = enum(c_int) {");
for (enumeration.fields) |field| { for (enumeration.fields) |field| {
if (field.value == .alias and field.value.alias.is_compat_alias) if (field.value == .alias)
continue; continue;
try self.renderEnumFieldName(name, field.name); try self.renderEnumFieldName(name, field.name);
try self.renderEnumerationValue(name, enumeration, field.value); switch (field.value) {
.int => |int| try self.writer.print(" = {}, ", .{int}),
.bitpos => |pos| try self.writer.print(" = 1 << {}, ", .{pos}),
.bit_vector => |bv| try self.writer.print("= 0x{X}, ", .{bv}),
.alias => unreachable,
}
} }
try self.writer.writeAll("_,};\n"); try self.writer.writeAll("_,");
for (enumeration.fields) |field| {
if (field.value != .alias or field.value.alias.is_compat_alias)
continue;
try self.writer.writeAll("pub const ");
try self.renderEnumFieldName(name, field.name);
try self.writer.writeAll(" = ");
try self.renderName(name);
try self.writer.writeByte('.');
try self.renderEnumFieldName(name, field.value.alias.name);
try self.writer.writeAll(";\n");
}
try self.writer.writeAll("};\n");
} }
fn bitmaskFlagsType(bitwidth: u8) ![]const u8 { fn bitmaskFlagsType(bitwidth: u8) ![]const u8 {
@@ -797,7 +776,7 @@ fn Renderer(comptime WriterType: type) type {
for (flags_by_bitpos[0..bits.bitwidth]) |maybe_flag_name, bitpos| { for (flags_by_bitpos[0..bits.bitwidth]) |maybe_flag_name, bitpos| {
if (maybe_flag_name) |flag_name| { if (maybe_flag_name) |flag_name| {
const field_name = try self.extractBitflagFieldName(bitflag_name, flag_name); const field_name = try extractBitflagFieldName(bitflag_name, flag_name);
try self.writeIdentifierWithCase(.snake, field_name); try self.writeIdentifierWithCase(.snake, field_name);
} else { } else {
try self.writer.print("_reserved_bit_{}", .{bitpos}); try self.writer.print("_reserved_bit_{}", .{bitpos});
@@ -843,7 +822,7 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll("pub const "); try self.writer.writeAll("pub const ");
try self.renderName(name); try self.renderName(name);
try self.writer.print(" = extern enum({s}) {{null_handle = 0, _}};\n", .{backing_type}); try self.writer.print(" = enum({s}) {{null_handle = 0, _}};\n", .{backing_type});
} }
fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void { fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void {
@@ -948,7 +927,7 @@ fn Renderer(comptime WriterType: type) type {
for (self.registry.decls) |decl| { for (self.registry.decls) |decl| {
if (decl.decl_type == .command) { if (decl.decl_type == .command) {
const command = decl.decl_type.command; const command = decl.decl_type.command;
if (self.classifyCommandDispatch(decl.name, command) == dispatch_type) { if (classifyCommandDispatch(decl.name, command) == dispatch_type) {
try self.renderWrapper(decl.name, decl.decl_type.command); try self.renderWrapper(decl.name, decl.decl_type.command);
} }
} }
@@ -1208,13 +1187,13 @@ fn Renderer(comptime WriterType: type) type {
try self.writer.writeAll(") {\n"); try self.writer.writeAll(") {\n");
for (command.success_codes) |success| { for (command.success_codes) |success| {
try self.writer.writeByte('.'); try self.writer.writeAll("Result.");
try self.renderEnumFieldName("VkResult", success); try self.renderEnumFieldName("VkResult", success);
try self.writer.writeAll(" => {},"); try self.writer.writeAll(" => {},");
} }
for (command.error_codes) |err| { for (command.error_codes) |err| {
try self.writer.writeByte('.'); try self.writer.writeAll("Result.");
try self.renderEnumFieldName("VkResult", err); try self.renderEnumFieldName("VkResult", err);
try self.writer.writeAll(" => return error."); try self.writer.writeAll(" => return error.");
try self.renderResultAsErrorName(err); try self.renderResultAsErrorName(err);