spirv: add zig-specific ext inst

This may be removed again in the future...
This commit is contained in:
Robin Voetter 2024-03-11 23:23:02 +01:00
parent e566158acf
commit 20d7bb68ac
No known key found for this signature in database
3 changed files with 69 additions and 23 deletions

View File

@ -0,0 +1,13 @@
{
"version": 0,
"revision": 0,
"instructions": [
{
"opname": "InvocationGlobal",
"opcode": 0,
"operands": [
{ "kind": "IdRef", "name": "initializer function" }
]
}
]
}

View File

@ -102,6 +102,7 @@ pub const Class = enum {
}; };
pub const OperandKind = enum { pub const OperandKind = enum {
Opcode,
ImageOperands, ImageOperands,
FPFastMathMode, FPFastMathMode,
SelectionControl, SelectionControl,
@ -187,6 +188,7 @@ pub const OperandKind = enum {
pub fn category(self: OperandKind) OperandCategory { pub fn category(self: OperandKind) OperandCategory {
return switch (self) { return switch (self) {
.Opcode => .literal,
.ImageOperands => .bit_enum, .ImageOperands => .bit_enum,
.FPFastMathMode => .bit_enum, .FPFastMathMode => .bit_enum,
.SelectionControl => .bit_enum, .SelectionControl => .bit_enum,
@ -273,6 +275,7 @@ pub const OperandKind = enum {
} }
pub fn enumerants(self: OperandKind) []const Enumerant { pub fn enumerants(self: OperandKind) []const Enumerant {
return switch (self) { return switch (self) {
.Opcode => unreachable,
.ImageOperands => &[_]Enumerant{ .ImageOperands => &[_]Enumerant{
.{ .name = "Bias", .value = 0x0001, .parameters = &[_]OperandKind{.IdRef} }, .{ .name = "Bias", .value = 0x0001, .parameters = &[_]OperandKind{.IdRef} },
.{ .name = "Lod", .value = 0x0002, .parameters = &[_]OperandKind{.IdRef} }, .{ .name = "Lod", .value = 0x0002, .parameters = &[_]OperandKind{.IdRef} },
@ -2104,7 +2107,6 @@ pub const Opcode = enum(u16) {
OpGroupLogicalXorKHR = 6408, OpGroupLogicalXorKHR = 6408,
OpMaskedGatherINTEL = 6428, OpMaskedGatherINTEL = 6428,
OpMaskedScatterINTEL = 6429, OpMaskedScatterINTEL = 6429,
pub const OpSDotKHR = Opcode.OpSDot; pub const OpSDotKHR = Opcode.OpSDot;
pub const OpUDotKHR = Opcode.OpUDot; pub const OpUDotKHR = Opcode.OpUDot;
pub const OpSUDotKHR = Opcode.OpSUDot; pub const OpSUDotKHR = Opcode.OpSUDot;
@ -5278,6 +5280,7 @@ pub const InstructionSet = enum {
@"nonsemantic.debugprintf", @"nonsemantic.debugprintf",
@"spv-amd-shader-explicit-vertex-parameter", @"spv-amd-shader-explicit-vertex-parameter",
@"nonsemantic.debugbreak", @"nonsemantic.debugbreak",
zig,
pub fn instructions(self: InstructionSet) []const Instruction { pub fn instructions(self: InstructionSet) []const Instruction {
return switch (self) { return switch (self) {
@ -16505,6 +16508,15 @@ pub const InstructionSet = enum {
.operands = &[_]Operand{}, .operands = &[_]Operand{},
}, },
}, },
.zig => &[_]Instruction{
.{
.name = "InvocationGlobal",
.opcode = 0,
.operands = &[_]Operand{
.{ .kind = .IdRef, .quantifier = .required },
},
},
},
}; };
} }
}; };

View File

@ -48,16 +48,13 @@ pub fn main() !void {
const a = arena.allocator(); const a = arena.allocator();
const args = try std.process.argsAlloc(a); const args = try std.process.argsAlloc(a);
if (args.len != 2) { if (args.len != 3) {
usageAndExit(args[0], 1); usageAndExit(args[0], 1);
} }
const json_path = try std.fs.path.join(a, &.{ args[1], "include/spirv/unified1/" }); 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 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"); const core_spec = try readRegistry(CoreRegistry, a, dir, "spirv.core.grammar.json");
std.sort.block(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); std.sort.block(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt);
@ -65,24 +62,35 @@ pub fn main() !void {
var it = dir.iterate(); var it = dir.iterate();
while (try it.next()) |entry| { while (try it.next()) |entry| {
if (entry.kind != .file or !std.mem.startsWith(u8, entry.name, "extinst.")) { if (entry.kind != .file) {
continue; continue;
} }
std.debug.assert(std.mem.endsWith(u8, entry.name, ".grammar.json")); try readExtRegistry(&exts, a, dir, entry.name);
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, std.fs.cwd(), args[2]);
var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); var bw = std.io.bufferedWriter(std.io.getStdOut().writer());
try render(bw.writer(), a, core_spec, exts.items); try render(bw.writer(), a, core_spec, exts.items);
try bw.flush(); 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 { 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)); const spec = try dir.readFileAlloc(a, path, std.math.maxInt(usize));
// Required for json parsing. // Required for json parsing.
@ -374,14 +382,19 @@ fn renderInstructionClass(writer: anytype, class: []const u8) !void {
} }
fn renderOperandKind(writer: anytype, operands: []const OperandKind) !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| { for (operands) |operand| {
try writer.print("{},\n", .{std.zig.fmtId(operand.kind)}); try writer.print("{},\n", .{std.zig.fmtId(operand.kind)});
} }
try writer.writeAll( try writer.writeAll(
\\ \\
\\pub fn category(self: OperandKind) OperandCategory { \\pub fn category(self: OperandKind) OperandCategory {
\\return switch (self) { \\ return switch (self) {
\\ .Opcode => .literal,
\\ \\
); );
for (operands) |operand| { 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.print(".{} => .{s},\n", .{ std.zig.fmtId(operand.kind), cat });
} }
try writer.writeAll( try writer.writeAll(
\\}; \\ };
\\} \\}
\\pub fn enumerants(self: OperandKind) []const Enumerant { \\pub fn enumerants(self: OperandKind) []const Enumerant {
\\return switch (self) { \\ return switch (self) {
\\ .Opcode => unreachable,
\\ \\
); );
for (operands) |operand| { for (operands) |operand| {
@ -483,7 +497,9 @@ fn renderOpcodes(
try writer.print("{} = {},\n", .{ std.zig.fmtId(inst.opname), inst.opcode }); try writer.print("{} = {},\n", .{ std.zig.fmtId(inst.opname), inst.opcode });
} }
try writer.writeByte('\n'); try writer.writeAll(
\\
);
for (aliases.items) |alias| { for (aliases.items) |alias| {
try writer.print("pub const {} = Opcode.{};\n", .{ try writer.print("pub const {} = Opcode.{};\n", .{
@ -495,7 +511,7 @@ fn renderOpcodes(
try writer.writeAll( try writer.writeAll(
\\ \\
\\pub fn Operands(comptime self: Opcode) type { \\pub fn Operands(comptime self: Opcode) type {
\\return switch (self) { \\ return switch (self) {
\\ \\
); );
@ -505,10 +521,10 @@ fn renderOpcodes(
} }
try writer.writeAll( try writer.writeAll(
\\}; \\ };
\\} \\}
\\pub fn class(self: Opcode) Class { \\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");
} }
try writer.writeAll("};\n}\n};\n"); try writer.writeAll(
\\ };
\\}
\\};
\\
);
} }
fn renderOperandKinds( fn renderOperandKinds(
@ -844,7 +865,7 @@ fn parseHexInt(text: []const u8) !u31 {
fn usageAndExit(arg0: []const u8, code: u8) noreturn { fn usageAndExit(arg0: []const u8, code: u8) noreturn {
std.io.getStdErr().writer().print( std.io.getStdErr().writer().print(
\\Usage: {s} <SPIRV-Headers repository path> \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json>
\\ \\
\\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers
\\repository. The result, printed to stdout, should be used to update \\repository. The result, printed to stdout, should be used to update