Skip to content

Commit

Permalink
Fix a whole bunch of issues exposed by ziglang/zig#9191
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Snektron committed Jul 6, 2021
1 parent 464b787 commit 51c16b7
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 75 deletions.
4 changes: 2 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand All @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions examples/graphics_context.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 3 additions & 4 deletions examples/triangle.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -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 {
Expand Down
43 changes: 37 additions & 6 deletions generator/id_render.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion generator/index.zig
Original file line number Diff line number Diff line change
@@ -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" {
Expand Down
1 change: 0 additions & 1 deletion generator/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const usage = "Usage: {s} [-h|--help] <spec xml path> <output zig source>\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();
Expand Down
2 changes: 1 addition & 1 deletion generator/vulkan/c_parse.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion generator/vulkan/generator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions generator/vulkan/parse.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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{
Expand Down
89 changes: 34 additions & 55 deletions generator/vulkan/render.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
},
Expand All @@ -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", {} },
Expand Down Expand Up @@ -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);
Expand All @@ -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)
continue;

try self.renderEnumFieldName(name, field.name);
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("_,");

for (enumeration.fields) |field| {
if (field.value == .alias and field.value.alias.is_compat_alias)
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.renderEnumerationValue(name, enumeration, field.value);
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");
try self.writer.writeAll("};\n");
}

fn bitmaskFlagsType(bitwidth: u8) ![]const u8 {
Expand Down Expand Up @@ -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});
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 51c16b7

Please sign in to comment.