diff --git a/src/codegen/spirv/extinst.zig.grammar.json b/src/codegen/spirv/extinst.zig.grammar.json new file mode 100644 index 0000000000..70c290097e --- /dev/null +++ b/src/codegen/spirv/extinst.zig.grammar.json @@ -0,0 +1,13 @@ +{ + "version": 0, + "revision": 0, + "instructions": [ + { + "opname": "InvocationGlobal", + "opcode": 0, + "operands": [ + { "kind": "IdRef", "name": "initializer function" } + ] + } + ] +} diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig index a3da5fa2f3..a0b3048961 100644 --- a/src/codegen/spirv/spec.zig +++ b/src/codegen/spirv/spec.zig @@ -102,6 +102,7 @@ pub const Class = enum { }; pub const OperandKind = enum { + Opcode, ImageOperands, FPFastMathMode, SelectionControl, @@ -187,6 +188,7 @@ pub const OperandKind = enum { pub fn category(self: OperandKind) OperandCategory { return switch (self) { + .Opcode => .literal, .ImageOperands => .bit_enum, .FPFastMathMode => .bit_enum, .SelectionControl => .bit_enum, @@ -273,6 +275,7 @@ pub const OperandKind = enum { } pub fn enumerants(self: OperandKind) []const Enumerant { return switch (self) { + .Opcode => unreachable, .ImageOperands => &[_]Enumerant{ .{ .name = "Bias", .value = 0x0001, .parameters = &[_]OperandKind{.IdRef} }, .{ .name = "Lod", .value = 0x0002, .parameters = &[_]OperandKind{.IdRef} }, @@ -2104,7 +2107,6 @@ pub const Opcode = enum(u16) { OpGroupLogicalXorKHR = 6408, OpMaskedGatherINTEL = 6428, OpMaskedScatterINTEL = 6429, - pub const OpSDotKHR = Opcode.OpSDot; pub const OpUDotKHR = Opcode.OpUDot; pub const OpSUDotKHR = Opcode.OpSUDot; @@ -5278,6 +5280,7 @@ pub const InstructionSet = enum { @"nonsemantic.debugprintf", @"spv-amd-shader-explicit-vertex-parameter", @"nonsemantic.debugbreak", + zig, pub fn instructions(self: InstructionSet) []const Instruction { return switch (self) { @@ -16505,6 +16508,15 @@ pub const InstructionSet = enum { .operands = &[_]Operand{}, }, }, + .zig => &[_]Instruction{ + .{ + .name = "InvocationGlobal", + .opcode = 0, + .operands = &[_]Operand{ + .{ .kind = .IdRef, .quantifier = .required }, + }, + }, + }, }; } }; diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig index f449d11e01..9972fc6f5b 100644 --- a/tools/gen_spirv_spec.zig +++ b/tools/gen_spirv_spec.zig @@ -48,16 +48,13 @@ pub fn main() !void { const a = arena.allocator(); const args = try std.process.argsAlloc(a); - if (args.len != 2) { + if (args.len != 3) { usageAndExit(args[0], 1); } const json_path = try std.fs.path.join(a, &.{ args[1], "include/spirv/unified1/" }); const dir = try std.fs.cwd().openDir(json_path, .{ .iterate = true }); - // const spec_path = try std.fs.path.join(a, &.{spirv_headers_dir_path, "spirv.core.grammar.json"}); - // const core_spec = try std.fs.cwd().readFileAlloc(a, spec_path, std.math.maxInt(usize)); - const core_spec = try readRegistry(CoreRegistry, a, dir, "spirv.core.grammar.json"); std.sort.block(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); @@ -65,24 +62,35 @@ pub fn main() !void { var it = dir.iterate(); while (try it.next()) |entry| { - if (entry.kind != .file or !std.mem.startsWith(u8, entry.name, "extinst.")) { + if (entry.kind != .file) { continue; } - std.debug.assert(std.mem.endsWith(u8, entry.name, ".grammar.json")); - const name = entry.name["extinst.".len .. entry.name.len - ".grammar.json".len]; - const spec = try readRegistry(ExtensionRegistry, a, dir, entry.name); - - std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); - - try exts.append(.{ .name = try a.dupe(u8, name), .spec = spec }); + try readExtRegistry(&exts, a, dir, entry.name); } + try readExtRegistry(&exts, a, std.fs.cwd(), args[2]); + var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); try render(bw.writer(), a, core_spec, exts.items); try bw.flush(); } +fn readExtRegistry(exts: *std.ArrayList(Extension), a: Allocator, dir: std.fs.Dir, sub_path: []const u8) !void { + const filename = std.fs.path.basename(sub_path); + if (!std.mem.startsWith(u8, filename, "extinst.")) { + return; + } + + std.debug.assert(std.mem.endsWith(u8, filename, ".grammar.json")); + const name = filename["extinst.".len .. filename.len - ".grammar.json".len]; + const spec = try readRegistry(ExtensionRegistry, a, dir, sub_path); + + std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); + + try exts.append(.{ .name = try a.dupe(u8, name), .spec = spec }); +} + fn readRegistry(comptime RegistryType: type, a: Allocator, dir: std.fs.Dir, path: []const u8) !RegistryType { const spec = try dir.readFileAlloc(a, path, std.math.maxInt(usize)); // Required for json parsing. @@ -374,14 +382,19 @@ fn renderInstructionClass(writer: anytype, class: []const u8) !void { } fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { - try writer.writeAll("pub const OperandKind = enum {\n"); + try writer.writeAll( + \\pub const OperandKind = enum { + \\ Opcode, + \\ + ); for (operands) |operand| { try writer.print("{},\n", .{std.zig.fmtId(operand.kind)}); } try writer.writeAll( \\ \\pub fn category(self: OperandKind) OperandCategory { - \\return switch (self) { + \\ return switch (self) { + \\ .Opcode => .literal, \\ ); for (operands) |operand| { @@ -395,10 +408,11 @@ fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { try writer.print(".{} => .{s},\n", .{ std.zig.fmtId(operand.kind), cat }); } try writer.writeAll( - \\}; + \\ }; \\} \\pub fn enumerants(self: OperandKind) []const Enumerant { - \\return switch (self) { + \\ return switch (self) { + \\ .Opcode => unreachable, \\ ); for (operands) |operand| { @@ -483,7 +497,9 @@ fn renderOpcodes( try writer.print("{} = {},\n", .{ std.zig.fmtId(inst.opname), inst.opcode }); } - try writer.writeByte('\n'); + try writer.writeAll( + \\ + ); for (aliases.items) |alias| { try writer.print("pub const {} = Opcode.{};\n", .{ @@ -495,7 +511,7 @@ fn renderOpcodes( try writer.writeAll( \\ \\pub fn Operands(comptime self: Opcode) type { - \\return switch (self) { + \\ return switch (self) { \\ ); @@ -505,10 +521,10 @@ fn renderOpcodes( } try writer.writeAll( - \\}; + \\ }; \\} \\pub fn class(self: Opcode) Class { - \\return switch (self) { + \\ return switch (self) { \\ ); @@ -519,7 +535,12 @@ fn renderOpcodes( try writer.writeAll(",\n"); } - try writer.writeAll("};\n}\n};\n"); + try writer.writeAll( + \\ }; + \\} + \\}; + \\ + ); } fn renderOperandKinds( @@ -844,7 +865,7 @@ fn parseHexInt(text: []const u8) !u31 { fn usageAndExit(arg0: []const u8, code: u8) noreturn { std.io.getStdErr().writer().print( - \\Usage: {s} + \\Usage: {s} \\ \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers \\repository. The result, printed to stdout, should be used to update