Update to zig 0.16.0, update deps, Vulkan validation fixes
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
.zig-cache
|
.zig-cache
|
||||||
zig-out
|
zig-out
|
||||||
|
zig-pkg
|
||||||
*.spv
|
*.spv
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
const llvm = b.option(bool, "llvm", "Use LLVM and LLD") orelse false;
|
const llvm = b.option(bool, "llvm", "Use LLVM and LLD") orelse false;
|
||||||
|
|
||||||
const media_dep = b.dependency("media", .{});
|
const media_dep = b.dependency("media", .{
|
||||||
const vecmath_dep = b.dependency("vecmath", .{});
|
.target = target,
|
||||||
|
});
|
||||||
|
const vecmath_dep = b.dependency("vecmath", .{
|
||||||
|
.target = target,
|
||||||
|
});
|
||||||
const vulkan_dep = b.dependency("vulkan_zig", .{ .registry = b.path("vendor/vk.xml") });
|
const vulkan_dep = b.dependency("vulkan_zig", .{ .registry = b.path("vendor/vk.xml") });
|
||||||
const zglfw_dep = b.dependency("zglfw", .{ .import_vulkan = true });
|
const zglfw_dep = b.dependency("zglfw", .{ .import_vulkan = true });
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
.path = "castle/packages/vecmath",
|
.path = "castle/packages/vecmath",
|
||||||
},
|
},
|
||||||
.vulkan_zig = .{
|
.vulkan_zig = .{
|
||||||
.url = "git+https://github.com/Snektron/vulkan-zig.git#1446b0b994c2362264cc24513d7c7ec31b469c50",
|
.url = "git+https://github.com/Snektron/vulkan-zig.git#f75b0011214705d6593e6ad64948c4832b1e6f27",
|
||||||
.hash = "vulkan-0.0.0-r7Ytx_VDAwAiMl0YSu2UOkVMIGJN7CeIQaxJR-hUSfD6",
|
.hash = "vulkan-0.0.0-r7Ytx759AwBNdwE-gHKt3vzRQaU7RFerBg3FmD7iTEv4",
|
||||||
},
|
},
|
||||||
.zglfw = .{
|
.zglfw = .{
|
||||||
.url = "git+https://github.com/zig-gamedev/zglfw.git#6034a5623312c58bf5e64c1a2b686691c28575f4",
|
.url = "git+https://github.com/zig-gamedev/zglfw.git#51003c105d23db378bb59ce415a387b22f1b0892",
|
||||||
.hash = "zglfw-0.10.0-dev-zgVDNPKyIQCBi-wv_vxkvIQq1u0bP4D56Wszx_2mszc7",
|
.hash = "zglfw-0.10.0-dev-zgVDNIy4IQDJNRy4jrP1As-SZxfJpuWhU1iJ-wBab_VD",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
2
castle
2
castle
Submodule castle updated: 85f4957661...dc839e098c
27
src/Game.zig
27
src/Game.zig
@@ -24,6 +24,7 @@ const Swapchain = @import("engine/Swapchain.zig");
|
|||||||
const Textures = @import("assets/Textures.zig");
|
const Textures = @import("assets/Textures.zig");
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
engine: *Engine,
|
engine: *Engine,
|
||||||
swapchain: *Swapchain,
|
swapchain: *Swapchain,
|
||||||
global_descriptor_set_layout: vk.DescriptorSetLayout,
|
global_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||||
@@ -60,8 +61,8 @@ const chunk_descriptor_pool = 1024;
|
|||||||
|
|
||||||
const camera_near_plane = 0.1;
|
const camera_near_plane = 0.1;
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain) !Game {
|
pub fn init(allocator: std.mem.Allocator, io: std.Io, engine: *Engine, swapchain: *Swapchain) !Game {
|
||||||
var stbi = media.stbi.init(allocator);
|
var stbi = media.stbi.init(allocator, io);
|
||||||
errdefer stbi.deinit();
|
errdefer stbi.deinit();
|
||||||
|
|
||||||
var materials = try Materials.init(engine, allocator);
|
var materials = try Materials.init(engine, allocator);
|
||||||
@@ -77,7 +78,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
|||||||
// will crash the game with segfault reading address 0x140 (presumably
|
// will crash the game with segfault reading address 0x140 (presumably
|
||||||
// within librenderdoc.so).
|
// within librenderdoc.so).
|
||||||
|
|
||||||
blocks.loadAll(engine, &materials, &textures, &stbi, allocator);
|
blocks.loadAll(engine, &materials, &textures, &stbi, allocator, io);
|
||||||
|
|
||||||
const sampler = try engine.createSampler(.{
|
const sampler = try engine.createSampler(.{
|
||||||
.mag_filter = .linear,
|
.mag_filter = .linear,
|
||||||
@@ -438,10 +439,10 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
|||||||
});
|
});
|
||||||
engine.setObjectName(global_descriptor_set, "DS Global", .{});
|
engine.setObjectName(global_descriptor_set, "DS Global", .{});
|
||||||
|
|
||||||
const block_grass = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Grass.json", allocator);
|
const block_grass = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Grass.json", allocator, io);
|
||||||
const block_dirt = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Dirt.json", allocator);
|
const block_dirt = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Dirt.json", allocator, io);
|
||||||
const block_stone = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Stone.json", allocator);
|
const block_stone = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Stone.json", allocator, io);
|
||||||
const block_bedrock = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Bedrock.json", allocator);
|
const block_bedrock = try blocks.getOrLoad(engine, &materials, &textures, &stbi, "Bedrock.json", allocator, io);
|
||||||
|
|
||||||
// VOLATILE Load all assets before this point
|
// VOLATILE Load all assets before this point
|
||||||
|
|
||||||
@@ -632,11 +633,21 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
|||||||
.elements = directional_lights_data,
|
.elements = directional_lights_data,
|
||||||
});
|
});
|
||||||
|
|
||||||
var skybox = try Skybox.load("skybox.hdr", engine, &stbi, 512, global_uniforms.buffer, swapchain.render_pass, allocator);
|
var skybox = try Skybox.load(
|
||||||
|
"skybox.hdr",
|
||||||
|
engine,
|
||||||
|
&stbi,
|
||||||
|
512,
|
||||||
|
global_uniforms.buffer,
|
||||||
|
swapchain.render_pass,
|
||||||
|
allocator,
|
||||||
|
io,
|
||||||
|
);
|
||||||
errdefer skybox.deinit(engine);
|
errdefer skybox.deinit(engine);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
|
.io = io,
|
||||||
.engine = engine,
|
.engine = engine,
|
||||||
.swapchain = swapchain,
|
.swapchain = swapchain,
|
||||||
.global_descriptor_set_layout = global_descriptor_set_layout,
|
.global_descriptor_set_layout = global_descriptor_set_layout,
|
||||||
|
|||||||
@@ -264,7 +264,15 @@ pub fn onMouseDown(self: *Player, button: glfw.MouseButton, game: *Game) void {
|
|||||||
},
|
},
|
||||||
.right => blk: {
|
.right => blk: {
|
||||||
const target_vx = raycast_hit.voxel.add(raycast_hit.side.getSignVector());
|
const target_vx = raycast_hit.voxel.add(raycast_hit.side.getSignVector());
|
||||||
const id = game.blocks.getOrLoad(game.engine, &game.materials, &game.textures, &game.stbi, blocks[self.block_index], game.allocator) catch |err| {
|
const id = game.blocks.getOrLoad(
|
||||||
|
game.engine,
|
||||||
|
&game.materials,
|
||||||
|
&game.textures,
|
||||||
|
&game.stbi,
|
||||||
|
blocks[self.block_index],
|
||||||
|
game.allocator,
|
||||||
|
game.io,
|
||||||
|
) catch |err| {
|
||||||
std.log.err("Error while placing voxel at {f}: {}", .{ target_vx, err });
|
std.log.err("Error while placing voxel at {f}: {}", .{ target_vx, err });
|
||||||
break :blk;
|
break :blk;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -138,11 +138,12 @@ pub fn getOrLoad(
|
|||||||
stbi: *media.stbi,
|
stbi: *media.stbi,
|
||||||
filename: []const u8,
|
filename: []const u8,
|
||||||
temp_allocator: std.mem.Allocator,
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
) !Id {
|
) !Id {
|
||||||
const key: Key = .{
|
const key: Key = .{
|
||||||
// If the material already exists, then the atom must exist and the
|
// If the material already exists, then the atom must exist and the
|
||||||
// following line will not return any error.
|
// following line will not return any error.
|
||||||
.filename = try .fromString(filename),
|
.filename = try .fromString(filename, io),
|
||||||
};
|
};
|
||||||
|
|
||||||
// We don't use `getOrPutAssumeCapacity` method, because we might already be
|
// We don't use `getOrPutAssumeCapacity` method, because we might already be
|
||||||
@@ -154,7 +155,7 @@ pub fn getOrLoad(
|
|||||||
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
||||||
error.Overflow => return error.OutOfBlocks,
|
error.Overflow => return error.OutOfBlocks,
|
||||||
};
|
};
|
||||||
const def = try loadBlock(engine, materials, textures, stbi, filename, temp_allocator);
|
const def = try loadBlock(engine, materials, textures, stbi, filename, temp_allocator, io);
|
||||||
|
|
||||||
self.map.putAssumeCapacityNoClobber(key, id);
|
self.map.putAssumeCapacityNoClobber(key, id);
|
||||||
self.array.appendAssumeCapacity(def);
|
self.array.appendAssumeCapacity(def);
|
||||||
@@ -171,6 +172,7 @@ pub fn getOrLoadAtom(
|
|||||||
stbi: *media.stbi,
|
stbi: *media.stbi,
|
||||||
filename: Atom,
|
filename: Atom,
|
||||||
temp_allocator: std.mem.Allocator,
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
) !Id {
|
) !Id {
|
||||||
const key: Key = .{
|
const key: Key = .{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
@@ -185,7 +187,7 @@ pub fn getOrLoadAtom(
|
|||||||
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
||||||
error.Overflow => return error.OutOfBlocks,
|
error.Overflow => return error.OutOfBlocks,
|
||||||
};
|
};
|
||||||
const def = try loadBlock(engine, materials, textures, stbi, filename.toString(), temp_allocator);
|
const def = try loadBlock(engine, materials, textures, stbi, filename.toString(), temp_allocator, io);
|
||||||
|
|
||||||
self.map.putAssumeCapacityNoClobber(key, id);
|
self.map.putAssumeCapacityNoClobber(key, id);
|
||||||
self.array.appendAssumeCapacity(def);
|
self.array.appendAssumeCapacity(def);
|
||||||
@@ -201,17 +203,18 @@ pub fn loadAll(
|
|||||||
textures: *Textures,
|
textures: *Textures,
|
||||||
stbi: *media.stbi,
|
stbi: *media.stbi,
|
||||||
temp_allocator: std.mem.Allocator,
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
) void {
|
) void {
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
var dir = cwd.openDir("assets/blocks", .{ .iterate = true }) catch |err| {
|
var dir = cwd.openDir(io, "assets/blocks", .{ .iterate = true }) catch |err| {
|
||||||
std.log.err("Error while opening block definitions directory: {s}", .{@errorName(err)});
|
std.log.err("Error while opening block definitions directory: {s}", .{@errorName(err)});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
defer dir.close();
|
defer dir.close(io);
|
||||||
|
|
||||||
var it = dir.iterate();
|
var it = dir.iterate();
|
||||||
while (it.next() catch |err| {
|
while (it.next(io) catch |err| {
|
||||||
std.log.err("Error while iterating over block definitions directory: {s}", .{@errorName(err)});
|
std.log.err("Error while iterating over block definitions directory: {s}", .{@errorName(err)});
|
||||||
return;
|
return;
|
||||||
}) |entry| {
|
}) |entry| {
|
||||||
@@ -220,7 +223,7 @@ pub fn loadAll(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = self.getOrLoad(engine, materials, textures, stbi, entry.name, temp_allocator) catch |err| {
|
_ = self.getOrLoad(engine, materials, textures, stbi, entry.name, temp_allocator, io) catch |err| {
|
||||||
std.log.err("Error while loading block definition entry {s}: {s}", .{ entry.name, @errorName(err) });
|
std.log.err("Error while loading block definition entry {s}: {s}", .{ entry.name, @errorName(err) });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -233,6 +236,7 @@ fn loadBlock(
|
|||||||
stbi: *media.stbi,
|
stbi: *media.stbi,
|
||||||
filename: []const u8,
|
filename: []const u8,
|
||||||
temp_allocator: std.mem.Allocator,
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
) !Definition {
|
) !Definition {
|
||||||
const DefinitionJson = struct {
|
const DefinitionJson = struct {
|
||||||
pub const Wall = struct {
|
pub const Wall = struct {
|
||||||
@@ -248,18 +252,18 @@ fn loadBlock(
|
|||||||
|
|
||||||
std.log.debug("Loading block \"{s}\"...", .{filename});
|
std.log.debug("Loading block \"{s}\"...", .{filename});
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
var dir = try cwd.openDir("assets/blocks", .{});
|
var dir = try cwd.openDir(io, "assets/blocks", .{});
|
||||||
defer dir.close();
|
defer dir.close(io);
|
||||||
|
|
||||||
// NOTE Buffer size approximated based on expected JSON structure.
|
// NOTE Buffer size approximated based on expected JSON structure.
|
||||||
var buffer: [1024]u8 = undefined;
|
var buffer: [1024]u8 = undefined;
|
||||||
|
|
||||||
const file = try dir.openFile(filename, .{});
|
const file = try dir.openFile(io, filename, .{});
|
||||||
defer file.close();
|
defer file.close(io);
|
||||||
|
|
||||||
var file_reader = file.reader(&buffer);
|
var file_reader = file.reader(io, &buffer);
|
||||||
var json_reader = std.json.Reader.init(temp_allocator, &file_reader.interface);
|
var json_reader = std.json.Reader.init(temp_allocator, &file_reader.interface);
|
||||||
defer json_reader.deinit();
|
defer json_reader.deinit();
|
||||||
|
|
||||||
@@ -279,7 +283,7 @@ fn loadBlock(
|
|||||||
return error.ParseError;
|
return error.ParseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const material = try materials.getOrLoad(engine, textures, stbi, name, temp_allocator);
|
const material = try materials.getOrLoad(engine, textures, stbi, name, temp_allocator, io);
|
||||||
break :blk .initUniform(material);
|
break :blk .initUniform(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +293,7 @@ fn loadBlock(
|
|||||||
var ret: Definition.Walls = undefined;
|
var ret: Definition.Walls = undefined;
|
||||||
inline for (@typeInfo(voxels.Orientation).@"enum".fields) |field| {
|
inline for (@typeInfo(voxels.Orientation).@"enum".fields) |field| {
|
||||||
@field(ret, field.name) = .{
|
@field(ret, field.name) = .{
|
||||||
.material = try materials.getOrLoad(engine, textures, stbi, @field(walls, field.name).material, temp_allocator),
|
.material = try materials.getOrLoad(engine, textures, stbi, @field(walls, field.name).material, temp_allocator, io),
|
||||||
.transform = @field(walls, field.name).transform,
|
.transform = @field(walls, field.name).transform,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,12 +149,20 @@ pub fn getAtom(self: *const Materials, filename: Atom) ?Id {
|
|||||||
/// deinitialized or reset after this function returns. Note that during loading
|
/// deinitialized or reset after this function returns. Note that during loading
|
||||||
/// the engine will make its own persistent allocations, so an out of memory
|
/// the engine will make its own persistent allocations, so an out of memory
|
||||||
/// error is not necessarily related to `temp_allocator`.
|
/// error is not necessarily related to `temp_allocator`.
|
||||||
pub fn getOrLoad(self: *Materials, engine: *Engine, textures: *Textures, stbi: *media.stbi, maybe_filename: ?[]const u8, temp_allocator: std.mem.Allocator) !Id {
|
pub fn getOrLoad(
|
||||||
|
self: *Materials,
|
||||||
|
engine: *Engine,
|
||||||
|
textures: *Textures,
|
||||||
|
stbi: *media.stbi,
|
||||||
|
maybe_filename: ?[]const u8,
|
||||||
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
|
) !Id {
|
||||||
if (maybe_filename) |filename| {
|
if (maybe_filename) |filename| {
|
||||||
const key: Key = .{
|
const key: Key = .{
|
||||||
// If the material already exists, then the atom must exist and the
|
// If the material already exists, then the atom must exist and the
|
||||||
// following line will not return any error.
|
// following line will not return any error.
|
||||||
.filename = try .fromString(filename),
|
.filename = try .fromString(filename, io),
|
||||||
};
|
};
|
||||||
|
|
||||||
// We don't use `getOrPutAssumeCapacity` method, because we might already be
|
// We don't use `getOrPutAssumeCapacity` method, because we might already be
|
||||||
@@ -166,7 +174,7 @@ pub fn getOrLoad(self: *Materials, engine: *Engine, textures: *Textures, stbi: *
|
|||||||
const id = Id.fromIndexSafe(self.material_count) catch |err| switch (err) {
|
const id = Id.fromIndexSafe(self.material_count) catch |err| switch (err) {
|
||||||
error.Overflow => return error.OutOfMaterials,
|
error.Overflow => return error.OutOfMaterials,
|
||||||
};
|
};
|
||||||
try self.loadMaterial(engine, textures, stbi, filename, id.toInt(), temp_allocator);
|
try self.loadMaterial(engine, textures, stbi, filename, id.toInt(), temp_allocator, io);
|
||||||
|
|
||||||
self.map.putAssumeCapacityNoClobber(key, id);
|
self.map.putAssumeCapacityNoClobber(key, id);
|
||||||
self.material_count += 1;
|
self.material_count += 1;
|
||||||
@@ -189,7 +197,15 @@ pub fn getOrLoad(self: *Materials, engine: *Engine, textures: *Textures, stbi: *
|
|||||||
/// deinitialized or reset after this function returns. Note that during loading
|
/// deinitialized or reset after this function returns. Note that during loading
|
||||||
/// the engine will make its own persistent allocations, so an out of memory
|
/// the engine will make its own persistent allocations, so an out of memory
|
||||||
/// error is not necessarily related to `temp_allocator`.
|
/// error is not necessarily related to `temp_allocator`.
|
||||||
pub fn getOrLoadAtom(self: *Materials, engine: *Engine, textures: *Textures, stbi: *media.stbi, filename: Atom, temp_allocator: std.mem.Allocator) !Id {
|
pub fn getOrLoadAtom(
|
||||||
|
self: *Materials,
|
||||||
|
engine: *Engine,
|
||||||
|
textures: *Textures,
|
||||||
|
stbi: *media.stbi,
|
||||||
|
filename: Atom,
|
||||||
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
|
) !Id {
|
||||||
if (filename != .empty) {
|
if (filename != .empty) {
|
||||||
const key: Key = .{
|
const key: Key = .{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
@@ -204,7 +220,7 @@ pub fn getOrLoadAtom(self: *Materials, engine: *Engine, textures: *Textures, stb
|
|||||||
const id = Id.fromIndexSafe(self.material_count) catch |err| switch (err) {
|
const id = Id.fromIndexSafe(self.material_count) catch |err| switch (err) {
|
||||||
error.Overflow => return error.OutOfMaterials,
|
error.Overflow => return error.OutOfMaterials,
|
||||||
};
|
};
|
||||||
try self.loadMaterial(engine, textures, stbi, filename.toString(), id.toInt(), temp_allocator);
|
try self.loadMaterial(engine, textures, stbi, filename.toString(), id.toInt(), temp_allocator, io);
|
||||||
|
|
||||||
self.map.putAssumeCapacityNoClobber(key, id);
|
self.map.putAssumeCapacityNoClobber(key, id);
|
||||||
self.material_count += 1;
|
self.material_count += 1;
|
||||||
@@ -251,7 +267,7 @@ pub fn loadAll(self: *Materials, engine: *Engine, textures: *Textures, stbi: *me
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, stbi: *media.stbi, filename: []const u8, index: u32, temp_allocator: std.mem.Allocator) !void {
|
fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, stbi: *media.stbi, filename: []const u8, index: u32, temp_allocator: std.mem.Allocator, io: std.Io) !void {
|
||||||
const MaterialJson = struct {
|
const MaterialJson = struct {
|
||||||
baseColor: [3]f32 = .{ 1, 1, 1 },
|
baseColor: [3]f32 = .{ 1, 1, 1 },
|
||||||
baseColorTexture: ?[]const u8 = null,
|
baseColorTexture: ?[]const u8 = null,
|
||||||
@@ -268,18 +284,18 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, stbi: *m
|
|||||||
|
|
||||||
std.log.debug("Loading material \"{s}\"...", .{filename});
|
std.log.debug("Loading material \"{s}\"...", .{filename});
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
var dir = try cwd.openDir("assets/materials", .{});
|
var dir = try cwd.openDir(io, "assets/materials", .{});
|
||||||
defer dir.close();
|
defer dir.close(io);
|
||||||
|
|
||||||
// NOTE Buffer size approximated based on expected JSON structure.
|
// NOTE Buffer size approximated based on expected JSON structure.
|
||||||
var buffer: [512]u8 = undefined;
|
var buffer: [512]u8 = undefined;
|
||||||
|
|
||||||
const file = try dir.openFile(filename, .{});
|
const file = try dir.openFile(io, filename, .{});
|
||||||
defer file.close();
|
defer file.close(io);
|
||||||
|
|
||||||
var file_reader = file.reader(&buffer);
|
var file_reader = file.reader(io, &buffer);
|
||||||
var json_reader = std.json.Reader.init(temp_allocator, &file_reader.interface);
|
var json_reader = std.json.Reader.init(temp_allocator, &file_reader.interface);
|
||||||
defer json_reader.deinit();
|
defer json_reader.deinit();
|
||||||
|
|
||||||
@@ -303,10 +319,10 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, stbi: *m
|
|||||||
.normal_scale = material_json.normalScale,
|
.normal_scale = material_json.normalScale,
|
||||||
.occlusion_texture_strength = material_json.occlusionTextureStrength,
|
.occlusion_texture_strength = material_json.occlusionTextureStrength,
|
||||||
.roughness = material_json.roughness,
|
.roughness = material_json.roughness,
|
||||||
.base_color_texture = try textures.getOrLoad(engine, stbi, material_json.baseColorTexture, .base_color),
|
.base_color_texture = try textures.getOrLoad(engine, stbi, material_json.baseColorTexture, .base_color, io),
|
||||||
.emissive_texture = try textures.getOrLoad(engine, stbi, material_json.emissiveTexture, .emissive),
|
.emissive_texture = try textures.getOrLoad(engine, stbi, material_json.emissiveTexture, .emissive, io),
|
||||||
.normal_texture = try textures.getOrLoad(engine, stbi, material_json.normalTexture, .normal),
|
.normal_texture = try textures.getOrLoad(engine, stbi, material_json.normalTexture, .normal, io),
|
||||||
.occlusion_roughness_metallic_texture = try textures.getOrLoad(engine, stbi, material_json.occlusionRoughnessMetallicTexture, .occlusion_roughness_metallic),
|
.occlusion_roughness_metallic_texture = try textures.getOrLoad(engine, stbi, material_json.occlusionRoughnessMetallicTexture, .occlusion_roughness_metallic, io),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -172,12 +172,19 @@ pub fn getAtom(self: *const Textures, filename: Atom, usage: Texture.Usage) ?Id
|
|||||||
/// if necessary. Will not return any error if the texture already exists. When
|
/// if necessary. Will not return any error if the texture already exists. When
|
||||||
/// the filename is `null`, returns an empty texture ID appropriate for given
|
/// the filename is `null`, returns an empty texture ID appropriate for given
|
||||||
/// usage.
|
/// usage.
|
||||||
pub fn getOrLoad(self: *Textures, engine: *Engine, stbi: *media.stbi, maybe_filename: ?[]const u8, usage: Texture.Usage) !Id {
|
pub fn getOrLoad(
|
||||||
|
self: *Textures,
|
||||||
|
engine: *Engine,
|
||||||
|
stbi: *media.stbi,
|
||||||
|
maybe_filename: ?[]const u8,
|
||||||
|
usage: Texture.Usage,
|
||||||
|
io: std.Io,
|
||||||
|
) !Id {
|
||||||
if (maybe_filename) |filename| {
|
if (maybe_filename) |filename| {
|
||||||
const key: Key = .{
|
const key: Key = .{
|
||||||
// If the texture already exists, then the atom must exist and the
|
// If the texture already exists, then the atom must exist and the
|
||||||
// following line will not return any error.
|
// following line will not return any error.
|
||||||
.filename = try .fromString(filename),
|
.filename = try .fromString(filename, io),
|
||||||
.usage = usage,
|
.usage = usage,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -190,7 +197,7 @@ pub fn getOrLoad(self: *Textures, engine: *Engine, stbi: *media.stbi, maybe_file
|
|||||||
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
||||||
error.Overflow => return error.OutOfTextures,
|
error.Overflow => return error.OutOfTextures,
|
||||||
};
|
};
|
||||||
const texture = try loadTexture(engine, stbi, filename, usage);
|
const texture = try loadTexture(engine, stbi, filename, usage, io);
|
||||||
|
|
||||||
self.map.putAssumeCapacityNoClobber(key, id);
|
self.map.putAssumeCapacityNoClobber(key, id);
|
||||||
self.array.appendAssumeCapacity(texture);
|
self.array.appendAssumeCapacity(texture);
|
||||||
@@ -207,7 +214,14 @@ pub fn getOrLoad(self: *Textures, engine: *Engine, stbi: *media.stbi, maybe_file
|
|||||||
/// if necessary. Will not return any error if the texture already exists. When
|
/// if necessary. Will not return any error if the texture already exists. When
|
||||||
/// the filename is `.empty`, returns an empty texture ID appropriate for given
|
/// the filename is `.empty`, returns an empty texture ID appropriate for given
|
||||||
/// usage.
|
/// usage.
|
||||||
pub fn getOrLoadAtom(self: *Textures, engine: *Engine, stbi: *media.stbi, filename: Atom, usage: Texture.Usage) !Id {
|
pub fn getOrLoadAtom(
|
||||||
|
self: *Textures,
|
||||||
|
engine: *Engine,
|
||||||
|
stbi: *media.stbi,
|
||||||
|
filename: Atom,
|
||||||
|
usage: Texture.Usage,
|
||||||
|
io: std.Io,
|
||||||
|
) !Id {
|
||||||
if (filename != .empty) {
|
if (filename != .empty) {
|
||||||
const key: Key = .{
|
const key: Key = .{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
@@ -223,7 +237,7 @@ pub fn getOrLoadAtom(self: *Textures, engine: *Engine, stbi: *media.stbi, filena
|
|||||||
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
|
||||||
error.Overflow => return error.OutOfTextures,
|
error.Overflow => return error.OutOfTextures,
|
||||||
};
|
};
|
||||||
const texture = try loadTexture(engine, stbi, filename.toString(), usage);
|
const texture = try loadTexture(engine, stbi, filename.toString(), usage, io);
|
||||||
|
|
||||||
self.map.putAssumeCapacityNoClobber(key, id);
|
self.map.putAssumeCapacityNoClobber(key, id);
|
||||||
self.array.appendAssumeCapacity(texture);
|
self.array.appendAssumeCapacity(texture);
|
||||||
@@ -235,21 +249,27 @@ pub fn getOrLoadAtom(self: *Textures, engine: *Engine, stbi: *media.stbi, filena
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadTexture(engine: *Engine, stbi: *media.stbi, filename: []const u8, usage: Texture.Usage) !Texture {
|
fn loadTexture(
|
||||||
|
engine: *Engine,
|
||||||
|
stbi: *media.stbi,
|
||||||
|
filename: []const u8,
|
||||||
|
usage: Texture.Usage,
|
||||||
|
io: std.Io,
|
||||||
|
) !Texture {
|
||||||
std.log.debug("Loading texture \"{s}\" as {s}...", .{ filename, @tagName(usage) });
|
std.log.debug("Loading texture \"{s}\" as {s}...", .{ filename, @tagName(usage) });
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
var dir = try cwd.openDir("assets/textures", .{});
|
var dir = try cwd.openDir(io, "assets/textures", .{});
|
||||||
defer dir.close();
|
defer dir.close(io);
|
||||||
|
|
||||||
var file = try dir.openFile(filename, .{});
|
var file = try dir.openFile(io, filename, .{});
|
||||||
defer file.close();
|
defer file.close(io);
|
||||||
|
|
||||||
// The textures are expected to be small; a standard block base color as a
|
// The textures are expected to be small; a standard block base color as a
|
||||||
// PNG takes well below 1 kiB.
|
// PNG takes well below 1 kiB.
|
||||||
var buf: [4096]u8 = undefined;
|
var buf: [4096]u8 = undefined;
|
||||||
var reader = file.reader(&buf);
|
var reader = file.reader(io, &buf);
|
||||||
|
|
||||||
const img = try stbi.loadDynamicIo(&reader.interface);
|
const img = try stbi.loadDynamicIo(&reader.interface);
|
||||||
defer stbi.freeDynamic(img);
|
defer stbi.freeDynamic(img);
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ pub const Atom = enum(u16) {
|
|||||||
/// Turn a string into an atom. Returns either an existing atom or makes a
|
/// Turn a string into an atom. Returns either an existing atom or makes a
|
||||||
/// new one, if necessary. This will always produce a valid atom. Will not
|
/// new one, if necessary. This will always produce a valid atom. Will not
|
||||||
/// return any error if the atom already exists.
|
/// return any error if the atom already exists.
|
||||||
pub fn fromString(string: []const u8) error{ OutOfMemory, OutOfAtoms }!Atom {
|
pub fn fromString(string: []const u8, io: std.Io) error{ Canceled, OutOfMemory, OutOfAtoms }!Atom {
|
||||||
mutex.lock();
|
try mutex.lock(io);
|
||||||
defer mutex.unlock();
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
std.debug.assert(initialized);
|
std.debug.assert(initialized);
|
||||||
|
|
||||||
@@ -66,9 +66,9 @@ pub const Atom = enum(u16) {
|
|||||||
/// Turn a string into an atom, if the string has been already registered as
|
/// Turn a string into an atom, if the string has been already registered as
|
||||||
/// an atom. Returns `null` otherwise. This will always produce a valid
|
/// an atom. Returns `null` otherwise. This will always produce a valid
|
||||||
/// atom.
|
/// atom.
|
||||||
pub fn fromStringIfExists(string: []const u8) ?Atom {
|
pub fn fromStringIfExists(string: []const u8, io: std.Io) error{Canceled}!?Atom {
|
||||||
mutex.lock();
|
try mutex.lock(io);
|
||||||
defer mutex.unlock();
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
std.debug.assert(initialized);
|
std.debug.assert(initialized);
|
||||||
|
|
||||||
@@ -81,9 +81,9 @@ pub const Atom = enum(u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Cast an atom into a string. The caller asserts that the atom is valid.
|
/// Cast an atom into a string. The caller asserts that the atom is valid.
|
||||||
pub fn toString(self: Atom) [:0]const u8 {
|
pub fn toString(self: Atom, io: std.Io) error{Canceled}![:0]const u8 {
|
||||||
try mutex.lock();
|
try mutex.lock(io);
|
||||||
defer mutex.unlock();
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
std.debug.assert(initialized);
|
std.debug.assert(initialized);
|
||||||
|
|
||||||
@@ -110,11 +110,11 @@ var map: std.StringHashMapUnmanaged(Atom) = undefined;
|
|||||||
var array: std.ArrayList([:0]const u8) = undefined;
|
var array: std.ArrayList([:0]const u8) = undefined;
|
||||||
|
|
||||||
/// Protects all reads and writes to `map` and `array`.
|
/// Protects all reads and writes to `map` and `array`.
|
||||||
var mutex: std.Thread.Mutex = .{};
|
var mutex: std.Io.Mutex = .init;
|
||||||
|
|
||||||
pub fn init(_allocator: std.mem.Allocator) !void {
|
pub fn init(_allocator: std.mem.Allocator, io: std.Io) !void {
|
||||||
mutex.lock();
|
try mutex.lock(io);
|
||||||
defer mutex.unlock();
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
std.debug.assert(!initialized);
|
std.debug.assert(!initialized);
|
||||||
|
|
||||||
@@ -129,9 +129,9 @@ pub fn init(_allocator: std.mem.Allocator) !void {
|
|||||||
try array.append(allocator, "");
|
try array.append(allocator, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub fn deinit(io: std.Io) void {
|
||||||
mutex.lock();
|
mutex.lockUncancelable(io);
|
||||||
defer mutex.unlock();
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
std.log.scoped(.deinit).debug("Deinitializing atoms", .{});
|
std.log.scoped(.deinit).debug("Deinitializing atoms", .{});
|
||||||
std.debug.assert(initialized);
|
std.debug.assert(initialized);
|
||||||
@@ -149,9 +149,9 @@ pub fn deinit() void {
|
|||||||
|
|
||||||
/// Dump all atoms in a readable format. Use for debugging. Does not flush the
|
/// Dump all atoms in a readable format. Use for debugging. Does not flush the
|
||||||
/// writer.
|
/// writer.
|
||||||
pub fn dump(writer: std.Io.Writer) !void {
|
pub fn dump(writer: std.Io.Writer, io: std.Io) void {
|
||||||
mutex.lock();
|
mutex.lockUncancelable(io);
|
||||||
defer mutex.unlock();
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
std.debug.assert(initialized);
|
std.debug.assert(initialized);
|
||||||
|
|
||||||
|
|||||||
@@ -120,10 +120,8 @@ pub fn bindDescriptorSets(
|
|||||||
pipeline_bind_point,
|
pipeline_bind_point,
|
||||||
layout,
|
layout,
|
||||||
first_set,
|
first_set,
|
||||||
@intCast(descriptor_sets.len),
|
descriptor_sets,
|
||||||
descriptor_sets.ptr,
|
dynamic_offsets,
|
||||||
@intCast(dynamic_offsets.len),
|
|
||||||
dynamic_offsets.ptr,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,9 +144,8 @@ pub fn bindVertexBuffers(self: CommandBuffer, first_binding: u32, bindings: []co
|
|||||||
|
|
||||||
self.proxy.bindVertexBuffers(
|
self.proxy.bindVertexBuffers(
|
||||||
first_binding,
|
first_binding,
|
||||||
@intCast(vertex_buffer_bindings.len),
|
vertex_buffer_bindings.items(.buffer),
|
||||||
vertex_buffer_bindings.items(.buffer).ptr,
|
vertex_buffer_bindings.items(.offset),
|
||||||
vertex_buffer_bindings.items(.offset).ptr,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +173,7 @@ pub fn copyBuffer(
|
|||||||
dst_buffer: vk.Buffer,
|
dst_buffer: vk.Buffer,
|
||||||
regions: []const vk.BufferCopy,
|
regions: []const vk.BufferCopy,
|
||||||
) void {
|
) void {
|
||||||
self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr);
|
self.proxy.copyBuffer(src_buffer, dst_buffer, regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copyBufferToImage(
|
pub fn copyBufferToImage(
|
||||||
@@ -186,7 +183,7 @@ pub fn copyBufferToImage(
|
|||||||
dst_image_layout: vk.ImageLayout,
|
dst_image_layout: vk.ImageLayout,
|
||||||
regions: []const vk.BufferImageCopy,
|
regions: []const vk.BufferImageCopy,
|
||||||
) void {
|
) void {
|
||||||
self.proxy.copyBufferToImage(src_buffer, dst_image, dst_image_layout, @intCast(regions.len), regions.ptr);
|
self.proxy.copyBufferToImage(src_buffer, dst_image, dst_image_layout, regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
|
pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
|
||||||
@@ -194,19 +191,16 @@ pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
|
|||||||
barrier.src_stage_mask,
|
barrier.src_stage_mask,
|
||||||
barrier.dst_stage_mask,
|
barrier.dst_stage_mask,
|
||||||
barrier.dependency_flags,
|
barrier.dependency_flags,
|
||||||
@intCast(barrier.memory_barriers.len),
|
barrier.memory_barriers,
|
||||||
barrier.memory_barriers.ptr,
|
barrier.buffer_memory_barriers,
|
||||||
@intCast(barrier.buffer_memory_barriers.len),
|
barrier.image_memory_barriers,
|
||||||
barrier.buffer_memory_barriers.ptr,
|
|
||||||
@intCast(barrier.image_memory_barriers.len),
|
|
||||||
barrier.image_memory_barriers.ptr,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setScissor(self: CommandBuffer, first_scissor: u32, scissors: []const vk.Rect2D) void {
|
pub fn setScissor(self: CommandBuffer, first_scissor: u32, scissors: []const vk.Rect2D) void {
|
||||||
self.proxy.setScissor(first_scissor, @intCast(scissors.len), scissors.ptr);
|
self.proxy.setScissor(first_scissor, scissors);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setViewport(self: CommandBuffer, first_viewport: u32, viewports: []const vk.Viewport) void {
|
pub fn setViewport(self: CommandBuffer, first_viewport: u32, viewports: []const vk.Viewport) void {
|
||||||
self.proxy.setViewport(first_viewport, @intCast(viewports.len), viewports.ptr);
|
self.proxy.setViewport(first_viewport, viewports);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ const vk_version: vk.Version = vk.makeApiVersion(
|
|||||||
c.app_version.patch,
|
c.app_version.patch,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
|
pub fn init(allocator: std.mem.Allocator, io: std.Io, maybe_window: ?*glfw.Window) !Engine {
|
||||||
const vk_allocator = try VkAllocator.init(allocator);
|
const vk_allocator = try VkAllocator.init(allocator, io);
|
||||||
errdefer vk_allocator.deinit();
|
errdefer vk_allocator.deinit();
|
||||||
|
|
||||||
// --- LOAD BASE DISPATCH --------------------------------------------------
|
// --- LOAD BASE DISPATCH --------------------------------------------------
|
||||||
@@ -381,8 +381,8 @@ pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
|
|||||||
const prng_ptr = try allocator.create(std.Random.Pcg);
|
const prng_ptr = try allocator.create(std.Random.Pcg);
|
||||||
errdefer allocator.destroy(prng_ptr);
|
errdefer allocator.destroy(prng_ptr);
|
||||||
|
|
||||||
const timestamp: u128 = @bitCast(std.time.nanoTimestamp());
|
const timestamp: u64 = @bitCast(@as(i64, @truncate(std.Io.Timestamp.now(io, .awake).nanoseconds)));
|
||||||
prng_ptr.* = .init(@truncate(timestamp));
|
prng_ptr.* = .init(timestamp);
|
||||||
const random = prng_ptr.random();
|
const random = prng_ptr.random();
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@@ -562,7 +562,7 @@ pub fn queueSubmit(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.device.queueSubmit(queue, submits.len, &submits, submit_info.fence);
|
try self.device.queueSubmit(queue, &submits, submit_info.fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PresentInfo = struct {
|
pub const PresentInfo = struct {
|
||||||
@@ -1152,7 +1152,7 @@ pub fn createGraphicsPipeline(self: *Engine, create_info: GraphicsPipelineCreate
|
|||||||
};
|
};
|
||||||
|
|
||||||
var pipelines: [1]vk.Pipeline = undefined;
|
var pipelines: [1]vk.Pipeline = undefined;
|
||||||
_ = try self.device.createGraphicsPipelines(.null_handle, graphics_pipeline_create_infos.len, &graphics_pipeline_create_infos, &self.vk_allocator.interface, &pipelines);
|
_ = try self.device.createGraphicsPipelines(.null_handle, &graphics_pipeline_create_infos, &self.vk_allocator.interface, &pipelines);
|
||||||
return pipelines[0];
|
return pipelines[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1357,12 +1357,12 @@ pub fn deviceWaitIdle(self: *Engine) !void {
|
|||||||
pub fn freeCommandBuffer(self: *Engine, free_info: CommandBufferFreeInfo) void {
|
pub fn freeCommandBuffer(self: *Engine, free_info: CommandBufferFreeInfo) void {
|
||||||
const command_pool = self.resolveCommandPool(free_info.queue_type);
|
const command_pool = self.resolveCommandPool(free_info.queue_type);
|
||||||
const command_buffers = [_]vk.CommandBuffer{free_info.command_buffer};
|
const command_buffers = [_]vk.CommandBuffer{free_info.command_buffer};
|
||||||
self.device.freeCommandBuffers(command_pool, command_buffers.len, &command_buffers);
|
self.device.freeCommandBuffers(command_pool, &command_buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn freeDescriptorSet(self: *Engine, descriptor_pool: vk.DescriptorPool, descriptor_set: vk.DescriptorSet) void {
|
pub fn freeDescriptorSet(self: *Engine, descriptor_pool: vk.DescriptorPool, descriptor_set: vk.DescriptorSet) void {
|
||||||
const descriptor_sets = [_]vk.DescriptorSet{descriptor_set};
|
const descriptor_sets = [_]vk.DescriptorSet{descriptor_set};
|
||||||
self.device.freeDescriptorSets(descriptor_pool, descriptor_sets.len, &descriptor_sets) catch unreachable;
|
self.device.freeDescriptorSets(descriptor_pool, &descriptor_sets) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn freeMemory(self: *Engine, device_memory: vk.DeviceMemory) void {
|
pub fn freeMemory(self: *Engine, device_memory: vk.DeviceMemory) void {
|
||||||
@@ -1398,7 +1398,8 @@ pub fn mapMemory(self: *Engine, memory: vk.DeviceMemory, offset: vk.DeviceSize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resetFence(self: *Engine, fence: vk.Fence) !void {
|
pub fn resetFence(self: *Engine, fence: vk.Fence) !void {
|
||||||
try self.device.resetFences(1, @ptrCast(&fence));
|
const fences = [_]vk.Fence{fence};
|
||||||
|
try self.device.resetFences(&fences);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unmapMemory(self: *Engine, memory: vk.DeviceMemory) void {
|
pub fn unmapMemory(self: *Engine, memory: vk.DeviceMemory) void {
|
||||||
@@ -1446,14 +1447,10 @@ pub fn updateDescriptorSets(self: *Engine, update_info: DescriptorSetsUpdateInfo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.device.updateDescriptorSets(
|
self.device.updateDescriptorSets(descriptor_writes, update_info.copies);
|
||||||
@intCast(descriptor_writes.len),
|
|
||||||
descriptor_writes.ptr,
|
|
||||||
@intCast(update_info.copies.len),
|
|
||||||
update_info.copies.ptr,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn waitForFence(self: *Engine, fence: vk.Fence) !void {
|
pub fn waitForFence(self: *Engine, fence: vk.Fence) !void {
|
||||||
_ = try self.device.waitForFences(1, @ptrCast(&fence), .true, 1 * std.time.ns_per_s);
|
const fences = [_]vk.Fence{fence};
|
||||||
|
_ = try self.device.waitForFences(&fences, .true, 1 * std.time.ns_per_s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,17 +25,26 @@ descriptor_set: vk.DescriptorSet,
|
|||||||
pipeline_layout: vk.PipelineLayout,
|
pipeline_layout: vk.PipelineLayout,
|
||||||
pipeline: vk.Pipeline,
|
pipeline: vk.Pipeline,
|
||||||
|
|
||||||
pub fn load(filename: []const u8, engine: *Engine, stbi: *media.stbi, cube_size: u32, global_uniforms_buffer: vk.Buffer, render_pass: vk.RenderPass, temp_allocator: std.mem.Allocator) !Skybox {
|
pub fn load(
|
||||||
|
filename: []const u8,
|
||||||
|
engine: *Engine,
|
||||||
|
stbi: *media.stbi,
|
||||||
|
cube_size: u32,
|
||||||
|
global_uniforms_buffer: vk.Buffer,
|
||||||
|
render_pass: vk.RenderPass,
|
||||||
|
temp_allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
|
) !Skybox {
|
||||||
std.log.debug("Loading skybox \"{s}\"...", .{filename});
|
std.log.debug("Loading skybox \"{s}\"...", .{filename});
|
||||||
|
|
||||||
// --- LOAD IMAGE FROM MEMORY ----------------------------------------------
|
// --- LOAD IMAGE FROM MEMORY ----------------------------------------------
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
var dir = try cwd.openDir("assets", .{});
|
var dir = try cwd.openDir(io, "assets", .{});
|
||||||
defer dir.close();
|
defer dir.close(io);
|
||||||
|
|
||||||
const file_buf = try dir.readFileAlloc(temp_allocator, filename, std.math.maxInt(usize));
|
const file_buf = try dir.readFileAlloc(io, filename, temp_allocator, .unlimited);
|
||||||
defer temp_allocator.free(file_buf);
|
defer temp_allocator.free(file_buf);
|
||||||
|
|
||||||
const img = try stbi.loadHdrBuf(file_buf);
|
const img = try stbi.loadHdrBuf(file_buf);
|
||||||
@@ -169,7 +178,7 @@ pub fn load(filename: []const u8, engine: *Engine, stbi: *media.stbi, cube_size:
|
|||||||
|
|
||||||
// --- TRANSITION TO SHADER_READ_ONLY_OPTIMAL ------------------------------
|
// --- TRANSITION TO SHADER_READ_ONLY_OPTIMAL ------------------------------
|
||||||
|
|
||||||
var transition1_command_buffer = try CommandBuffer.init(engine, .graphics);
|
var transition1_command_buffer = try CommandBuffer.init(engine, .compute);
|
||||||
defer transition1_command_buffer.deinit(engine);
|
defer transition1_command_buffer.deinit(engine);
|
||||||
|
|
||||||
try transition1_command_buffer.beginCommandBuffer();
|
try transition1_command_buffer.beginCommandBuffer();
|
||||||
@@ -304,7 +313,7 @@ pub fn load(filename: []const u8, engine: *Engine, stbi: *media.stbi, cube_size:
|
|||||||
defer engine.destroyShaderModule(compute_shader);
|
defer engine.destroyShaderModule(compute_shader);
|
||||||
|
|
||||||
var compute_pipeline: vk.Pipeline = undefined;
|
var compute_pipeline: vk.Pipeline = undefined;
|
||||||
_ = try engine.device.createComputePipelines(.null_handle, 1, &.{
|
_ = try engine.device.createComputePipelines(.null_handle, &.{
|
||||||
.{
|
.{
|
||||||
.stage = .{
|
.stage = .{
|
||||||
.stage = .{ .compute_bit = true },
|
.stage = .{ .compute_bit = true },
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ pub fn init(engine: *Engine) !Swapchain {
|
|||||||
.color_attachment_write_bit = true,
|
.color_attachment_write_bit = true,
|
||||||
.depth_stencil_attachment_write_bit = true,
|
.depth_stencil_attachment_write_bit = true,
|
||||||
},
|
},
|
||||||
|
.dependency_flags = .{
|
||||||
|
.by_region_bit = true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ const vk = @import("vulkan");
|
|||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
allocations: std.AutoHashMapUnmanaged(*anyopaque, usize) = .empty,
|
allocations: std.AutoHashMapUnmanaged(*anyopaque, usize) = .empty,
|
||||||
mutex: std.Thread.Mutex = .{},
|
mutex: std.Io.Mutex = .init,
|
||||||
allocated_bytes: usize = 0,
|
allocated_bytes: usize = 0,
|
||||||
|
io: std.Io,
|
||||||
|
|
||||||
interface: vk.AllocationCallbacks,
|
interface: vk.AllocationCallbacks,
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ const actual_alignment: std.mem.Alignment = .@"16";
|
|||||||
|
|
||||||
const log = std.log.scoped(.vk_allocator);
|
const log = std.log.scoped(.vk_allocator);
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !*VkAllocator {
|
pub fn init(allocator: std.mem.Allocator, io: std.Io) !*VkAllocator {
|
||||||
// NOTE We allocate the structure to pin its address.
|
// NOTE We allocate the structure to pin its address.
|
||||||
const self = try allocator.create(VkAllocator);
|
const self = try allocator.create(VkAllocator);
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ pub fn init(allocator: std.mem.Allocator) !*VkAllocator {
|
|||||||
.pfn_reallocation = &reallocationFunction,
|
.pfn_reallocation = &reallocationFunction,
|
||||||
.pfn_free = &freeFunction,
|
.pfn_free = &freeFunction,
|
||||||
},
|
},
|
||||||
|
.io = io,
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -69,8 +71,8 @@ fn allocationFunction(
|
|||||||
const desired_alignment = std.mem.Alignment.fromByteUnits(alignment);
|
const desired_alignment = std.mem.Alignment.fromByteUnits(alignment);
|
||||||
std.debug.assert(std.mem.Alignment.compare(actual_alignment, .gte, desired_alignment));
|
std.debug.assert(std.mem.Alignment.compare(actual_alignment, .gte, desired_alignment));
|
||||||
|
|
||||||
self.mutex.lock();
|
self.mutex.lock(self.io) catch return null;
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock(self.io);
|
||||||
|
|
||||||
self.allocations.ensureUnusedCapacity(self.allocator, 1) catch return null;
|
self.allocations.ensureUnusedCapacity(self.allocator, 1) catch return null;
|
||||||
const memory = self.allocator.alignedAlloc(u8, actual_alignment, size) catch return null;
|
const memory = self.allocator.alignedAlloc(u8, actual_alignment, size) catch return null;
|
||||||
@@ -94,8 +96,8 @@ fn reallocationFunction(
|
|||||||
const desired_alignment = std.mem.Alignment.fromByteUnits(alignment);
|
const desired_alignment = std.mem.Alignment.fromByteUnits(alignment);
|
||||||
std.debug.assert(std.mem.Alignment.compare(actual_alignment, .gte, desired_alignment));
|
std.debug.assert(std.mem.Alignment.compare(actual_alignment, .gte, desired_alignment));
|
||||||
|
|
||||||
self.mutex.lock();
|
self.mutex.lock(self.io) catch return null;
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock(self.io);
|
||||||
|
|
||||||
// NOTE If we were pedantic, we would consider the fact that we might not
|
// NOTE If we were pedantic, we would consider the fact that we might not
|
||||||
// need unused capacity if the memory doesn't get relocated.
|
// need unused capacity if the memory doesn't get relocated.
|
||||||
@@ -130,8 +132,8 @@ fn freeFunction(
|
|||||||
const self: *VkAllocator = @ptrCast(@alignCast(p_user_data.?));
|
const self: *VkAllocator = @ptrCast(@alignCast(p_user_data.?));
|
||||||
|
|
||||||
if (maybe_p_memory) |p_memory| {
|
if (maybe_p_memory) |p_memory| {
|
||||||
self.mutex.lock();
|
self.mutex.lockUncancelable();
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock(self.io);
|
||||||
|
|
||||||
const size = self.allocations.fetchRemove(p_memory).?.value;
|
const size = self.allocations.fetchRemove(p_memory).?.value;
|
||||||
self.allocated_bytes -= size;
|
self.allocated_bytes -= size;
|
||||||
|
|||||||
18
src/main.zig
18
src/main.zig
@@ -24,14 +24,12 @@ pub const std_options: std.Options = .{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main(init: std.process.Init) !void {
|
||||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
const allocator = init.gpa;
|
||||||
defer _ = gpa.deinit();
|
const io = init.io;
|
||||||
|
|
||||||
const allocator = gpa.allocator();
|
try atoms.init(allocator, io);
|
||||||
|
defer atoms.deinit(io);
|
||||||
try atoms.init(allocator);
|
|
||||||
defer atoms.deinit();
|
|
||||||
|
|
||||||
glfw.init() catch |err| {
|
glfw.init() catch |err| {
|
||||||
std.log.err("Could not initialize GLFW", .{});
|
std.log.err("Could not initialize GLFW", .{});
|
||||||
@@ -45,7 +43,7 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfw.windowHint(.client_api, .no_api);
|
glfw.windowHint(.client_api, .no_api);
|
||||||
var window = glfw.Window.create(c.default_window_width, c.default_window_height, c.window_title, null) catch |err| {
|
var window = glfw.Window.create(c.default_window_width, c.default_window_height, c.window_title, null, null) catch |err| {
|
||||||
std.log.err("Could not create window", .{});
|
std.log.err("Could not create window", .{});
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
@@ -61,13 +59,13 @@ pub fn main() !void {
|
|||||||
_ = window.setCursorPosCallback(cursorPosCallback);
|
_ = window.setCursorPosCallback(cursorPosCallback);
|
||||||
_ = window.setMouseButtonCallback(mouseButtonCallback);
|
_ = window.setMouseButtonCallback(mouseButtonCallback);
|
||||||
|
|
||||||
var engine = try Engine.init(allocator, window);
|
var engine = try Engine.init(allocator, io, window);
|
||||||
defer engine.deinit();
|
defer engine.deinit();
|
||||||
|
|
||||||
var swapchain = try Swapchain.init(&engine);
|
var swapchain = try Swapchain.init(&engine);
|
||||||
defer swapchain.deinit(&engine);
|
defer swapchain.deinit(&engine);
|
||||||
|
|
||||||
var game = try Game.init(allocator, &engine, &swapchain);
|
var game = try Game.init(allocator, io, &engine, &swapchain);
|
||||||
var callback_context: CallbackContext = blk: {
|
var callback_context: CallbackContext = blk: {
|
||||||
const cursor_last_xpos, const cursor_last_ypos = window.getCursorPos();
|
const cursor_last_xpos, const cursor_last_ypos = window.getCursorPos();
|
||||||
break :blk .{
|
break :blk .{
|
||||||
|
|||||||
Reference in New Issue
Block a user