Globalize textures, materials and gui
This commit is contained in:
@@ -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),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user