Globalize textures, materials and gui

This commit is contained in:
2026-05-23 01:37:28 +02:00
parent c971443b02
commit 40fcba9323
13 changed files with 195 additions and 242 deletions

View File

@@ -58,7 +58,7 @@ pub const Key = struct {
filename: Atom,
};
/// Maps a key value to a material ID. Preallocated with `allocator_general`.
/// Maps a key value to a material ID. Preallocated with `allocator_persistent`.
map: std.AutoHashMapUnmanaged(Key, Id),
/// Stores all material data in a single contiguous storage buffer. Use the
/// material ID as an index into this buffer.
@@ -70,24 +70,30 @@ material_count: usize,
/// storage buffer should take 208 kiB in VRAM.
pub const max_materials = 4096;
pub fn init() !Materials {
const allocator_general = ctx.allocator_general;
pub fn init() !*Materials {
const allocator_persistent = ctx.allocator_persistent;
var map: std.AutoHashMapUnmanaged(Key, Id) = .empty;
errdefer map.deinit(allocator_general);
try map.ensureTotalCapacity(allocator_general, max_materials);
const materials = try allocator_persistent.create(Materials);
var material_buffer = try shaders.MaterialBuffer.init(.{
materials.* = .{
.map = .empty,
.material_buffer = undefined,
.material_count = 0,
};
try materials.map.ensureTotalCapacity(allocator_persistent, max_materials);
materials.material_buffer = try .init(.{
.usage = .storage,
.target_queue = .graphics,
.array_capacity = max_materials,
.name = "Materials",
});
errdefer material_buffer.deinit();
errdefer materials.material_buffer.deinit();
// VOLATILE Synchronize with explicit values on top of `Id` type.
try material_buffer.write(.{
try materials.material_buffer.write(.{
.element_offset = Id.empty.toInt(),
.elements = &.{
.{
@@ -105,21 +111,16 @@ pub fn init() !Materials {
},
},
});
materials.material_count += 1;
return .{
.map = map,
.material_buffer = material_buffer,
.material_count = @typeInfo(Id).@"enum".fields.len,
};
std.debug.assert(materials.material_count == @typeInfo(Id).@"enum".fields.len);
return materials;
}
pub fn deinit(self: *Materials) void {
const allocator_general = ctx.allocator_general;
std.log.scoped(.deinit).debug("Deinitializing {*}", .{self});
self.material_buffer.deinit();
self.map.deinit(allocator_general);
self.* = undefined;
}
@@ -161,12 +162,7 @@ pub fn getAtom(self: *const Materials, filename: Atom) ?Id {
/// deinitialized or reset after this function returns. Note that during loading
/// the engine will make its own persistent allocations, so an out of memory
/// error is not necessarily related to `temp_allocator`.
pub fn getOrLoad(
self: *Materials,
textures: *Textures,
stbi: *media.stbi,
maybe_filename: ?[]const u8,
) !Id {
pub fn getOrLoad(self: *Materials, maybe_filename: ?[]const u8) !Id {
if (maybe_filename) |filename| {
const key: Key = .{
// If the material already exists, then the atom must exist and the
@@ -183,7 +179,7 @@ pub fn getOrLoad(
const id = Id.fromIndexSafe(self.material_count) catch |err| switch (err) {
error.Overflow => return error.OutOfMaterials,
};
try self.loadMaterial(textures, stbi, filename, id.toInt());
try self.loadMaterial(filename, id.toInt());
self.map.putAssumeCapacityNoClobber(key, id);
self.material_count += 1;
@@ -206,12 +202,7 @@ pub fn getOrLoad(
/// deinitialized or reset after this function returns. Note that during loading
/// the engine will make its own persistent allocations, so an out of memory
/// error is not necessarily related to `temp_allocator`.
pub fn getOrLoadAtom(
self: *Materials,
textures: *Textures,
stbi: *media.stbi,
filename: Atom,
) !Id {
pub fn getOrLoadAtom(self: *Materials, filename: Atom) !Id {
if (filename != .empty) {
const key: Key = .{
.filename = filename,
@@ -226,7 +217,7 @@ pub fn getOrLoadAtom(
const id = Id.fromIndexSafe(self.material_count) catch |err| switch (err) {
error.Overflow => return error.OutOfMaterials,
};
try self.loadMaterial(textures, stbi, filename.toString(), id.toInt());
try self.loadMaterial(filename.toString(), id.toInt());
self.map.putAssumeCapacityNoClobber(key, id);
self.material_count += 1;
@@ -248,11 +239,7 @@ pub fn getOrLoadAtom(
/// deinitialized or reset after this function returns. Note that during loading
/// the engine will make its own persistent allocations, so an out of memory
/// error is not necessarily related to `temp_allocator`.
pub fn loadAll(
self: *Materials,
textures: *Textures,
stbi: *media.stbi,
) void {
pub fn loadAll(self: *Materials) void {
const io = ctx.io;
const cwd = std.Io.Dir.cwd();
@@ -273,15 +260,16 @@ pub fn loadAll(
continue;
}
_ = self.getOrLoad(textures, stbi, entry.name) catch |err| {
_ = self.getOrLoad(entry.name) catch |err| {
std.log.err("Error while loading material entry {s}: {s}", .{ entry.name, @errorName(err) });
};
}
}
fn loadMaterial(self: *Materials, textures: *Textures, stbi: *media.stbi, filename: []const u8, index: u32) !void {
fn loadMaterial(self: *Materials, filename: []const u8, index: u32) !void {
const allocator_frame = ctx.allocator_frame;
const io = ctx.io;
const textures = ctx.textures;
const MaterialJson = struct {
baseColor: [3]f32 = .{ 1, 1, 1 },
@@ -330,10 +318,10 @@ fn loadMaterial(self: *Materials, textures: *Textures, stbi: *media.stbi, filena
.normal_scale = material_json.normalScale,
.occlusion_texture_strength = material_json.occlusionTextureStrength,
.roughness = material_json.roughness,
.base_color_texture = try textures.getOrLoad(stbi, material_json.baseColorTexture, .base_color),
.emissive_texture = try textures.getOrLoad(stbi, material_json.emissiveTexture, .emissive),
.normal_texture = try textures.getOrLoad(stbi, material_json.normalTexture, .normal),
.occlusion_roughness_metallic_texture = try textures.getOrLoad(stbi, material_json.occlusionRoughnessMetallicTexture, .occlusion_roughness_metallic),
.base_color_texture = try textures.getOrLoad(material_json.baseColorTexture, .base_color),
.emissive_texture = try textures.getOrLoad(material_json.emissiveTexture, .emissive),
.normal_texture = try textures.getOrLoad(material_json.normalTexture, .normal),
.occlusion_roughness_metallic_texture = try textures.getOrLoad(material_json.occlusionRoughnessMetallicTexture, .occlusion_roughness_metallic),
},
},
});