Refactor literally everything

This commit is contained in:
2025-11-26 01:19:20 +01:00
parent d6a4b8c1fe
commit 9f2d1e4608
22 changed files with 2070 additions and 1034 deletions

View File

@@ -3,36 +3,41 @@ const std = @import("std");
const stbi = @import("zstbi");
const Atoms = @import("Atoms.zig");
const atoms = @import("../engine/atoms.zig");
const Engine = @import("../engine/Engine.zig");
const Texture = @import("../engine/Texture.zig");
allocator: std.mem.Allocator,
map: Map,
array: Array,
textures: Array,
empty_base_color: Id,
empty_emissive: Id,
empty_normal: Id,
empty_occlusuion_roughness_metallic: Id,
pub const Id = extern struct {
id: u32,
};
pub const capacity = std.math.maxInt(std.meta.Tag(Id));
pub const Key = struct {
atom: Atoms.Atom,
atom: atoms.Atom,
usage: Texture.Usage,
};
pub const Id = enum(u16) {
empty_base_color = 0,
empty_emissive = 1,
empty_normal = 2,
empty_occlusion_roughness_metallic = 3,
_,
pub fn next(self: Id) Id {
return @enumFromInt(@intFromEnum(self) + 1);
}
};
pub const Map = std.AutoHashMapUnmanaged(Key, Id);
pub const Array = std.ArrayList(Texture);
pub fn init(allocator: std.mem.Allocator, engine: *Engine) !Textures {
pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
var map: Map = .empty;
errdefer map.deinit(allocator);
try map.ensureTotalCapacity(allocator, capacity);
var array: Array = try .initCapacity(allocator, 4);
var array: Array = try .initCapacity(allocator, capacity);
errdefer {
for (array.items) |*texture| {
texture.deinit(engine);
@@ -40,79 +45,116 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine) !Textures {
array.deinit(allocator);
}
const empty_base_color: Id = .{ .id = @intCast(array.items.len) };
const empty_base_color_texture: Texture = try .init(engine, 1, 1, .base_color);
array.appendAssumeCapacity(empty_base_color_texture);
const empty_base_color_texture = try Texture.init(engine, .{
.width = 1,
.height = 1,
.usage = .base_color,
.target_queue = .graphics,
});
const empty_emissive: Id = .{ .id = @intCast(array.items.len) };
const empty_emissive_texture: Texture = try .init(engine, 1, 1, .emissive);
array.appendAssumeCapacity(empty_emissive_texture);
const empty_emissive_texture = try Texture.init(engine, .{
.width = 1,
.height = 1,
.usage = .emissive,
.target_queue = .graphics,
});
const empty_normal: Id = .{ .id = @intCast(array.items.len) };
const empty_normal_texture: Texture = try .init(engine, 1, 1, .normal);
array.appendAssumeCapacity(empty_normal_texture);
const empty_normal_texture = try Texture.init(engine, .{
.width = 1,
.height = 1,
.usage = .normal,
.target_queue = .graphics,
});
const empty_occlusuion_roughness_metallic: Id = .{ .id = @intCast(array.items.len) };
const empty_occlusuion_roughness_metallic_texture: Texture = try .init(engine, 1, 1, .occlusion_roughness_metallic);
array.appendAssumeCapacity(empty_occlusuion_roughness_metallic_texture);
const empty_occlusuion_roughness_metallic_texture = try Texture.init(engine, .{
.width = 1,
.height = 1,
.usage = .occlusion_roughness_metallic,
.target_queue = .graphics,
});
try empty_base_color_texture.write([4]u8, engine, &.{.{ 255, 255, 255, 255 }});
try empty_emissive_texture.write([4]f16, engine, &.{.{ 1.0, 1.0, 1.0, 1.0 }});
try empty_normal_texture.write([4]i8, engine, &.{.{ 0, 0, 127, 127 }});
try empty_occlusuion_roughness_metallic_texture.write([4]u8, engine, &.{.{ 255, 255, 255, 255 }});
array.appendSliceAssumeCapacity(&.{
empty_base_color_texture,
empty_emissive_texture,
empty_normal_texture,
empty_occlusuion_roughness_metallic_texture,
});
try empty_base_color_texture.writeSamples(u8, engine, &.{ 255, 255, 255, 255 });
try empty_emissive_texture.writeSamples(f16, engine, &.{ 1.0, 1.0, 1.0, 1.0 });
try empty_normal_texture.writeSamples(i8, engine, &.{ 0, 0, 127, 127 });
try empty_occlusuion_roughness_metallic_texture.writeSamples(u8, engine, &.{ 255, 255, 255, 255 });
return .{
.allocator = allocator,
.map = map,
.array = array,
.empty_base_color = empty_base_color,
.empty_emissive = empty_emissive,
.empty_normal = empty_normal,
.empty_occlusuion_roughness_metallic = empty_occlusuion_roughness_metallic,
.textures = array,
};
}
pub fn deinit(self: *Textures, engine: *Engine) void {
for (self.array.items) |*texture| {
pub fn deinit(self: *Textures, engine: *Engine, allocator: std.mem.Allocator) void {
for (self.textures.items) |*texture| {
texture.deinit(engine);
}
self.array.deinit(self.allocator);
self.textures.deinit(allocator);
self.map.deinit(allocator);
self.* = undefined;
}
self.map.deinit(self.allocator);
pub fn getAtom(self: *const Textures, atom: atoms.Atom, usage: Texture.Usage) ?Id {
const key: Key = .{ .atom = atom, .usage = usage };
return self.map.get(key);
}
pub fn getFilename(self: *const Textures, filename: []const u8, usage: Texture.Usage) ?Id {
const atom = atoms.getAtom(filename) orelse return null;
const key: Key = .{ .atom = atom, .usage = usage };
return self.map.get(key);
}
pub fn getTexture(self: *const Textures, id: Id) ?*Texture {
const index: usize = id.id;
return if (index < self.array.items.len) &self.array.items[index] else null;
return if (index < self.textures.items.len) &self.textures.items[index] else null;
}
pub fn getId(self: *const Textures, key: Key) ?Id {
return self.map.get(key);
}
pub fn getOrLoadId(self: *Textures, engine: *Engine, atoms: *Atoms, key: Key) !Id {
const entry = try self.map.getOrPut(self.allocator, key);
pub fn getOrLoadAtom(self: *Textures, engine: *Engine, atom: atoms.Atom, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Id {
const key: Key = .{ .atom = atom, .usage = usage };
const entry = self.map.getOrPutAssumeCapacity(key);
if (entry.found_existing) {
return entry.value_ptr.*;
} else {
errdefer _ = self.map.remove(key);
try self.array.ensureUnusedCapacity(self.allocator, 1);
const texture = try self.loadTexture(engine, atoms, key);
const texture = try self.loadTexture(engine, atoms.getString(atom), usage, temp_allocator);
const id = self.nextId();
entry.value_ptr.* = id;
self.array.appendAssumeCapacity(texture);
self.textures.appendAssumeCapacity(texture);
return id;
}
}
fn loadTexture(self: *Textures, engine: *Engine, atoms: *Atoms, key: Key) !Texture {
const filename = atoms.getString(key.atom).?;
std.log.debug("Loading texture \"{s}\" as {s}...", .{ filename, @tagName(key.usage) });
pub fn getOrLoadFilename(self: *Textures, engine: *Engine, filename: []const u8, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Id {
const atom = try atoms.getOrPutAtom(filename);
const key: Key = .{ .atom = atom, .usage = usage };
const entry = self.map.getOrPutAssumeCapacity(key);
if (entry.found_existing) {
return entry.value_ptr.*;
} else {
errdefer _ = self.map.remove(key);
const texture = try loadTexture(engine, filename, usage, temp_allocator);
const id = self.nextId();
entry.value_ptr.* = id;
self.textures.appendAssumeCapacity(texture);
return id;
}
}
fn loadTexture(engine: *Engine, filename: []const u8, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Texture {
std.log.debug("Loading texture \"{s}\" as {s}...", .{ filename, @tagName(usage) });
const cwd = std.fs.cwd();
@@ -122,22 +164,26 @@ fn loadTexture(self: *Textures, engine: *Engine, atoms: *Atoms, key: Key) !Textu
const file = try dir.openFile(filename, .{});
defer file.close();
const file_buf = try file.readToEndAlloc(self.allocator, std.math.maxInt(usize));
defer self.allocator.free(file_buf);
const file_buf = try file.readToEndAlloc(temp_allocator, std.math.maxInt(usize));
defer temp_allocator.free(file_buf);
var img = try stbi.Image.loadFromMemory(file_buf, key.usage.sampleCount());
var img = try stbi.Image.loadFromMemory(file_buf, usage.samplesPerTexel());
defer img.deinit();
std.debug.assert(img.num_components == key.usage.sampleCount());
std.debug.assert(img.num_components == usage.samplesPerTexel());
var texture: Texture = try .init(engine, img.width, img.height, key.usage);
var texture = try Texture.init(engine, .{
.width = img.width,
.height = img.height,
.usage = usage,
.target_queue = .graphics,
});
errdefer texture.deinit(engine);
try texture.write(u8, engine, img.data);
try texture.writeRaw(engine, img.data);
return texture;
}
fn nextId(self: *const Textures) Id {
const index = self.array.items.len;
return .{ .id = @intCast(index) };
const index = self.textures.items.len;
return @enumFromInt(index);
}