Compare commits
3 Commits
a18fcb44ac
...
a6d2538352
| Author | SHA1 | Date | |
|---|---|---|---|
| a6d2538352 | |||
| 2fb4e38209 | |||
| e8674a6bcd |
@@ -1,6 +1,7 @@
|
|||||||
const Chunk = @This();
|
const Chunk = @This();
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const c = @import("const.zig");
|
||||||
const ctx = @import("AppContext.zig");
|
const ctx = @import("AppContext.zig");
|
||||||
const math = @import("math.zig");
|
const math = @import("math.zig");
|
||||||
const shaders = @import("shaders.zig");
|
const shaders = @import("shaders.zig");
|
||||||
@@ -15,9 +16,7 @@ const Game = @import("Game.zig");
|
|||||||
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
||||||
const Materials = @import("engine/Materials.zig");
|
const Materials = @import("engine/Materials.zig");
|
||||||
|
|
||||||
const ObjectUniformsBuffer = GenericBuffer(void, shaders.ObjectUniforms);
|
const chunk_size = c.vx_per_ck;
|
||||||
|
|
||||||
pub const chunk_size = 16;
|
|
||||||
|
|
||||||
const initial_capacity = 256;
|
const initial_capacity = 256;
|
||||||
var next_chunk_id: std.atomic.Value(u64) = .init(0);
|
var next_chunk_id: std.atomic.Value(u64) = .init(0);
|
||||||
@@ -27,7 +26,7 @@ var next_chunk_id: std.atomic.Value(u64) = .init(0);
|
|||||||
blocks: [chunk_size][chunk_size][chunk_size]Blocks.Id,
|
blocks: [chunk_size][chunk_size][chunk_size]Blocks.Id,
|
||||||
origin: vm.Vector3,
|
origin: vm.Vector3,
|
||||||
descriptor_set: vk.DescriptorSet,
|
descriptor_set: vk.DescriptorSet,
|
||||||
object_buffer: ObjectUniformsBuffer,
|
object_buffer: shaders.ObjectUniformsBuffer,
|
||||||
object_count: u32,
|
object_count: u32,
|
||||||
|
|
||||||
/// For debug purposes, a unique "name" per chunk instance.
|
/// For debug purposes, a unique "name" per chunk instance.
|
||||||
@@ -50,10 +49,10 @@ pub fn init(init_info: InitInfo) !Chunk {
|
|||||||
});
|
});
|
||||||
errdefer engine.freeDescriptorSet(init_info.descriptor_pool, descriptor_set);
|
errdefer engine.freeDescriptorSet(init_info.descriptor_pool, descriptor_set);
|
||||||
|
|
||||||
var object_buffer: ObjectUniformsBuffer = try .init(.{
|
var object_buffer: shaders.ObjectUniformsBuffer = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = initial_capacity,
|
.capacity = initial_capacity,
|
||||||
});
|
});
|
||||||
errdefer object_buffer.deinit();
|
errdefer object_buffer.deinit();
|
||||||
|
|
||||||
@@ -135,12 +134,12 @@ pub fn refresh(self: *Chunk, blocks: *const Blocks, neighbors: Neighbors) !void
|
|||||||
}
|
}
|
||||||
|
|
||||||
const object_count: u32 = @intCast(uniforms.items.len);
|
const object_count: u32 = @intCast(uniforms.items.len);
|
||||||
if (self.object_buffer.array_capacity < object_count) {
|
if (self.object_buffer.capacity < object_count) {
|
||||||
const desired_capacity = std.math.ceilPowerOfTwoAssert(u32, object_count);
|
const desired_capacity = std.math.ceilPowerOfTwoAssert(u32, object_count);
|
||||||
const new_object_buffer: ObjectUniformsBuffer = try .init(.{
|
const new_object_buffer: shaders.ObjectUniformsBuffer = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = desired_capacity,
|
.capacity = desired_capacity,
|
||||||
});
|
});
|
||||||
|
|
||||||
try engine.updateDescriptorSets(.{
|
try engine.updateDescriptorSets(.{
|
||||||
@@ -169,7 +168,7 @@ pub fn refresh(self: *Chunk, blocks: *const Blocks, neighbors: Neighbors) !void
|
|||||||
engine.setObjectName(new_object_buffer.device_memory, "DM Chunk[{d}]", .{self.chunk_id});
|
engine.setObjectName(new_object_buffer.device_memory, "DM Chunk[{d}]", .{self.chunk_id});
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.object_buffer.write(.{ .elements = uniforms.items });
|
try self.object_buffer.writeSlice(uniforms.items);
|
||||||
self.object_count = object_count;
|
self.object_count = object_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
90
src/Game.zig
90
src/Game.zig
@@ -21,7 +21,6 @@ const Iterator2 = math.Iterator2;
|
|||||||
const Materials = @import("engine/Materials.zig");
|
const Materials = @import("engine/Materials.zig");
|
||||||
const Player = @import("Player.zig");
|
const Player = @import("Player.zig");
|
||||||
const Skybox = @import("engine/Skybox.zig");
|
const Skybox = @import("engine/Skybox.zig");
|
||||||
const StagingBuffer = @import("engine/StagingBuffer.zig");
|
|
||||||
const Swapchain = @import("engine/Swapchain.zig");
|
const Swapchain = @import("engine/Swapchain.zig");
|
||||||
const Texture = @import("engine/Texture.zig");
|
const Texture = @import("engine/Texture.zig");
|
||||||
const Textures = @import("engine/Textures.zig");
|
const Textures = @import("engine/Textures.zig");
|
||||||
@@ -37,7 +36,8 @@ vertex_buffer: shaders.VertexBuffer,
|
|||||||
index_buffer: shaders.IndexBuffer,
|
index_buffer: shaders.IndexBuffer,
|
||||||
|
|
||||||
global_uniforms: shaders.GlobalUniformsBuffer,
|
global_uniforms: shaders.GlobalUniformsBuffer,
|
||||||
global_uniforms_staging_buffer: StagingBuffer,
|
global_uniforms_staging_buffer: shaders.GlobalUniformsBuffer,
|
||||||
|
global_uniforms_staging_ptr: *shaders.GlobalUniforms,
|
||||||
global_uniforms_transfer_semaphores: []vk.Semaphore,
|
global_uniforms_transfer_semaphores: []vk.Semaphore,
|
||||||
point_lights: shaders.PointLightBuffer,
|
point_lights: shaders.PointLightBuffer,
|
||||||
directional_lights: shaders.DirectionalLightBuffer,
|
directional_lights: shaders.DirectionalLightBuffer,
|
||||||
@@ -174,49 +174,45 @@ pub fn init() !Game {
|
|||||||
var vertex_buffer = try shaders.VertexBuffer.init(.{
|
var vertex_buffer = try shaders.VertexBuffer.init(.{
|
||||||
.usage = .vertex,
|
.usage = .vertex,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = 4,
|
.capacity = 4,
|
||||||
.name = "QuadVB",
|
.name = "QuadVB",
|
||||||
});
|
});
|
||||||
errdefer vertex_buffer.deinit();
|
errdefer vertex_buffer.deinit();
|
||||||
try vertex_buffer.write(.{
|
try vertex_buffer.writeSlice(&.{
|
||||||
.elements = &.{
|
.init(
|
||||||
.init(
|
.init(0, 0, 0),
|
||||||
.init(0, 0, 0),
|
.init(0, 1),
|
||||||
.init(0, 1),
|
.init(0, 0, 1),
|
||||||
.init(0, 0, 1),
|
.init(1, 0, 0, -1),
|
||||||
.init(1, 0, 0, -1),
|
),
|
||||||
),
|
.init(
|
||||||
.init(
|
.init(1, 0, 0),
|
||||||
.init(1, 0, 0),
|
.init(1, 1),
|
||||||
.init(1, 1),
|
.init(0, 0, 1),
|
||||||
.init(0, 0, 1),
|
.init(1, 0, 0, -1),
|
||||||
.init(1, 0, 0, -1),
|
),
|
||||||
),
|
.init(
|
||||||
.init(
|
.init(0, 1, 0),
|
||||||
.init(0, 1, 0),
|
.init(0, 0),
|
||||||
.init(0, 0),
|
.init(0, 0, 1),
|
||||||
.init(0, 0, 1),
|
.init(1, 0, 0, -1),
|
||||||
.init(1, 0, 0, -1),
|
),
|
||||||
),
|
.init(
|
||||||
.init(
|
.init(1, 1, 0),
|
||||||
.init(1, 1, 0),
|
.init(1, 0),
|
||||||
.init(1, 0),
|
.init(0, 0, 1),
|
||||||
.init(0, 0, 1),
|
.init(1, 0, 0, -1),
|
||||||
.init(1, 0, 0, -1),
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var index_buffer = try shaders.IndexBuffer.init(.{
|
var index_buffer = try shaders.IndexBuffer.init(.{
|
||||||
.usage = .index,
|
.usage = .index,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = 6,
|
.capacity = 6,
|
||||||
.name = "QuadIB",
|
.name = "QuadIB",
|
||||||
});
|
});
|
||||||
errdefer index_buffer.deinit();
|
errdefer index_buffer.deinit();
|
||||||
try index_buffer.write(.{
|
try index_buffer.writeSlice(&.{ 0, 1, 2, 2, 1, 3 });
|
||||||
.elements = &.{ 0, 1, 2, 2, 1, 3 },
|
|
||||||
});
|
|
||||||
|
|
||||||
var global_uniforms = try shaders.GlobalUniformsBuffer.init(.{
|
var global_uniforms = try shaders.GlobalUniformsBuffer.init(.{
|
||||||
.usage = .uniform,
|
.usage = .uniform,
|
||||||
@@ -225,12 +221,17 @@ pub fn init() !Game {
|
|||||||
});
|
});
|
||||||
errdefer global_uniforms.deinit();
|
errdefer global_uniforms.deinit();
|
||||||
|
|
||||||
var global_uniforms_staging_buffer = try StagingBuffer.init(.{
|
var global_uniforms_staging_buffer = try shaders.GlobalUniformsBuffer.init(.{
|
||||||
.capacity = @sizeOf(shaders.GlobalUniforms),
|
.usage = .staging,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
|
.mappable = true,
|
||||||
|
.name = "GlobalUniforms Staging",
|
||||||
});
|
});
|
||||||
errdefer global_uniforms_staging_buffer.deinit();
|
errdefer global_uniforms_staging_buffer.deinit();
|
||||||
|
|
||||||
|
const global_uniforms_staging_ptr = try global_uniforms_staging_buffer.map();
|
||||||
|
errdefer global_uniforms_staging_buffer.unmap();
|
||||||
|
|
||||||
const global_uniforms_transfer_semaphores = blk: {
|
const global_uniforms_transfer_semaphores = blk: {
|
||||||
var semaphores: std.ArrayList(vk.Semaphore) = try .initCapacity(allocator_general, swapchain.swapchain_images.len);
|
var semaphores: std.ArrayList(vk.Semaphore) = try .initCapacity(allocator_general, swapchain.swapchain_images.len);
|
||||||
errdefer semaphores.deinit(allocator_general);
|
errdefer semaphores.deinit(allocator_general);
|
||||||
@@ -255,7 +256,7 @@ pub fn init() !Game {
|
|||||||
var point_lights = try shaders.PointLightBuffer.init(.{
|
var point_lights = try shaders.PointLightBuffer.init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = max_point_lights,
|
.capacity = max_point_lights,
|
||||||
.name = "PointLights",
|
.name = "PointLights",
|
||||||
});
|
});
|
||||||
errdefer point_lights.deinit();
|
errdefer point_lights.deinit();
|
||||||
@@ -263,7 +264,7 @@ pub fn init() !Game {
|
|||||||
var directional_lights = try shaders.DirectionalLightBuffer.init(.{
|
var directional_lights = try shaders.DirectionalLightBuffer.init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = max_directional_lights,
|
.capacity = max_directional_lights,
|
||||||
.name = "DirectionalLights",
|
.name = "DirectionalLights",
|
||||||
});
|
});
|
||||||
errdefer directional_lights.deinit();
|
errdefer directional_lights.deinit();
|
||||||
@@ -620,8 +621,8 @@ pub fn init() !Game {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try point_lights.write(.{ .elements = &point_lights_data });
|
try point_lights.writeSlice(&point_lights_data);
|
||||||
try directional_lights.write(.{ .elements = &directional_lights_data });
|
try directional_lights.writeSlice(&directional_lights_data);
|
||||||
|
|
||||||
var skybox = try Skybox.load("skybox.hdr", 512, global_uniforms.buffer);
|
var skybox = try Skybox.load("skybox.hdr", 512, global_uniforms.buffer);
|
||||||
errdefer skybox.deinit();
|
errdefer skybox.deinit();
|
||||||
@@ -748,6 +749,7 @@ pub fn init() !Game {
|
|||||||
|
|
||||||
.global_uniforms = global_uniforms,
|
.global_uniforms = global_uniforms,
|
||||||
.global_uniforms_staging_buffer = global_uniforms_staging_buffer,
|
.global_uniforms_staging_buffer = global_uniforms_staging_buffer,
|
||||||
|
.global_uniforms_staging_ptr = global_uniforms_staging_ptr,
|
||||||
.global_uniforms_transfer_semaphores = global_uniforms_transfer_semaphores,
|
.global_uniforms_transfer_semaphores = global_uniforms_transfer_semaphores,
|
||||||
.point_lights = point_lights,
|
.point_lights = point_lights,
|
||||||
.directional_lights = directional_lights,
|
.directional_lights = directional_lights,
|
||||||
@@ -780,6 +782,7 @@ pub fn deinit(self: *Game) void {
|
|||||||
self.skybox.deinit();
|
self.skybox.deinit();
|
||||||
|
|
||||||
self.global_uniforms.deinit();
|
self.global_uniforms.deinit();
|
||||||
|
self.global_uniforms_staging_buffer.unmap();
|
||||||
self.global_uniforms_staging_buffer.deinit();
|
self.global_uniforms_staging_buffer.deinit();
|
||||||
self.point_lights.deinit();
|
self.point_lights.deinit();
|
||||||
self.directional_lights.deinit();
|
self.directional_lights.deinit();
|
||||||
@@ -905,7 +908,7 @@ fn render(self: *Game) !void {
|
|||||||
|
|
||||||
const ambient_light = vm.Vector3.init(0.01, 0.01, 0.01);
|
const ambient_light = vm.Vector3.init(0.01, 0.01, 0.01);
|
||||||
|
|
||||||
const global_uniforms_data: shaders.GlobalUniforms = .{
|
self.global_uniforms_staging_ptr.* = .{
|
||||||
.matrixWStoVS = matrix_ws_to_vs,
|
.matrixWStoVS = matrix_ws_to_vs,
|
||||||
.matrixVStoCS = matrix_vs_to_cs,
|
.matrixVStoCS = matrix_vs_to_cs,
|
||||||
.matrixSSPXtoCS = matrix_sspx_to_cs,
|
.matrixSSPXtoCS = matrix_sspx_to_cs,
|
||||||
@@ -914,10 +917,7 @@ fn render(self: *Game) !void {
|
|||||||
.directionalLightCount = directional_lights_data.len,
|
.directionalLightCount = directional_lights_data.len,
|
||||||
.ambientLight = ambient_light,
|
.ambientLight = ambient_light,
|
||||||
};
|
};
|
||||||
|
try self.global_uniforms_staging_buffer.flush(0, 1);
|
||||||
const staging_memory = try self.global_uniforms_staging_buffer.map();
|
|
||||||
@memcpy(staging_memory, std.mem.asBytes(&global_uniforms_data));
|
|
||||||
self.global_uniforms_staging_buffer.unmap();
|
|
||||||
|
|
||||||
try self.deferred_command_buffers.ensureUnusedCapacity(allocator_general, 1);
|
try self.deferred_command_buffers.ensureUnusedCapacity(allocator_general, 1);
|
||||||
const global_uniforms_transfer_command_buffer = try CommandBuffer.init(.transfer);
|
const global_uniforms_transfer_command_buffer = try CommandBuffer.init(.transfer);
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ codepoint_glyph_id: std.hash_map.AutoHashMapUnmanaged(u21, u16),
|
|||||||
kerning_em: std.hash_map.AutoHashMapUnmanaged([2]u16, f32),
|
kerning_em: std.hash_map.AutoHashMapUnmanaged([2]u16, f32),
|
||||||
cap_height_em: f32,
|
cap_height_em: f32,
|
||||||
|
|
||||||
glyph_data: GenericBuffer(void, shaders.GlyphData),
|
glyph_data: GenericBuffer(shaders.GlyphData),
|
||||||
control_points: GenericBuffer(void, [2]f16),
|
control_points: GenericBuffer([2]f16),
|
||||||
band_data: GenericBuffer(void, u32),
|
band_data: GenericBuffer(u32),
|
||||||
|
|
||||||
const BandHelper = struct {
|
const BandHelper = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
@@ -394,39 +394,39 @@ pub fn init(ttf_buffer: []const u8, init_info: InitInfo) !Font {
|
|||||||
|
|
||||||
// std.debug.print("Kerning table size: {d}\n", .{kerning_em.size});
|
// std.debug.print("Kerning table size: {d}\n", .{kerning_em.size});
|
||||||
|
|
||||||
var glyph_data: GenericBuffer(void, shaders.GlyphData) = try .init(.{
|
var glyph_data: GenericBuffer(shaders.GlyphData) = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = @intCast(gpu_glyph_data.items.len),
|
.capacity = @intCast(gpu_glyph_data.items.len),
|
||||||
.name = "Glyph data",
|
.name = "Glyph data",
|
||||||
});
|
});
|
||||||
errdefer glyph_data.deinit();
|
errdefer glyph_data.deinit();
|
||||||
|
|
||||||
// std.debug.print("Glyph data size: {d} [B]\n", .{gpu_glyph_data.items.len * @sizeOf(shaders.GlyphData)});
|
// std.debug.print("Glyph data size: {d} [B]\n", .{gpu_glyph_data.items.len * @sizeOf(shaders.GlyphData)});
|
||||||
|
|
||||||
var control_points: GenericBuffer(void, [2]f16) = try .init(.{
|
var control_points: GenericBuffer([2]f16) = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = @intCast(control_points_array.items.len),
|
.capacity = @intCast(control_points_array.items.len),
|
||||||
.name = "Control points",
|
.name = "Control points",
|
||||||
});
|
});
|
||||||
errdefer control_points.deinit();
|
errdefer control_points.deinit();
|
||||||
|
|
||||||
// std.debug.print("Control points size: {d} [B]\n", .{control_points_array.items.len * @sizeOf([2]f16)});
|
// std.debug.print("Control points size: {d} [B]\n", .{control_points_array.items.len * @sizeOf([2]f16)});
|
||||||
|
|
||||||
var band_data: GenericBuffer(void, u32) = try .init(.{
|
var band_data: GenericBuffer(u32) = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = @intCast(band_data_array.items.len),
|
.capacity = @intCast(band_data_array.items.len),
|
||||||
.name = "Band data",
|
.name = "Band data",
|
||||||
});
|
});
|
||||||
errdefer band_data.deinit();
|
errdefer band_data.deinit();
|
||||||
|
|
||||||
// std.debug.print("Band data size: {d} [B]\n", .{band_data_array.items.len * @sizeOf(u32)});
|
// std.debug.print("Band data size: {d} [B]\n", .{band_data_array.items.len * @sizeOf(u32)});
|
||||||
|
|
||||||
try glyph_data.write(.{ .elements = gpu_glyph_data.items });
|
try glyph_data.writeSlice(gpu_glyph_data.items);
|
||||||
try control_points.write(.{ .elements = control_points_array.items });
|
try control_points.writeSlice(control_points_array.items);
|
||||||
try band_data.write(.{ .elements = band_data_array.items });
|
try band_data.writeSlice(band_data_array.items);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.cpu_glyph_data = cpu_glyph_data.toOwnedSliceAssert(),
|
.cpu_glyph_data = cpu_glyph_data.toOwnedSliceAssert(),
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ const vk = @import("vulkan");
|
|||||||
|
|
||||||
const CommandBuffer = @import("CommandBuffer.zig");
|
const CommandBuffer = @import("CommandBuffer.zig");
|
||||||
const Engine = @import("Engine.zig");
|
const Engine = @import("Engine.zig");
|
||||||
const StagingBuffer = @import("StagingBuffer.zig");
|
|
||||||
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
||||||
|
|
||||||
pub const Usage = enum {
|
pub const Usage = enum {
|
||||||
@@ -14,6 +13,7 @@ pub const Usage = enum {
|
|||||||
index,
|
index,
|
||||||
vertex,
|
vertex,
|
||||||
indirect,
|
indirect,
|
||||||
|
staging,
|
||||||
|
|
||||||
pub fn asBufferUsageFlags(self: Usage) vk.BufferUsageFlags {
|
pub fn asBufferUsageFlags(self: Usage) vk.BufferUsageFlags {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
@@ -22,6 +22,7 @@ pub const Usage = enum {
|
|||||||
.index => .{ .transfer_dst_bit = true, .index_buffer_bit = true },
|
.index => .{ .transfer_dst_bit = true, .index_buffer_bit = true },
|
||||||
.vertex => .{ .transfer_dst_bit = true, .vertex_buffer_bit = true },
|
.vertex => .{ .transfer_dst_bit = true, .vertex_buffer_bit = true },
|
||||||
.indirect => .{ .transfer_dst_bit = true, .indirect_buffer_bit = true },
|
.indirect => .{ .transfer_dst_bit = true, .indirect_buffer_bit = true },
|
||||||
|
.staging => .{ .transfer_src_bit = true },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -29,34 +30,27 @@ pub const Usage = enum {
|
|||||||
pub const InitInfo = struct {
|
pub const InitInfo = struct {
|
||||||
usage: Usage,
|
usage: Usage,
|
||||||
target_queue: TargetQueue,
|
target_queue: TargetQueue,
|
||||||
array_capacity: u32 = 0,
|
mappable: bool = false,
|
||||||
|
capacity: u32 = 1,
|
||||||
name: ?[]const u8 = null,
|
name: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
pub fn GenericBuffer(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
buffer: vk.Buffer,
|
buffer: vk.Buffer,
|
||||||
device_memory: vk.DeviceMemory,
|
device_memory: vk.DeviceMemory,
|
||||||
|
mappable: bool,
|
||||||
target_queue: TargetQueue,
|
target_queue: TargetQueue,
|
||||||
array_capacity: u32,
|
capacity: u32,
|
||||||
|
|
||||||
const header_size: u32 = @sizeOf(Header);
|
const element_size: u32 = @sizeOf(T);
|
||||||
const element_size: u32 = @sizeOf(Element);
|
|
||||||
const array_offset: u32 = std.mem.alignForward(usize, header_size, @alignOf(Element));
|
|
||||||
|
|
||||||
pub const WriteInfo = struct {
|
|
||||||
header: ?Header = null,
|
|
||||||
element_offset: u32 = 0,
|
|
||||||
elements: []const Element = &.{},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn init(init_info: InitInfo) !Self {
|
pub fn init(init_info: InitInfo) !Self {
|
||||||
const engine = ctx.engine;
|
const engine = ctx.engine;
|
||||||
|
|
||||||
const array_size = try std.math.mul(u32, init_info.array_capacity, element_size);
|
const size = try std.math.mul(u32, init_info.capacity, element_size);
|
||||||
const size = try std.math.add(u32, array_offset, array_size);
|
|
||||||
|
|
||||||
const target_queue_family = switch (init_info.target_queue) {
|
const target_queue_family = switch (init_info.target_queue) {
|
||||||
.graphics => engine.graphics_queue.allocation.family,
|
.graphics => engine.graphics_queue.allocation.family,
|
||||||
@@ -71,14 +65,17 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
|||||||
});
|
});
|
||||||
errdefer engine.destroyBuffer(buffer);
|
errdefer engine.destroyBuffer(buffer);
|
||||||
if (init_info.name) |name| {
|
if (init_info.name) |name| {
|
||||||
engine.setObjectName(buffer, "B {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) });
|
engine.setObjectName(buffer, "B {s} [{s}]", .{ name, @typeName(T) });
|
||||||
}
|
}
|
||||||
|
|
||||||
const memory_requirements = engine.getBufferMemoryRequirements(buffer);
|
const memory_requirements = engine.getBufferMemoryRequirements(buffer);
|
||||||
const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
const device_memory = try engine.allocate(memory_requirements, .{
|
||||||
|
.device_local_bit = !init_info.mappable,
|
||||||
|
.host_visible_bit = init_info.mappable,
|
||||||
|
});
|
||||||
errdefer engine.freeMemory(device_memory);
|
errdefer engine.freeMemory(device_memory);
|
||||||
if (init_info.name) |name| {
|
if (init_info.name) |name| {
|
||||||
engine.setObjectName(device_memory, "DM {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) });
|
engine.setObjectName(device_memory, "DM {s} [{s}]", .{ name, @typeName(T) });
|
||||||
}
|
}
|
||||||
|
|
||||||
try engine.bindBufferMemory(buffer, device_memory, 0);
|
try engine.bindBufferMemory(buffer, device_memory, 0);
|
||||||
@@ -86,8 +83,9 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
|||||||
return .{
|
return .{
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
.device_memory = device_memory,
|
.device_memory = device_memory,
|
||||||
|
.mappable = init_info.mappable,
|
||||||
.target_queue = init_info.target_queue,
|
.target_queue = init_info.target_queue,
|
||||||
.array_capacity = init_info.array_capacity,
|
.capacity = init_info.capacity,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,120 +100,130 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
|||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(self: Self, write_info: WriteInfo) !void {
|
pub fn write(self: Self, value: T) !void {
|
||||||
const engine = ctx.engine;
|
return self.writeSliceAt(0, &.{value});
|
||||||
|
|
||||||
const element_count = std.math.cast(u32, write_info.elements.len) orelse return error.Overflow;
|
|
||||||
std.debug.assert(write_info.element_offset + element_count <= self.array_capacity);
|
|
||||||
|
|
||||||
const header_write_size: u32 = if (write_info.header != null) header_size else 0;
|
|
||||||
const array_write_size = element_count * element_size;
|
|
||||||
const array_write_offset: u32 = if (header_write_size > 0) array_offset else 0;
|
|
||||||
const write_size = array_write_offset + array_write_size;
|
|
||||||
|
|
||||||
if (write_size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var regions_buffer: [2]vk.BufferCopy = undefined;
|
|
||||||
var regions: std.ArrayList(vk.BufferCopy) = .initBuffer(®ions_buffer);
|
|
||||||
|
|
||||||
// One continuous write
|
|
||||||
if (header_write_size > 0 and array_write_size > 0 and write_info.element_offset == 0) {
|
|
||||||
regions.appendAssumeCapacity(.{
|
|
||||||
.src_offset = 0,
|
|
||||||
.dst_offset = 0,
|
|
||||||
.size = write_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Separate writes for header and array (if they exist)
|
|
||||||
else {
|
|
||||||
if (header_write_size > 0) {
|
|
||||||
regions.appendAssumeCapacity(.{
|
|
||||||
.src_offset = 0,
|
|
||||||
.dst_offset = 0,
|
|
||||||
.size = header_write_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (array_write_size > 0) {
|
|
||||||
regions.appendAssumeCapacity(.{
|
|
||||||
.src_offset = array_write_offset,
|
|
||||||
.dst_offset = array_offset + write_info.element_offset * element_size,
|
|
||||||
.size = array_write_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std.debug.assert(regions.items.len > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
var staging_buffer: StagingBuffer = try .init(.{
|
|
||||||
.target_queue = self.target_queue,
|
|
||||||
.capacity = write_size,
|
|
||||||
});
|
|
||||||
defer staging_buffer.deinit();
|
|
||||||
|
|
||||||
const staging_memory = try staging_buffer.map();
|
|
||||||
if (write_info.header) |header| {
|
|
||||||
@memcpy(staging_memory[0..header_size], std.mem.asBytes(&header));
|
|
||||||
}
|
|
||||||
@memcpy(staging_memory[array_write_offset..write_size], std.mem.sliceAsBytes(write_info.elements));
|
|
||||||
staging_buffer.unmap();
|
|
||||||
|
|
||||||
var command_buffer: CommandBuffer = try .init(.transfer);
|
|
||||||
defer command_buffer.deinit();
|
|
||||||
|
|
||||||
try command_buffer.beginCommandBuffer();
|
|
||||||
command_buffer.copyBuffer(staging_buffer.buffer, self.buffer, regions.items);
|
|
||||||
try command_buffer.endCommandBuffer();
|
|
||||||
|
|
||||||
const fence = try engine.createFence(.{});
|
|
||||||
defer engine.destroyFence(fence);
|
|
||||||
|
|
||||||
try command_buffer.submit(.{ .fence = fence });
|
|
||||||
try engine.waitForFence(fence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeRaw(self: Self, data_offset: u32, data: []const u8) !void {
|
pub fn writeAt(self: Self, index: u32, value: T) !void {
|
||||||
|
return self.writeSliceAt(index, &.{value});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeSlice(self: Self, values: []const T) !void {
|
||||||
|
return self.writeSliceAt(0, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeSliceAt(self: Self, first_index: u32, values: []const T) !void {
|
||||||
const engine = ctx.engine;
|
const engine = ctx.engine;
|
||||||
|
|
||||||
const array_size = self.array_capacity * element_size;
|
const element_count = std.math.cast(u32, values.len) orelse return error.Overflow;
|
||||||
const size = array_offset + array_size;
|
std.debug.assert(first_index + element_count <= self.capacity);
|
||||||
|
|
||||||
const data_size = std.math.cast(u32, data.len) orelse return error.Overflow;
|
const write_size = element_count * element_size;
|
||||||
std.debug.assert(data_offset + data_size <= size);
|
if (element_count == 0) return;
|
||||||
|
|
||||||
var staging_buffer = try StagingBuffer.init(engine, .{
|
if (self.mappable) {
|
||||||
.target_queue = self.target_queue,
|
const slice = try self.mapSliceAt(first_index, element_count);
|
||||||
.capacity = data_size,
|
defer self.unmap();
|
||||||
});
|
|
||||||
defer staging_buffer.deinit(engine);
|
|
||||||
|
|
||||||
const staging_memory = try staging_buffer.map(engine);
|
@memcpy(slice, values);
|
||||||
@memcpy(staging_memory, data);
|
try self.flush(first_index, element_count);
|
||||||
staging_buffer.unmap(engine);
|
} else {
|
||||||
|
var staging_buffer: GenericBuffer(T) = try .init(.{
|
||||||
|
.usage = .staging,
|
||||||
|
.target_queue = self.target_queue,
|
||||||
|
.mappable = true,
|
||||||
|
.capacity = element_count,
|
||||||
|
});
|
||||||
|
defer staging_buffer.deinit();
|
||||||
|
|
||||||
var command_buffer = try CommandBuffer.init(engine, .transfer);
|
{
|
||||||
defer command_buffer.deinit(engine);
|
const staging_slice = try staging_buffer.mapSlice();
|
||||||
|
defer staging_buffer.unmap();
|
||||||
|
|
||||||
try command_buffer.beginCommandBuffer(.{});
|
@memcpy(staging_slice, values);
|
||||||
command_buffer.copyBuffer(
|
try staging_buffer.flush(0, element_count);
|
||||||
staging_buffer.buffer,
|
}
|
||||||
self.buffer,
|
|
||||||
&.{
|
var command_buffer: CommandBuffer = try .init(.transfer);
|
||||||
|
defer command_buffer.deinit();
|
||||||
|
|
||||||
|
try command_buffer.beginCommandBuffer();
|
||||||
|
const regions = [_]vk.BufferCopy{
|
||||||
.{
|
.{
|
||||||
.src_offset = 0,
|
.src_offset = 0,
|
||||||
.dst_offset = data_offset,
|
.dst_offset = first_index * element_size,
|
||||||
.size = data_size,
|
.size = write_size,
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
command_buffer.copyBuffer(staging_buffer.buffer, self.buffer, ®ions);
|
||||||
|
try command_buffer.endCommandBuffer();
|
||||||
|
|
||||||
|
const fence = try engine.createFence(.{});
|
||||||
|
defer engine.destroyFence(fence);
|
||||||
|
|
||||||
|
try command_buffer.submit(.{ .fence = fence });
|
||||||
|
try engine.waitForFence(fence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map(self: Self) !*T {
|
||||||
|
std.debug.assert(self.mappable);
|
||||||
|
|
||||||
|
const slice = try self.mapSliceAt(0, 1);
|
||||||
|
return &slice[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mapAt(self: Self, index: u32) !*T {
|
||||||
|
std.debug.assert(self.mappable);
|
||||||
|
|
||||||
|
const slice = try self.mapSliceAt(index, 1);
|
||||||
|
return &slice[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mapSlice(self: Self) ![]T {
|
||||||
|
std.debug.assert(self.mappable);
|
||||||
|
|
||||||
|
return self.mapSliceAt(0, self.capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mapSliceAt(self: Self, first_index: u32, count: u32) ![]T {
|
||||||
|
const engine = ctx.engine;
|
||||||
|
|
||||||
|
std.debug.assert(self.mappable);
|
||||||
|
std.debug.assert(first_index + count <= self.capacity);
|
||||||
|
|
||||||
|
const byte_offset = @as(u64, first_index) * @as(u64, element_size);
|
||||||
|
const byte_length = @as(u64, count) * @as(u64, element_size);
|
||||||
|
|
||||||
|
const mapped_memory = try engine.mapMemory(self.device_memory, byte_offset, byte_length, .{});
|
||||||
|
const slice = @as([*]T, @ptrCast(@alignCast(mapped_memory.ptr)))[0..count];
|
||||||
|
|
||||||
|
return slice;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush(self: Self, first_index: u32, count: u32) !void {
|
||||||
|
const engine = ctx.engine;
|
||||||
|
|
||||||
|
std.debug.assert(self.mappable);
|
||||||
|
std.debug.assert(first_index + count <= self.capacity);
|
||||||
|
|
||||||
|
const byte_offset = @as(u64, first_index) * @as(u64, element_size);
|
||||||
|
const byte_length = @as(u64, count) * @as(u64, element_size);
|
||||||
|
|
||||||
|
try engine.device.flushMappedMemoryRanges(&.{
|
||||||
|
.{
|
||||||
|
.memory = self.device_memory,
|
||||||
|
.offset = byte_offset,
|
||||||
|
.size = byte_length,
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
try command_buffer.endCommandBuffer();
|
}
|
||||||
|
|
||||||
const fence = try engine.createFence(.{});
|
pub fn unmap(self: Self) void {
|
||||||
defer engine.destroyFence(fence);
|
const engine = ctx.engine;
|
||||||
|
|
||||||
try command_buffer.submit(engine, .{ .fence = fence });
|
std.debug.assert(self.mappable);
|
||||||
try engine.waitForFence(fence);
|
engine.unmapMemory(self.device_memory);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ pub const Batch = struct {
|
|||||||
instance_count: u32,
|
instance_count: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
box_gpu_buffer: GenericBuffer(void, Draw.Box),
|
box_gpu_buffer: GenericBuffer(Draw.Box),
|
||||||
text_gpu_buffer: GenericBuffer(void, Draw.Text),
|
text_gpu_buffer: GenericBuffer(Draw.Text),
|
||||||
image_gpu_buffer: GenericBuffer(void, Draw.Image),
|
image_gpu_buffer: GenericBuffer(Draw.Image),
|
||||||
|
|
||||||
box_cpu_buffer: std.ArrayList(Draw.Box),
|
box_cpu_buffer: std.ArrayList(Draw.Box),
|
||||||
text_cpu_buffer: std.ArrayList(Draw.Text),
|
text_cpu_buffer: std.ArrayList(Draw.Text),
|
||||||
@@ -91,26 +91,26 @@ pub fn init() !*Gui {
|
|||||||
|
|
||||||
const gui = try allocator_persistent.create(Gui);
|
const gui = try allocator_persistent.create(Gui);
|
||||||
|
|
||||||
var box_gpu_buffer: GenericBuffer(void, Draw.Box) = try .init(.{
|
var box_gpu_buffer: GenericBuffer(Draw.Box) = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = max_box_draws,
|
.capacity = max_box_draws,
|
||||||
.name = "GUI box draws",
|
.name = "GUI box draws",
|
||||||
});
|
});
|
||||||
errdefer box_gpu_buffer.deinit();
|
errdefer box_gpu_buffer.deinit();
|
||||||
|
|
||||||
var text_gpu_buffer: GenericBuffer(void, Draw.Text) = try .init(.{
|
var text_gpu_buffer: GenericBuffer(Draw.Text) = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = max_text_draws,
|
.capacity = max_text_draws,
|
||||||
.name = "GUI text draws",
|
.name = "GUI text draws",
|
||||||
});
|
});
|
||||||
errdefer text_gpu_buffer.deinit();
|
errdefer text_gpu_buffer.deinit();
|
||||||
|
|
||||||
var image_gpu_buffer: GenericBuffer(void, Draw.Image) = try .init(.{
|
var image_gpu_buffer: GenericBuffer(Draw.Image) = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = max_image_draws,
|
.capacity = max_image_draws,
|
||||||
.name = "GUI image draws",
|
.name = "GUI image draws",
|
||||||
});
|
});
|
||||||
errdefer image_gpu_buffer.deinit();
|
errdefer image_gpu_buffer.deinit();
|
||||||
@@ -123,13 +123,11 @@ pub fn init() !*Gui {
|
|||||||
var index_buffer = try shaders.IndexBuffer.init(.{
|
var index_buffer = try shaders.IndexBuffer.init(.{
|
||||||
.usage = .index,
|
.usage = .index,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = 6,
|
.capacity = 6,
|
||||||
.name = "QuadIB",
|
.name = "QuadIB",
|
||||||
});
|
});
|
||||||
errdefer index_buffer.deinit();
|
errdefer index_buffer.deinit();
|
||||||
try index_buffer.write(.{
|
try index_buffer.writeSlice(&.{ 0, 1, 2, 2, 1, 3 });
|
||||||
.elements = &.{ 0, 1, 2, 2, 1, 3 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const sampler = try engine.createSampler(.{
|
const sampler = try engine.createSampler(.{
|
||||||
.mag_filter = .linear,
|
.mag_filter = .linear,
|
||||||
@@ -842,9 +840,9 @@ fn extendOrAddBatch(self: *Gui, draw_type: std.meta.DeclEnum(Draw), instance: u3
|
|||||||
pub fn draw(self: *const Gui, command_buffer: CommandBuffer) !void {
|
pub fn draw(self: *const Gui, command_buffer: CommandBuffer) !void {
|
||||||
command_buffer.bindIndexBuffer(self.index_buffer.buffer, 0, .uint16);
|
command_buffer.bindIndexBuffer(self.index_buffer.buffer, 0, .uint16);
|
||||||
|
|
||||||
try self.box_gpu_buffer.write(.{ .elements = self.box_cpu_buffer.items });
|
try self.box_gpu_buffer.writeSlice(self.box_cpu_buffer.items);
|
||||||
try self.text_gpu_buffer.write(.{ .elements = self.text_cpu_buffer.items });
|
try self.text_gpu_buffer.writeSlice(self.text_cpu_buffer.items);
|
||||||
try self.image_gpu_buffer.write(.{ .elements = self.image_cpu_buffer.items });
|
try self.image_gpu_buffer.writeSlice(self.image_cpu_buffer.items);
|
||||||
|
|
||||||
for (self.batches.items) |batch| {
|
for (self.batches.items) |batch| {
|
||||||
switch (batch.draw_type) {
|
switch (batch.draw_type) {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ pub fn init() !*Materials {
|
|||||||
materials.material_buffer = try .init(.{
|
materials.material_buffer = try .init(.{
|
||||||
.usage = .storage,
|
.usage = .storage,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = max_materials,
|
.capacity = max_materials,
|
||||||
.name = "Materials",
|
.name = "Materials",
|
||||||
});
|
});
|
||||||
errdefer materials.material_buffer.deinit();
|
errdefer materials.material_buffer.deinit();
|
||||||
@@ -114,11 +114,7 @@ pub fn init() !*Materials {
|
|||||||
};
|
};
|
||||||
|
|
||||||
materials.array.appendSliceAssumeCapacity(&material_data);
|
materials.array.appendSliceAssumeCapacity(&material_data);
|
||||||
|
try materials.material_buffer.writeSlice(&material_data);
|
||||||
try materials.material_buffer.write(.{
|
|
||||||
.element_offset = Id.empty.toInt(),
|
|
||||||
.elements = &material_data,
|
|
||||||
});
|
|
||||||
|
|
||||||
std.debug.assert(materials.array.items.len == @typeInfo(Id).@"enum".fields.len);
|
std.debug.assert(materials.array.items.len == @typeInfo(Id).@"enum".fields.len);
|
||||||
return materials;
|
return materials;
|
||||||
@@ -314,26 +310,20 @@ fn loadMaterial(self: *Materials, filename: []const u8, index: u32) !shaders.Mat
|
|||||||
.allocate = .alloc_if_needed,
|
.allocate = .alloc_if_needed,
|
||||||
});
|
});
|
||||||
|
|
||||||
const material_data = [_]shaders.Material{
|
const material_data: shaders.Material = .{
|
||||||
.{
|
.base_color = .initArray(material_json.baseColor),
|
||||||
.base_color = .initArray(material_json.baseColor),
|
.emissive = .initArray(material_json.emissive),
|
||||||
.emissive = .initArray(material_json.emissive),
|
.ior = material_json.ior,
|
||||||
.ior = material_json.ior,
|
.metallic = material_json.metallic,
|
||||||
.metallic = material_json.metallic,
|
.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(material_json.baseColorTexture, .base_color),
|
||||||
.base_color_texture = try textures.getOrLoad(material_json.baseColorTexture, .base_color),
|
.emissive_texture = try textures.getOrLoad(material_json.emissiveTexture, .emissive),
|
||||||
.emissive_texture = try textures.getOrLoad(material_json.emissiveTexture, .emissive),
|
.normal_texture = try textures.getOrLoad(material_json.normalTexture, .normal),
|
||||||
.normal_texture = try textures.getOrLoad(material_json.normalTexture, .normal),
|
.occlusion_roughness_metallic_texture = try textures.getOrLoad(material_json.occlusionRoughnessMetallicTexture, .occlusion_roughness_metallic),
|
||||||
.occlusion_roughness_metallic_texture = try textures.getOrLoad(material_json.occlusionRoughnessMetallicTexture, .occlusion_roughness_metallic),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.material_buffer.write(.{
|
try self.material_buffer.writeAt(index, material_data);
|
||||||
.element_offset = index,
|
return material_data;
|
||||||
.elements = &material_data,
|
|
||||||
});
|
|
||||||
|
|
||||||
return material_data[0];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ const vm = @import("vecmath");
|
|||||||
const CommandBuffer = @import("CommandBuffer.zig");
|
const CommandBuffer = @import("CommandBuffer.zig");
|
||||||
const Engine = @import("Engine.zig");
|
const Engine = @import("Engine.zig");
|
||||||
const GenericBuffer = @import("GenericBuffer.zig").GenericBuffer;
|
const GenericBuffer = @import("GenericBuffer.zig").GenericBuffer;
|
||||||
const StagingBuffer = @import("StagingBuffer.zig");
|
|
||||||
const Swapchain = @import("Swapchain.zig");
|
const Swapchain = @import("Swapchain.zig");
|
||||||
const Texture = @import("Texture.zig");
|
const Texture = @import("Texture.zig");
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ image: vk.Image,
|
|||||||
image_view: vk.ImageView,
|
image_view: vk.ImageView,
|
||||||
device_memory: vk.DeviceMemory,
|
device_memory: vk.DeviceMemory,
|
||||||
|
|
||||||
vertex_buffer: GenericBuffer(void, vm.Vector3),
|
vertex_buffer: GenericBuffer(vm.Vector3),
|
||||||
index_buffer: shaders.IndexBuffer,
|
index_buffer: shaders.IndexBuffer,
|
||||||
sampler: vk.Sampler,
|
sampler: vk.Sampler,
|
||||||
|
|
||||||
@@ -69,15 +68,21 @@ pub fn load(
|
|||||||
|
|
||||||
// --- LOAD IMAGE INTO STAGING BUFFER --------------------------------------
|
// --- LOAD IMAGE INTO STAGING BUFFER --------------------------------------
|
||||||
|
|
||||||
var staging_buffer = try StagingBuffer.init(.{
|
var staging_buffer = try GenericBuffer(vm.ColorHdr).init(.{
|
||||||
.capacity = @intCast(img.width * img.height * @sizeOf(vm.ColorHdr)),
|
.usage = .staging,
|
||||||
.target_queue = .compute,
|
.target_queue = .compute,
|
||||||
|
.mappable = true,
|
||||||
|
.capacity = img.width * img.height,
|
||||||
});
|
});
|
||||||
defer staging_buffer.deinit();
|
defer staging_buffer.deinit();
|
||||||
|
|
||||||
const staging_memory = try staging_buffer.map();
|
{
|
||||||
@memcpy(staging_memory, @as([*]const u8, @ptrCast(img.data)));
|
const staging_memory = try staging_buffer.mapSlice();
|
||||||
staging_buffer.unmap();
|
defer staging_buffer.unmap();
|
||||||
|
|
||||||
|
@memcpy(staging_memory, img.data);
|
||||||
|
try staging_buffer.flush(0, img.width * img.height);
|
||||||
|
}
|
||||||
|
|
||||||
// --- CREATE EQUIRECTANGULAR IMAGE ----------------------------------------
|
// --- CREATE EQUIRECTANGULAR IMAGE ----------------------------------------
|
||||||
|
|
||||||
@@ -495,10 +500,10 @@ pub fn load(
|
|||||||
|
|
||||||
// --- SKYBOX PIPELINE -----------------------------------------------------
|
// --- SKYBOX PIPELINE -----------------------------------------------------
|
||||||
|
|
||||||
var vertex_buffer = try GenericBuffer(void, vm.Vector3).init(.{
|
var vertex_buffer = try GenericBuffer(vm.Vector3).init(.{
|
||||||
.usage = .vertex,
|
.usage = .vertex,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = 8,
|
.capacity = 8,
|
||||||
});
|
});
|
||||||
errdefer vertex_buffer.deinit();
|
errdefer vertex_buffer.deinit();
|
||||||
|
|
||||||
@@ -510,47 +515,43 @@ pub fn load(
|
|||||||
// ┃╱ ┃╱ │╱
|
// ┃╱ ┃╱ │╱
|
||||||
// 0━━━━1 O────X
|
// 0━━━━1 O────X
|
||||||
|
|
||||||
try vertex_buffer.write(.{
|
try vertex_buffer.writeSlice(&.{
|
||||||
.elements = &.{
|
.init(-1, -1, -1),
|
||||||
.init(-1, -1, -1),
|
.init(1, -1, -1),
|
||||||
.init(1, -1, -1),
|
.init(-1, 1, -1),
|
||||||
.init(-1, 1, -1),
|
.init(1, 1, -1),
|
||||||
.init(1, 1, -1),
|
.init(-1, -1, 1),
|
||||||
.init(-1, -1, 1),
|
.init(1, -1, 1),
|
||||||
.init(1, -1, 1),
|
.init(-1, 1, 1),
|
||||||
.init(-1, 1, 1),
|
.init(1, 1, 1),
|
||||||
.init(1, 1, 1),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var index_buffer = try GenericBuffer(void, u16).init(.{
|
var index_buffer: shaders.IndexBuffer = try .init(.{
|
||||||
.usage = .index,
|
.usage = .index,
|
||||||
.target_queue = .graphics,
|
.target_queue = .graphics,
|
||||||
.array_capacity = 36,
|
.capacity = 36,
|
||||||
});
|
});
|
||||||
errdefer index_buffer.deinit();
|
errdefer index_buffer.deinit();
|
||||||
|
|
||||||
try index_buffer.write(.{
|
try index_buffer.writeSlice(&.{
|
||||||
.elements = &.{
|
// Positive X
|
||||||
// Positive X
|
3, 1, 7,
|
||||||
3, 1, 7,
|
7, 1, 5,
|
||||||
7, 1, 5,
|
// Negative X
|
||||||
// Negative X
|
0, 2, 4,
|
||||||
0, 2, 4,
|
4, 2, 6,
|
||||||
4, 2, 6,
|
// Positive Y
|
||||||
// Positive Y
|
2, 3, 6,
|
||||||
2, 3, 6,
|
6, 3, 7,
|
||||||
6, 3, 7,
|
// Negative Y
|
||||||
// Negative Y
|
1, 0, 5,
|
||||||
1, 0, 5,
|
5, 0, 4,
|
||||||
5, 0, 4,
|
// Positive Z
|
||||||
// Positive Z
|
6, 7, 4,
|
||||||
6, 7, 4,
|
4, 7, 5,
|
||||||
4, 7, 5,
|
// Negative Z
|
||||||
// Negative Z
|
0, 1, 2,
|
||||||
0, 1, 2,
|
2, 1, 3,
|
||||||
2, 1, 3,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const descriptor_set_layout = try engine.createDescriptorSetLayout(.{
|
const descriptor_set_layout = try engine.createDescriptorSetLayout(.{
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
const StagingBuffer = @This();
|
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const ctx = @import("../AppContext.zig");
|
|
||||||
const vk = @import("vulkan");
|
|
||||||
|
|
||||||
const Engine = @import("Engine.zig");
|
|
||||||
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
|
||||||
|
|
||||||
buffer: vk.Buffer,
|
|
||||||
device_memory: vk.DeviceMemory,
|
|
||||||
capacity: u32,
|
|
||||||
|
|
||||||
pub const InitInfo = struct {
|
|
||||||
target_queue: TargetQueue,
|
|
||||||
capacity: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn init(init_info: InitInfo) !StagingBuffer {
|
|
||||||
const engine = ctx.engine;
|
|
||||||
|
|
||||||
const target_queue_family = switch (init_info.target_queue) {
|
|
||||||
.graphics => engine.graphics_queue.allocation.family,
|
|
||||||
.compute => engine.compute_queue.allocation.family,
|
|
||||||
};
|
|
||||||
const transfer_queue_family = engine.transfer_queue.allocation.family;
|
|
||||||
|
|
||||||
const buffer = try engine.createBuffer(.{
|
|
||||||
.size = init_info.capacity,
|
|
||||||
.usage = .{
|
|
||||||
.transfer_src_bit = true,
|
|
||||||
},
|
|
||||||
.queue_family_indices = &.{ target_queue_family, transfer_queue_family },
|
|
||||||
});
|
|
||||||
errdefer engine.destroyBuffer(buffer);
|
|
||||||
|
|
||||||
const memory_requirements = engine.getBufferMemoryRequirements(buffer);
|
|
||||||
const device_memory = try engine.allocate(
|
|
||||||
memory_requirements,
|
|
||||||
.{
|
|
||||||
.host_visible_bit = true,
|
|
||||||
.host_coherent_bit = true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
errdefer engine.freeMemory(device_memory);
|
|
||||||
|
|
||||||
try engine.bindBufferMemory(buffer, device_memory, 0);
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.buffer = buffer,
|
|
||||||
.device_memory = device_memory,
|
|
||||||
.capacity = init_info.capacity,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *StagingBuffer) void {
|
|
||||||
const engine = ctx.engine;
|
|
||||||
|
|
||||||
std.log.scoped(.deinit).debug("Deinitializing {*}", .{self});
|
|
||||||
|
|
||||||
engine.freeMemory(self.device_memory);
|
|
||||||
engine.destroyBuffer(self.buffer);
|
|
||||||
|
|
||||||
self.* = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map(self: StagingBuffer) ![]u8 {
|
|
||||||
const mapped_memory = try self.mapPartial(0, self.capacity);
|
|
||||||
return mapped_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mapPartial(self: StagingBuffer, offset: u32, len: u32) ![]u8 {
|
|
||||||
const engine = ctx.engine;
|
|
||||||
|
|
||||||
const mapped_memory = try engine.mapMemory(self.device_memory, offset, len, .{});
|
|
||||||
return mapped_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unmap(self: StagingBuffer) void {
|
|
||||||
const engine = ctx.engine;
|
|
||||||
|
|
||||||
engine.unmapMemory(self.device_memory);
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ const vk = @import("vulkan");
|
|||||||
const CommandBuffer = @import("CommandBuffer.zig");
|
const CommandBuffer = @import("CommandBuffer.zig");
|
||||||
const DeviceAllocation = @import("DeviceAllocation.zig");
|
const DeviceAllocation = @import("DeviceAllocation.zig");
|
||||||
const Engine = @import("Engine.zig");
|
const Engine = @import("Engine.zig");
|
||||||
const StagingBuffer = @import("StagingBuffer.zig");
|
const GenericBuffer = @import("GenericBuffer.zig").GenericBuffer;
|
||||||
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
||||||
|
|
||||||
pub const Usage = enum {
|
pub const Usage = enum {
|
||||||
@@ -207,15 +207,21 @@ pub fn writeRaw(self: Texture, data: []const u8) !void {
|
|||||||
std.debug.assert(data.len == byte_length);
|
std.debug.assert(data.len == byte_length);
|
||||||
std.debug.assert(self.usage != .depth);
|
std.debug.assert(self.usage != .depth);
|
||||||
|
|
||||||
var staging_buffer = try StagingBuffer.init(.{
|
var staging_buffer = try GenericBuffer(u8).init(.{
|
||||||
.capacity = @intCast(byte_length),
|
.usage = .staging,
|
||||||
.target_queue = self.target_queue,
|
.target_queue = self.target_queue,
|
||||||
|
.mappable = true,
|
||||||
|
.capacity = @intCast(byte_length),
|
||||||
});
|
});
|
||||||
defer staging_buffer.deinit();
|
defer staging_buffer.deinit();
|
||||||
|
|
||||||
const staging_memory = try staging_buffer.map();
|
{
|
||||||
@memcpy(staging_memory, data);
|
const staging_memory = try staging_buffer.mapSlice();
|
||||||
staging_buffer.unmap();
|
defer staging_buffer.unmap();
|
||||||
|
|
||||||
|
@memcpy(staging_memory, data);
|
||||||
|
try staging_buffer.flush(0, byte_length);
|
||||||
|
}
|
||||||
|
|
||||||
// --- TRANSITION TO TRANSFER_DST_OPTIMAL AND COPY -----------------
|
// --- TRANSITION TO TRANSFER_DST_OPTIMAL AND COPY -----------------
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ const Materials = @import("engine/Materials.zig");
|
|||||||
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
||||||
const Textures = @import("engine/Textures.zig");
|
const Textures = @import("engine/Textures.zig");
|
||||||
|
|
||||||
pub const VertexBuffer = GenericBuffer(void, Vertex);
|
pub const VertexBuffer = GenericBuffer(Vertex);
|
||||||
pub const IndexBuffer = GenericBuffer(void, Index);
|
pub const IndexBuffer = GenericBuffer(Index);
|
||||||
pub const GlobalUniformsBuffer = GenericBuffer(GlobalUniforms, void);
|
pub const GlobalUniformsBuffer = GenericBuffer(GlobalUniforms);
|
||||||
pub const PointLightBuffer = GenericBuffer(void, PointLight);
|
pub const PointLightBuffer = GenericBuffer(PointLight);
|
||||||
pub const DirectionalLightBuffer = GenericBuffer(void, DirectionalLight);
|
pub const DirectionalLightBuffer = GenericBuffer(DirectionalLight);
|
||||||
pub const MaterialBuffer = GenericBuffer(void, Material);
|
pub const MaterialBuffer = GenericBuffer(Material);
|
||||||
pub const ObjectUniformsBuffer = GenericBuffer(void, ObjectUniforms);
|
pub const ObjectUniformsBuffer = GenericBuffer(ObjectUniforms);
|
||||||
|
|
||||||
pub const Vertex = extern struct {
|
pub const Vertex = extern struct {
|
||||||
positionOS: vm.Vector3,
|
positionOS: vm.Vector3,
|
||||||
|
|||||||
Reference in New Issue
Block a user