forked from mirror/vulkan-zig
Fix some allocation bugs, replace everything by arena (#18)
This commit is contained in:
@@ -9,41 +9,30 @@ const Allocator = mem.Allocator;
|
|||||||
const FeatureLevel = reg.FeatureLevel;
|
const FeatureLevel = reg.FeatureLevel;
|
||||||
|
|
||||||
const EnumFieldMerger = struct {
|
const EnumFieldMerger = struct {
|
||||||
const EnumExtensionMap = std.StringArrayHashMap(std.ArrayListUnmanaged(reg.Enum.Field));
|
const EnumExtensionMap = std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged(reg.Enum.Field));
|
||||||
const FieldSet = std.StringArrayHashMap(void);
|
const FieldSet = std.StringArrayHashMapUnmanaged(void);
|
||||||
|
|
||||||
gpa: *Allocator,
|
arena: *Allocator,
|
||||||
reg_arena: *Allocator,
|
|
||||||
registry: *reg.Registry,
|
registry: *reg.Registry,
|
||||||
enum_extensions: EnumExtensionMap,
|
enum_extensions: EnumExtensionMap,
|
||||||
field_set: FieldSet,
|
field_set: FieldSet,
|
||||||
|
|
||||||
fn init(gpa: *Allocator, reg_arena: *Allocator, registry: *reg.Registry) EnumFieldMerger {
|
fn init(arena: *Allocator, registry: *reg.Registry) EnumFieldMerger {
|
||||||
return .{
|
return .{
|
||||||
.gpa = gpa,
|
.arena = arena,
|
||||||
.reg_arena = reg_arena,
|
|
||||||
.registry = registry,
|
.registry = registry,
|
||||||
.enum_extensions = EnumExtensionMap.init(gpa),
|
.enum_extensions = .{},
|
||||||
.field_set = FieldSet.init(gpa),
|
.field_set = .{},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *EnumFieldMerger) void {
|
|
||||||
for (self.enum_extensions.values()) |*value| {
|
|
||||||
value.deinit(self.gpa);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.field_set.deinit();
|
|
||||||
self.enum_extensions.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn putEnumExtension(self: *EnumFieldMerger, enum_name: []const u8, field: reg.Enum.Field) !void {
|
fn putEnumExtension(self: *EnumFieldMerger, enum_name: []const u8, field: reg.Enum.Field) !void {
|
||||||
const res = try self.enum_extensions.getOrPut(enum_name);
|
const res = try self.enum_extensions.getOrPut(self.arena, enum_name);
|
||||||
if (!res.found_existing) {
|
if (!res.found_existing) {
|
||||||
res.value_ptr.* = std.ArrayListUnmanaged(reg.Enum.Field){};
|
res.value_ptr.* = std.ArrayListUnmanaged(reg.Enum.Field){};
|
||||||
}
|
}
|
||||||
|
|
||||||
try res.value_ptr.append(self.gpa, field);
|
try res.value_ptr.append(self.arena, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addRequires(self: *EnumFieldMerger, reqs: []const reg.Require) !void {
|
fn addRequires(self: *EnumFieldMerger, reqs: []const reg.Require) !void {
|
||||||
@@ -61,11 +50,11 @@ const EnumFieldMerger = struct {
|
|||||||
self.field_set.clearRetainingCapacity();
|
self.field_set.clearRetainingCapacity();
|
||||||
|
|
||||||
const n_fields_upper_bound = base_enum.fields.len + extensions.items.len;
|
const n_fields_upper_bound = base_enum.fields.len + extensions.items.len;
|
||||||
const new_fields = try self.reg_arena.alloc(reg.Enum.Field, n_fields_upper_bound);
|
const new_fields = try self.arena.alloc(reg.Enum.Field, n_fields_upper_bound);
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
|
||||||
for (base_enum.fields) |field| {
|
for (base_enum.fields) |field| {
|
||||||
const res = try self.field_set.getOrPut(field.name);
|
const res = try self.field_set.getOrPut(self.arena, field.name);
|
||||||
if (!res.found_existing) {
|
if (!res.found_existing) {
|
||||||
new_fields[i] = field;
|
new_fields[i] = field;
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -74,16 +63,16 @@ const EnumFieldMerger = struct {
|
|||||||
|
|
||||||
// Assume that if a field name clobbers, the value is the same
|
// Assume that if a field name clobbers, the value is the same
|
||||||
for (extensions.items) |field| {
|
for (extensions.items) |field| {
|
||||||
const res = try self.field_set.getOrPut(field.name);
|
const res = try self.field_set.getOrPut(self.arena, field.name);
|
||||||
if (!res.found_existing) {
|
if (!res.found_existing) {
|
||||||
new_fields[i] = field;
|
new_fields[i] = field;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Existing base_enum.fields was allocatued by `self.reg_arena`, so
|
// Existing base_enum.fields was allocated by `self.arena`, so
|
||||||
// it gets cleaned up whenever that is deinited.
|
// it gets cleaned up whenever that is deinited.
|
||||||
base_enum.fields = self.reg_arena.shrink(new_fields, i);
|
base_enum.fields = self.arena.shrink(new_fields, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge(self: *EnumFieldMerger) !void {
|
fn merge(self: *EnumFieldMerger) !void {
|
||||||
@@ -106,8 +95,7 @@ const EnumFieldMerger = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Generator = struct {
|
pub const Generator = struct {
|
||||||
gpa: *Allocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
reg_arena: std.heap.ArenaAllocator,
|
|
||||||
registry: reg.Registry,
|
registry: reg.Registry,
|
||||||
id_renderer: IdRenderer,
|
id_renderer: IdRenderer,
|
||||||
|
|
||||||
@@ -118,16 +106,14 @@ pub const Generator = struct {
|
|||||||
for (tags) |*tag, i| tag.* = result.registry.tags[i].name;
|
for (tags) |*tag, i| tag.* = result.registry.tags[i].name;
|
||||||
|
|
||||||
return Generator{
|
return Generator{
|
||||||
.gpa = allocator,
|
.arena = result.arena,
|
||||||
.reg_arena = result.arena,
|
|
||||||
.registry = result.registry,
|
.registry = result.registry,
|
||||||
.id_renderer = IdRenderer.init(allocator, tags),
|
.id_renderer = IdRenderer.init(allocator, tags),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: Generator) void {
|
fn deinit(self: Generator) void {
|
||||||
self.gpa.free(self.id_renderer.tags);
|
self.arena.deinit();
|
||||||
self.reg_arena.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stripFlagBits(self: Generator, name: []const u8) []const u8 {
|
fn stripFlagBits(self: Generator, name: []const u8) []const u8 {
|
||||||
@@ -142,14 +128,13 @@ pub const Generator = struct {
|
|||||||
|
|
||||||
// Solve `registry.declarations` according to `registry.extensions` and `registry.features`.
|
// Solve `registry.declarations` according to `registry.extensions` and `registry.features`.
|
||||||
fn mergeEnumFields(self: *Generator) !void {
|
fn mergeEnumFields(self: *Generator) !void {
|
||||||
var merger = EnumFieldMerger.init(self.gpa, &self.reg_arena.allocator, &self.registry);
|
var merger = EnumFieldMerger.init(&self.arena.allocator, &self.registry);
|
||||||
defer merger.deinit();
|
|
||||||
try merger.merge();
|
try merger.merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/KhronosGroup/Vulkan-Docs/pull/1556
|
// https://github.com/KhronosGroup/Vulkan-Docs/pull/1556
|
||||||
fn fixupBitFlags(self: *Generator) !void {
|
fn fixupBitFlags(self: *Generator) !void {
|
||||||
var seen_bits = std.StringArrayHashMap(void).init(&self.reg_arena.allocator);
|
var seen_bits = std.StringArrayHashMap(void).init(&self.arena.allocator);
|
||||||
defer seen_bits.deinit();
|
defer seen_bits.deinit();
|
||||||
|
|
||||||
for (self.registry.decls) |decl| {
|
for (self.registry.decls) |decl| {
|
||||||
@@ -181,7 +166,7 @@ pub const Generator = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render(self: *Generator, writer: anytype) !void {
|
fn render(self: *Generator, writer: anytype) !void {
|
||||||
try renderRegistry(writer, &self.reg_arena.allocator, &self.registry, &self.id_renderer);
|
try renderRegistry(writer, &self.arena.allocator, &self.registry, &self.id_renderer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -185,10 +185,6 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
declarations_by_name: std.StringHashMap(*const reg.DeclarationType),
|
declarations_by_name: std.StringHashMap(*const reg.DeclarationType),
|
||||||
|
|
||||||
fn init(writer: WriterType, allocator: *Allocator, registry: *const reg.Registry, id_renderer: *IdRenderer) !Self {
|
fn init(writer: WriterType, allocator: *Allocator, registry: *const reg.Registry, id_renderer: *IdRenderer) !Self {
|
||||||
const tags = try allocator.alloc([]const u8, registry.tags.len);
|
|
||||||
errdefer allocator.free(tags);
|
|
||||||
for (tags) |*tag, i| tag.* = registry.tags[i].name;
|
|
||||||
|
|
||||||
var declarations_by_name = std.StringHashMap(*const reg.DeclarationType).init(allocator);
|
var declarations_by_name = std.StringHashMap(*const reg.DeclarationType).init(allocator);
|
||||||
errdefer declarations_by_name.deinit();
|
errdefer declarations_by_name.deinit();
|
||||||
|
|
||||||
@@ -212,8 +208,6 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
|
|
||||||
fn deinit(self: *Self) void {
|
fn deinit(self: *Self) void {
|
||||||
self.declarations_by_name.deinit();
|
self.declarations_by_name.deinit();
|
||||||
self.allocator.free(self.id_renderer.tags);
|
|
||||||
self.id_renderer.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeIdentifier(self: Self, id: []const u8) !void {
|
fn writeIdentifier(self: Self, id: []const u8) !void {
|
||||||
|
|||||||
Reference in New Issue
Block a user