diff --git a/generator/spirv/generator.zig b/generator/spirv/generator.zig index 031bcf4..ea7d97b 100644 --- a/generator/spirv/generator.zig +++ b/generator/spirv/generator.zig @@ -3,12 +3,46 @@ const reg = @import("registry.zig"); const renderSpirv = @import("render.zig").render; const Allocator = std.mem.Allocator; +pub fn mergeRegistries(allocator: *Allocator, core: reg.CoreRegistry, extensions: []const reg.ExtensionRegistry) !reg.CoreRegistry { + var merged = core; + + var total_instructions = core.instructions.len; + var total_operand_kinds = core.operand_kinds.len; + for (extensions) |ext| { + total_instructions += ext.instructions.len; + total_operand_kinds += ext.operand_kinds.len; + } + + merged.instructions = try allocator.alloc(reg.Instruction, total_instructions); + merged.operand_kinds = try allocator.alloc(reg.OperandKind, total_operand_kinds); + + // Assume the core and extension registries contain no common operand kinds and instructions. + for (core.instructions) |inst, i| merged.instructions[i] = inst; + for (core.operand_kinds) |operand_kind, i| merged.operand_kinds[i] = operand_kind; + + var inst_i = core.instructions.len; + var oper_i = core.operand_kinds.len; + + for (extensions) |ext| { + for (ext.instructions) |inst| { + merged.instructions[inst_i] = inst; + inst_i += 1; + } + + for (ext.operand_kinds) |operand_kind| { + merged.operand_kinds[oper_i] = operand_kind; + oper_i += 1; + } + } + + return merged; +} + pub fn generate(allocator: *Allocator, spec_jsons: []const []const u8, writer: anytype) !void { var arena = std.heap.ArenaAllocator.init(allocator); defer arena.deinit(); - // Only one of the passed specs may be core (and one of them _must_ be core) - - // the others must be exensions. + // Exactly one of the passed specs must be core - the others must be exensions. var core_registry: reg.CoreRegistry = undefined; const num_ext_registries = spec_jsons.len - 1; const ext_registries = try arena.allocator.alloc(reg.ExtensionRegistry, num_ext_registries); @@ -34,5 +68,6 @@ pub fn generate(allocator: *Allocator, spec_jsons: []const []const u8, writer: a return error.MultipleCoreRegistries; } - try renderSpirv(writer, allocator, &core_registry, ext_registries); + const merged = try mergeRegistries(&arena.allocator, core_registry, ext_registries); + try renderSpirv(writer, &arena.allocator, &merged); } diff --git a/generator/spirv/render.zig b/generator/spirv/render.zig index d529d1c..1e75918 100644 --- a/generator/spirv/render.zig +++ b/generator/spirv/render.zig @@ -21,8 +21,7 @@ fn Renderer(comptime WriterType: type) type { writer: WriterType, allocator: *Allocator, - core: *const reg.CoreRegistry, - extensions: []const reg.ExtensionRegistry, + registry: *const reg.CoreRegistry, id_renderer: IdRenderer, fn deinit(self: Self) void { @@ -35,13 +34,12 @@ fn Renderer(comptime WriterType: type) type { }; } -pub fn render(writer: anytype, allocator: *Allocator, core: *const reg.CoreRegistry, extensions: []const reg.ExtensionRegistry) !void { +pub fn render(writer: anytype, allocator: *Allocator, registry: *const reg.CoreRegistry) !void { const id_renderer = IdRenderer.init(allocator, &tags); var renderer = Renderer(@TypeOf(writer)) { .writer = writer, .allocator = allocator, - .core = core, - .extensions = extensions, + .registry = registry, .id_renderer = id_renderer, }; defer renderer.deinit();