Refactor literally everything
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
pub const Atoms = @This();
|
||||
const std = @import("std");
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
string_arena_state: std.heap.ArenaAllocator.State,
|
||||
map: Map,
|
||||
array: Array,
|
||||
|
||||
pub const Atom = extern struct {
|
||||
atom: u32,
|
||||
};
|
||||
|
||||
pub const Map = std.StringHashMapUnmanaged(Atom);
|
||||
pub const Array = std.ArrayList([]const u8);
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) Atoms {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.string_arena_state = .{},
|
||||
.map = .empty,
|
||||
.array = .empty,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Atoms) void {
|
||||
self.string_arena_state.promote(std.heap.page_allocator).deinit();
|
||||
self.map.deinit(self.allocator);
|
||||
self.array.deinit(self.allocator);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn getString(self: *const Atoms, atom: Atom) ?[]const u8 {
|
||||
const index: usize = atom.atom;
|
||||
return if (index < self.array.items.len) self.array.items[index] else null;
|
||||
}
|
||||
|
||||
pub fn getAtom(self: *const Atoms, string: []const u8) ?Atom {
|
||||
return self.map.get(string);
|
||||
}
|
||||
|
||||
pub fn getOrPutAtom(self: *Atoms, string: []const u8) !Atom {
|
||||
const entry = try self.map.getOrPut(self.allocator, string);
|
||||
|
||||
if (entry.found_existing) {
|
||||
return entry.value_ptr.*;
|
||||
} else {
|
||||
errdefer _ = self.map.remove(string);
|
||||
try self.array.ensureUnusedCapacity(self.allocator, 1);
|
||||
const owned_string = try self.toOwnedString(string);
|
||||
|
||||
const index = self.array.items.len;
|
||||
const atom: Atom = .{ .atom = @intCast(index) };
|
||||
|
||||
entry.key_ptr.* = owned_string;
|
||||
entry.value_ptr.* = atom;
|
||||
|
||||
self.array.appendAssumeCapacity(owned_string);
|
||||
|
||||
return atom;
|
||||
}
|
||||
}
|
||||
|
||||
fn toOwnedString(self: *Atoms, string: []const u8) ![]const u8 {
|
||||
var string_arena = self.string_arena_state.promote(std.heap.page_allocator);
|
||||
defer self.string_arena_state = string_arena.state;
|
||||
|
||||
const allocator = string_arena.allocator();
|
||||
const owned_string = try allocator.dupe(u8, string);
|
||||
return owned_string;
|
||||
}
|
||||
@@ -3,76 +3,112 @@ const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const Atoms = @import("Atoms.zig");
|
||||
const atoms = @import("../engine/atoms.zig");
|
||||
const Engine = @import("../engine/Engine.zig");
|
||||
const StorageBuffer = @import("../engine/StorageBuffer.zig");
|
||||
const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer;
|
||||
const Textures = @import("Textures.zig");
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
const MaterialBuffer = GenericBuffer(void, Material);
|
||||
|
||||
map: Map,
|
||||
storage_buffer: StorageBuffer,
|
||||
material_buffer: MaterialBuffer,
|
||||
next_id: Id,
|
||||
|
||||
pub const initial_capacity = 4;
|
||||
// capacity * @sizeOf(Material) = 832 kiB
|
||||
pub const capacity = std.math.maxInt(std.meta.Tag(Id));
|
||||
|
||||
pub const Id = extern struct {
|
||||
id: u32,
|
||||
pub const Key = struct { atom: atoms.Atom };
|
||||
pub const Id = enum(u16) {
|
||||
_,
|
||||
|
||||
pub fn next(self: Id) Id {
|
||||
return @enumFromInt(@intFromEnum(self) + 1);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Map = std.AutoHashMapUnmanaged(Atoms.Atom, Id);
|
||||
pub const Map = std.AutoHashMapUnmanaged(Key, Id);
|
||||
|
||||
pub const Material = extern struct {
|
||||
base_color: [3]f32,
|
||||
base_color_texture: Textures.Id,
|
||||
emissive: [3]f32,
|
||||
emissive_texture: Textures.Id,
|
||||
ior: f32,
|
||||
metallic: f32,
|
||||
normal_scale: f32,
|
||||
normal_texture: Textures.Id,
|
||||
occlusion_roughness_metallic_texture: Textures.Id,
|
||||
occlusion_texture_strength: f32,
|
||||
roughness: f32,
|
||||
|
||||
base_color_texture: Textures.Id,
|
||||
emissive_texture: Textures.Id,
|
||||
normal_texture: Textures.Id,
|
||||
occlusion_roughness_metallic_texture: Textures.Id,
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, engine: *Engine) !Materials {
|
||||
pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Materials {
|
||||
var map: Map = .empty;
|
||||
errdefer map.deinit(allocator);
|
||||
try map.ensureTotalCapacity(allocator, capacity);
|
||||
|
||||
var storage_buffer: StorageBuffer = try .init(engine, void, Material, initial_capacity);
|
||||
errdefer storage_buffer.deinit(engine);
|
||||
var material_buffer = try MaterialBuffer.init(engine, .{
|
||||
.usage = .storage,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = capacity,
|
||||
});
|
||||
errdefer material_buffer.deinit(engine);
|
||||
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.map = map,
|
||||
.storage_buffer = storage_buffer,
|
||||
.next_id = .{ .id = 0 },
|
||||
.material_buffer = material_buffer,
|
||||
.next_id = @enumFromInt(0),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Materials, engine: *Engine) void {
|
||||
self.storage_buffer.deinit(engine);
|
||||
self.map.deinit(self.allocator);
|
||||
pub fn deinit(self: *Materials, engine: *Engine, allocator: std.mem.Allocator) void {
|
||||
self.material_buffer.deinit(engine);
|
||||
self.map.deinit(allocator);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn getId(self: *const Materials, key: Atoms.Atom) ?Id {
|
||||
pub fn getAtom(self: *const Materials, atom: atoms.Atom) ?Id {
|
||||
const key: Key = .{ .atom = atom };
|
||||
return self.map.get(key);
|
||||
}
|
||||
|
||||
pub fn getOrLoadId(self: *Materials, engine: *Engine, textures: *Textures, atoms: *Atoms, key: Atoms.Atom) !Id {
|
||||
const entry = try self.map.getOrPut(self.allocator, key);
|
||||
pub fn getFilename(self: *const Materials, filename: []const u8) ?Id {
|
||||
const atom = atoms.getAtom(filename) orelse return null;
|
||||
const key: Key = .{ .atom = atom };
|
||||
return self.map.get(key);
|
||||
}
|
||||
|
||||
pub fn getOrLoadAtom(self: *Materials, engine: *Engine, textures: *Textures, atom: atoms.Atom, temp_allocator: std.mem.Allocator) !Id {
|
||||
const key: Key = .{ .atom = atom };
|
||||
const entry = self.map.getOrPutAssumeCapacity(key);
|
||||
|
||||
if (entry.found_existing) {
|
||||
return entry.value_ptr.*;
|
||||
} else {
|
||||
const id = try self.loadMaterial(engine, textures, atoms, key);
|
||||
errdefer _ = self.map.remove(key);
|
||||
const id = try self.loadMaterial(engine, textures, atoms.getString(atom), temp_allocator);
|
||||
entry.value_ptr.* = id;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, atoms: *Atoms, key: Atoms.Atom) !Id {
|
||||
pub fn getOrLoadFilename(self: *Materials, engine: *Engine, textures: *Textures, filename: []const u8, temp_allocator: std.mem.Allocator) !Id {
|
||||
const atom = try atoms.getOrPutAtom(filename);
|
||||
const key: Key = .{ .atom = atom };
|
||||
const entry = self.map.getOrPutAssumeCapacity(key);
|
||||
|
||||
if (entry.found_existing) {
|
||||
return entry.value_ptr.*;
|
||||
} else {
|
||||
errdefer _ = self.map.remove(key);
|
||||
const id = try self.loadMaterial(engine, textures, filename, temp_allocator);
|
||||
entry.value_ptr.* = id;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, filename: []const u8, temp_allocator: std.mem.Allocator) !Id {
|
||||
const MaterialJson = struct {
|
||||
baseColor: [3]f32 = .{ 1, 1, 1 },
|
||||
baseColorTexture: ?[]const u8 = null,
|
||||
@@ -87,7 +123,6 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, atoms: *
|
||||
roughness: f32 = 1,
|
||||
};
|
||||
|
||||
const filename = atoms.getString(key).?;
|
||||
std.log.debug("Loading material \"{s}\"...", .{filename});
|
||||
|
||||
const cwd = std.fs.cwd();
|
||||
@@ -102,10 +137,10 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, atoms: *
|
||||
defer file.close();
|
||||
|
||||
var file_reader = file.reader(&buffer);
|
||||
var json_reader: std.json.Reader = .init(self.allocator, &file_reader.interface);
|
||||
var json_reader: std.json.Reader = .init(temp_allocator, &file_reader.interface);
|
||||
defer json_reader.deinit();
|
||||
|
||||
const parsed: std.json.Parsed(MaterialJson) = try std.json.parseFromTokenSource(MaterialJson, self.allocator, &json_reader, .{
|
||||
const parsed: std.json.Parsed(MaterialJson) = try std.json.parseFromTokenSource(MaterialJson, temp_allocator, &json_reader, .{
|
||||
.duplicate_field_behavior = .@"error",
|
||||
.ignore_unknown_fields = false,
|
||||
.allocate = .alloc_if_needed,
|
||||
@@ -116,65 +151,57 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, atoms: *
|
||||
|
||||
const base_color_texture = blk: {
|
||||
if (material_json.baseColorTexture) |name| {
|
||||
const atom = try atoms.getOrPutAtom(name);
|
||||
break :blk try textures.getOrLoadId(engine, atoms, .{ .atom = atom, .usage = .base_color });
|
||||
break :blk try textures.getOrLoadFilename(engine, name, .base_color, temp_allocator);
|
||||
} else {
|
||||
break :blk textures.empty_base_color;
|
||||
break :blk .empty_base_color;
|
||||
}
|
||||
};
|
||||
|
||||
const emissive_texture = blk: {
|
||||
if (material_json.emissiveTexture) |name| {
|
||||
const atom = try atoms.getOrPutAtom(name);
|
||||
break :blk try textures.getOrLoadId(engine, atoms, .{ .atom = atom, .usage = .emissive });
|
||||
break :blk try textures.getOrLoadFilename(engine, name, .emissive, temp_allocator);
|
||||
} else {
|
||||
break :blk textures.empty_emissive;
|
||||
break :blk .empty_emissive;
|
||||
}
|
||||
};
|
||||
|
||||
const normal_texture = blk: {
|
||||
if (material_json.normalTexture) |name| {
|
||||
const atom = try atoms.getOrPutAtom(name);
|
||||
break :blk try textures.getOrLoadId(engine, atoms, .{ .atom = atom, .usage = .normal });
|
||||
break :blk try textures.getOrLoadFilename(engine, name, .normal, temp_allocator);
|
||||
} else {
|
||||
break :blk textures.empty_normal;
|
||||
break :blk .empty_normal;
|
||||
}
|
||||
};
|
||||
|
||||
const occlusion_roughness_metallic_texture = blk: {
|
||||
if (material_json.occlusionRoughnessMetallicTexture) |name| {
|
||||
const atom = try atoms.getOrPutAtom(name);
|
||||
break :blk try textures.getOrLoadId(engine, atoms, .{ .atom = atom, .usage = .occlusion_roughness_metallic });
|
||||
break :blk try textures.getOrLoadFilename(engine, name, .occlusion_roughness_metallic, temp_allocator);
|
||||
} else {
|
||||
break :blk textures.empty_occlusuion_roughness_metallic;
|
||||
break :blk .empty_occlusion_roughness_metallic;
|
||||
}
|
||||
};
|
||||
|
||||
const next_id = self.next_id;
|
||||
const offset: usize = next_id.id;
|
||||
|
||||
if (offset >= self.storage_buffer.array_capacity) {
|
||||
try self.storage_buffer.enlarge(void, Material, engine, self.storage_buffer.array_capacity * 2);
|
||||
}
|
||||
|
||||
const materials = [_]Material{
|
||||
.{
|
||||
.base_color = material_json.baseColor,
|
||||
.base_color_texture = base_color_texture,
|
||||
.emissive = material_json.emissive,
|
||||
.emissive_texture = emissive_texture,
|
||||
.ior = material_json.ior,
|
||||
.metallic = material_json.metallic,
|
||||
.normal_scale = material_json.normalScale,
|
||||
.normal_texture = normal_texture,
|
||||
.occlusion_roughness_metallic_texture = occlusion_roughness_metallic_texture,
|
||||
.occlusion_texture_strength = material_json.occlusionTextureStrength,
|
||||
.roughness = material_json.roughness,
|
||||
try self.material_buffer.write(engine, .{
|
||||
.element_offset = @intFromEnum(self.next_id),
|
||||
.elements = &.{
|
||||
.{
|
||||
.base_color = material_json.baseColor,
|
||||
.emissive = material_json.emissive,
|
||||
.ior = material_json.ior,
|
||||
.metallic = material_json.metallic,
|
||||
.normal_scale = material_json.normalScale,
|
||||
.occlusion_texture_strength = material_json.occlusionTextureStrength,
|
||||
.roughness = material_json.roughness,
|
||||
.base_color_texture = base_color_texture,
|
||||
.emissive_texture = emissive_texture,
|
||||
.normal_texture = normal_texture,
|
||||
.occlusion_roughness_metallic_texture = occlusion_roughness_metallic_texture,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
try self.storage_buffer.writeOffset(void, Material, engine, {}, offset, &materials);
|
||||
self.next_id = .{ .id = next_id.id + 1 };
|
||||
const id = self.next_id;
|
||||
self.next_id = self.next_id.next();
|
||||
|
||||
return next_id;
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user