From b3c71d69ea87da197f94f3f897efdbdd88f4a6e0 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 24 Jun 2021 02:11:36 +0200 Subject: [PATCH] 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. --- build.zig | 4 +- examples/graphics_context.zig | 4 +- examples/triangle.zig | 7 ++- generator/id_render.zig | 43 +++++++++++++--- generator/index.zig | 1 - generator/main.zig | 1 - generator/vulkan/c_parse.zig | 2 +- generator/vulkan/generator.zig | 2 +- generator/vulkan/parse.zig | 4 +- generator/vulkan/render.zig | 89 +++++++++++++--------------------- 10 files changed, 82 insertions(+), 75 deletions(-) diff --git a/build.zig b/build.zig index 93b7ffb..acf2791 100644 --- a/build.zig +++ b/build.zig @@ -34,7 +34,7 @@ pub const ResourceGenStep = struct { 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 }; var i: usize = 0; while (std.mem.indexOfAnyPos(u8, path, i, separators)) |j| { @@ -55,7 +55,7 @@ pub const ResourceGenStep = struct { var writer = self.resources.writer(); 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; } diff --git a/examples/graphics_context.zig b/examples/graphics_context.zig index 89e2152..389088d 100644 --- a/examples/graphics_context.zig +++ b/examples/graphics_context.zig @@ -123,7 +123,7 @@ pub const GraphicsContext = struct { self.vki = try InstanceDispatch.load(self.instance, c.glfwGetInstanceProcAddress); 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); 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; if (c.glfwCreateWindowSurface(instance, window, null, &surface) != .success) { return error.SurfaceInitFailed; diff --git a/examples/triangle.zig b/examples/triangle.zig index 69b6d74..f357a24 100644 --- a/examples/triangle.zig +++ b/examples/triangle.zig @@ -78,7 +78,7 @@ pub fn main() !void { const render_pass = try createRenderPass(&gc, swapchain); 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); 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); try gc.vkd.bindBufferMemory(gc.dev, buffer, memory, 0); - try uploadVertices(&gc, pool, buffer, memory); + try uploadVertices(&gc, pool, buffer); var cmdbufs = try createCommandBuffers( &gc, @@ -157,7 +157,7 @@ pub fn main() !void { 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, .{ .flags = .{}, .size = @sizeOf(@TypeOf(vertices)), @@ -368,7 +368,6 @@ fn createRenderPass(gc: *const GraphicsContext, swapchain: Swapchain) !vk.Render fn createPipeline( gc: *const GraphicsContext, - extent: vk.Extent2D, layout: vk.PipelineLayout, render_pass: vk.RenderPass, ) !vk.Pipeline { diff --git a/generator/id_render.zig b/generator/id_render.zig index e3c7135..29b10a2 100644 --- a/generator/id_render.zig +++ b/generator/id_render.zig @@ -2,6 +2,41 @@ const std = @import("std"); const mem = std.mem; 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 { 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 { self.text_cache.items.len = 0; 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 { @@ -162,7 +193,7 @@ pub const IdRenderer = struct { .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 { diff --git a/generator/index.zig b/generator/index.zig index b87c685..05ca2fe 100644 --- a/generator/index.zig +++ b/generator/index.zig @@ -1,6 +1,5 @@ pub const generateVk = @import("vulkan/generator.zig").generate; 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; test "main" { diff --git a/generator/main.zig b/generator/main.zig index 9e817bf..569928d 100644 --- a/generator/main.zig +++ b/generator/main.zig @@ -5,7 +5,6 @@ const usage = "Usage: {s} [-h|--help] \n"; pub fn main() !void { const stderr = std.io.getStdErr(); - const stdout = std.io.getStdOut(); var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); diff --git a/generator/vulkan/c_parse.zig b/generator/vulkan/c_parse.zig index 61782d0..5d9d552 100644 --- a/generator/vulkan/c_parse.zig +++ b/generator/vulkan/c_parse.zig @@ -514,7 +514,7 @@ pub fn parseVersion(xctok: *XmlCTokenizer) ![4][]const u8 { return error.InvalidVersion; } - const name = try xctok.expect(.name); + _ = try xctok.expect(.name); const vk_make_version = try xctok.expect(.type_name); if (!mem.eql(u8, vk_make_version.text, "VK_MAKE_API_VERSION")) { return error.NotVersion; diff --git a/generator/vulkan/generator.zig b/generator/vulkan/generator.zig index b0c28d1..10bc4ce 100644 --- a/generator/vulkan/generator.zig +++ b/generator/vulkan/generator.zig @@ -171,7 +171,7 @@ pub const Generator = struct { if (e.is_bitmask and seen_bits.get(decl.name) == null) continue; }, - else => {} + else => {}, } self.registry.decls[i] = decl; i += 1; diff --git a/generator/vulkan/parse.zig b/generator/vulkan/parse.zig index fc0065c..789f966 100644 --- a/generator/vulkan/parse.zig +++ b/generator/vulkan/parse.zig @@ -74,7 +74,7 @@ fn parseTypes(allocator: *Allocator, out: []registry.Declaration, types_elem: *x } else if (mem.eql(u8, category, "funcpointer")) { break :blk try parseFuncPointer(allocator, ty); } else if (mem.eql(u8, category, "enum")) { - break :blk (try parseEnumAlias(allocator, ty)) orelse continue; + break :blk (try parseEnumAlias(ty)) orelse 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| { const name = elem.getAttribute("name") orelse return error.InvalidRegistry; return registry.Declaration{ diff --git a/generator/vulkan/render.zig b/generator/vulkan/render.zig index 6351f58..b6efd3b 100644 --- a/generator/vulkan/render.zig +++ b/generator/vulkan/render.zig @@ -40,7 +40,7 @@ const preamble = \\ return fromInt(toInt(lhs) & toInt(rhs)); \\ } \\ pub fn complement(self: FlagsType) FlagsType { - \\ return fromInt(~toInt(lhs)); + \\ return fromInt(~toInt(self)); \\ } \\ pub fn subtract(lhs: FlagsType, rhs: FlagsType) FlagsType { \\ 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 { - 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 { @@ -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 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"); } - 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 { if (ptr.child.* != .name) { return false; @@ -373,7 +363,7 @@ fn Renderer(comptime WriterType: type) type { } }, .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; } }, @@ -387,7 +377,7 @@ fn Renderer(comptime WriterType: type) type { 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, .{ .{ "VkDevice", {} }, .{ "VkCommandBuffer", {} }, @@ -710,37 +700,6 @@ fn Renderer(comptime WriterType: type) type { 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 { if (enumeration.is_bitmask) { try self.renderBitmaskBits(name, enumeration); @@ -749,17 +708,37 @@ fn Renderer(comptime WriterType: type) type { try self.writer.writeAll("pub const "); try self.renderName(name); - try self.writer.writeAll(" = extern enum(i32) {"); + try self.writer.writeAll(" = enum(c_int) {"); for (enumeration.fields) |field| { - if (field.value == .alias and field.value.alias.is_compat_alias) + if (field.value == .alias) continue; 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 { @@ -797,7 +776,7 @@ fn Renderer(comptime WriterType: type) type { for (flags_by_bitpos[0..bits.bitwidth]) |maybe_flag_name, bitpos| { 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); } else { 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.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 { @@ -948,7 +927,7 @@ fn Renderer(comptime WriterType: type) type { for (self.registry.decls) |decl| { if (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); } } @@ -1208,13 +1187,13 @@ fn Renderer(comptime WriterType: type) type { try self.writer.writeAll(") {\n"); for (command.success_codes) |success| { - try self.writer.writeByte('.'); + try self.writer.writeAll("Result."); try self.renderEnumFieldName("VkResult", success); try self.writer.writeAll(" => {},"); } for (command.error_codes) |err| { - try self.writer.writeByte('.'); + try self.writer.writeAll("Result."); try self.renderEnumFieldName("VkResult", err); try self.writer.writeAll(" => return error."); try self.renderResultAsErrorName(err);