Compare commits

..

5 Commits

19 changed files with 412 additions and 419 deletions

View File

@@ -1,22 +1,28 @@
{ {
"walls": { "walls": {
"positive_x": { "positive_x": {
"material": "OakLogTop.json" "material": "OakLogTop.json",
"transform": "identity"
}, },
"negative_x": { "negative_x": {
"material": "OakLogTop.json" "material": "OakLogTop.json",
"transform": "mirror"
}, },
"positive_y": { "positive_y": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_ccw"
}, },
"negative_y": { "negative_y": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_cw"
}, },
"positive_z": { "positive_z": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_cw"
}, },
"negative_z": { "negative_z": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_cw"
} }
} }
} }

View File

@@ -1,22 +1,28 @@
{ {
"walls": { "walls": {
"positive_x": { "positive_x": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_cw"
}, },
"negative_x": { "negative_x": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_ccw"
}, },
"positive_y": { "positive_y": {
"material": "OakLogTop.json" "material": "OakLogTop.json",
"transform": "identity"
}, },
"negative_y": { "negative_y": {
"material": "OakLogTop.json" "material": "OakLogTop.json",
"transform": "mirror"
}, },
"positive_z": { "positive_z": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "identity"
}, },
"negative_z": { "negative_z": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "rotate_180"
} }
} }
} }

View File

@@ -1,22 +1,28 @@
{ {
"walls": { "walls": {
"positive_x": { "positive_x": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "identity"
}, },
"negative_x": { "negative_x": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "identity"
}, },
"positive_y": { "positive_y": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "identity"
}, },
"negative_y": { "negative_y": {
"material": "OakLog.json" "material": "OakLog.json",
"transform": "identity"
}, },
"positive_z": { "positive_z": {
"material": "OakLogTop.json" "material": "OakLogTop.json",
"transform": "identity"
}, },
"negative_z": { "negative_z": {
"material": "OakLogTop.json" "material": "OakLogTop.json",
"transform": "mirror_rotate_180"
} }
} }
} }

View File

@@ -1,5 +1,5 @@
struct GlobalUniforms { struct GlobalUniforms {
float4x4 matrixWStoVS; float3x4 matrixWStoVS;
float4x4 matrixVStoCS; float4x4 matrixVStoCS;
float2x3 matrixSSPXtoCS; float2x3 matrixSSPXtoCS;
@@ -12,10 +12,10 @@ struct PointLight {
float3 positionWS; float3 positionWS;
float3 color; float3 color;
IncomingLight getIncoming(float4x4 matrixWStoVS, float3 positionVS) { IncomingLight getIncoming(float3x4 matrixWStoVS, float3 positionVS) {
IncomingLight light; IncomingLight light;
let lightPositionVS = mul(matrixWStoVS, float4(positionWS, 1.0)).xyz; let lightPositionVS = mul(matrixWStoVS, float4(positionWS, 1.0));
let lightDirectionVS = normalize(lightPositionVS - positionVS); let lightDirectionVS = normalize(lightPositionVS - positionVS);
let lightDistance = distance(positionVS, lightPositionVS); let lightDistance = distance(positionVS, lightPositionVS);
let lightAttenuation = 1.0 / (lightDistance * lightDistance); let lightAttenuation = 1.0 / (lightDistance * lightDistance);
@@ -31,11 +31,11 @@ struct DirectionalLight {
float3 directionWS; float3 directionWS;
float3 color; float3 color;
IncomingLight getIncoming(float4x4 matrixWStoVS) { IncomingLight getIncoming(float3x4 matrixWStoVS) {
IncomingLight light; IncomingLight light;
light.radiance = color; light.radiance = color;
light.directionVS = normalize(mul(matrixWStoVS, float4(-directionWS, 0.0)).xyz); light.directionVS = normalize(mul(matrixWStoVS, float4(-directionWS, 0.0)));
return light; return light;
} }
} }
@@ -56,8 +56,9 @@ struct Material {
} }
struct ObjectUniforms { struct ObjectUniforms {
float4x4 matrixOStoWS; // Limited to a composition of translation and rotation
float4x4 matrixOStoWSNormal; float3x4 matrixOStoWS;
float2x3 texCoordTransform;
uint16_t material; uint16_t material;
} }

View File

@@ -33,22 +33,24 @@ Varyings vertexMain(Vertex vert, uint instanceID : SV_VulkanInstanceID) {
let object = _Objects[instanceID]; let object = _Objects[instanceID];
let positionWS = mul(object.matrixOStoWS, float4(vert.positionOS, 1.0)).xyz; let positionWS = mul(object.matrixOStoWS, float4(vert.positionOS, 1.0));
let positionVS = mul(_Global.matrixWStoVS, float4(positionWS, 1.0)).xyz; let positionVS = mul(_Global.matrixWStoVS, float4(positionWS, 1.0));
let positionCS = mul(_Global.matrixVStoCS, float4(positionVS, 1.0)); let positionCS = mul(_Global.matrixVStoCS, float4(positionVS, 1.0));
let normalWS = normalize(mul(object.matrixOStoWSNormal, float4(vert.normalOS, 0.0)).xyz); let texCoord = mul(object.texCoordTransform, float3(vert.texCoord, 1.0));
let normalVS = normalize(mul(_Global.matrixWStoVS, float4(normalWS, 0.0)).xyz);
let tangentWS = normalize(mul(object.matrixOStoWSNormal, float4(vert.tangentOS.xyz, 0.0)).xyz); let normalWS = normalize(mul(object.matrixOStoWS, float4(vert.normalOS, 0.0)));
let tangentVS = normalize(mul(_Global.matrixWStoVS, float4(tangentWS, 0.0)).xyz); let normalVS = normalize(mul(_Global.matrixWStoVS, float4(normalWS, 0.0)));
let tangentWS = normalize(mul(object.matrixOStoWS, float4(vert.tangentOS.xyz, 0.0)));
let tangentVS = normalize(mul(_Global.matrixWStoVS, float4(tangentWS, 0.0)));
let bitangentVS = vert.tangentOS.w * normalize(cross(normalVS, tangentVS)); let bitangentVS = vert.tangentOS.w * normalize(cross(normalVS, tangentVS));
out.positionCS = positionCS; out.positionCS = positionCS;
out.instance = instanceID; out.instance = instanceID;
out.positionVS = positionVS; out.positionVS = positionVS;
out.texCoord = vert.texCoord; out.texCoord = texCoord;
out.normalVS = normalVS; out.normalVS = normalVS;
out.tangentVS = tangentVS; out.tangentVS = tangentVS;
out.bitangentVS = bitangentVS; out.bitangentVS = bitangentVS;

View File

@@ -18,7 +18,7 @@ struct Varyings {
Varyings vertexMain(Vertex vert) { Varyings vertexMain(Vertex vert) {
Varyings out; Varyings out;
let directionVS = mul(_Global.matrixWStoVS, float4(vert.directionWS, 0.0)).xyz; let directionVS = mul(_Global.matrixWStoVS, float4(vert.directionWS, 0.0));
let directionCS = mul(_Global.matrixVStoCS, float4(directionVS, 0.0)); let directionCS = mul(_Global.matrixVStoCS, float4(directionVS, 0.0));
out.positionCS = float4(directionCS.xy, 0.0, directionCS.w); out.positionCS = float4(directionCS.xy, 0.0, directionCS.w);

2
castle

Submodule castle updated: af5f035830...99b8cf1d8e

View File

@@ -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();
@@ -120,13 +119,18 @@ pub fn refresh(self: *Chunk, blocks: *const Blocks, neighbors: Neighbors) !void
inline for (@typeInfo(voxels.Orientation).@"enum".fields) |field| { inline for (@typeInfo(voxels.Orientation).@"enum".fields) |field| {
const side = @field(voxels.Orientation, field.name); const side = @field(voxels.Orientation, field.name);
const material = @field(block.walls, field.name).material; const wall: Blocks.Definition.Wall = @field(block.walls, field.name);
if (material != .empty and self.getOpposite(side, ix, iy, iz, blocks, neighbors) == .empty) { if (wall.material != .empty and self.getOpposite(side, ix, iy, iz, blocks, neighbors) == .empty) {
const matrix = getMatrix(side, origin); const matrix = getMatrix(side, origin);
try uniforms.append(allocator_frame, .{ try uniforms.append(allocator_frame, .{
.matrixOStoWS = matrix, .matrixOStoWS = .{
.matrixOStoWSNormal = matrix, matrix.getIVersor().dropW(),
.material = material, matrix.getJVersor().dropW(),
matrix.getKVersor().dropW(),
matrix.getTranslationVector().dropW(),
},
.texCoordTransform = wall.transform.getMatrix(),
.material = wall.material,
}); });
} }
} }
@@ -135,12 +139,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 +173,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;
} }

View File

@@ -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,
@@ -86,9 +86,9 @@ pub fn init() !Game {
.mag_filter = .linear, .mag_filter = .linear,
.min_filter = .linear, .min_filter = .linear,
.mipmap_mode = .linear, .mipmap_mode = .linear,
.address_mode_u = .repeat, .address_mode_u = .clamp_to_edge,
.address_mode_v = .repeat, .address_mode_v = .clamp_to_edge,
.address_mode_w = .repeat, .address_mode_w = .clamp_to_edge,
.mip_lod_bias = 0, .mip_lod_bias = 0,
.anisotropy_enable = .false, .anisotropy_enable = .false,
.max_anisotropy = 0, .max_anisotropy = 0,
@@ -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,8 +908,13 @@ 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.getIVersor().dropW(),
matrix_ws_to_vs.getJVersor().dropW(),
matrix_ws_to_vs.getKVersor().dropW(),
matrix_ws_to_vs.getTranslationVector().dropW(),
},
.matrixVStoCS = matrix_vs_to_cs, .matrixVStoCS = matrix_vs_to_cs,
.matrixSSPXtoCS = matrix_sspx_to_cs, .matrixSSPXtoCS = matrix_sspx_to_cs,
@@ -914,10 +922,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);

View File

@@ -184,9 +184,9 @@ pub const blocks = [9][:0]const u8{
"Bricks.json", "Bricks.json",
"ChiseledStoneBricks.json", "ChiseledStoneBricks.json",
"Cobblestone.json", "Cobblestone.json",
"DiamondBlock.json", "OakLogX.json",
"GoldBlock.json", "OakLogY.json",
"IronBlock.json", "OakLogZ.json",
"OakPlanks.json", "OakPlanks.json",
"SmoothStone.json", "SmoothStone.json",
"StoneBricks.json", "StoneBricks.json",

View File

@@ -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(),

View File

@@ -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(&regions_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, &regions);
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);
} }
}; };
} }

View File

@@ -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,21 +123,19 @@ 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,
.min_filter = .linear, .min_filter = .linear,
.mipmap_mode = .linear, .mipmap_mode = .linear,
.address_mode_u = .repeat, .address_mode_u = .clamp_to_edge,
.address_mode_v = .repeat, .address_mode_v = .clamp_to_edge,
.address_mode_w = .repeat, .address_mode_w = .clamp_to_edge,
.mip_lod_bias = 0, .mip_lod_bias = 0,
.anisotropy_enable = .false, .anisotropy_enable = .false,
.max_anisotropy = 0, .max_anisotropy = 0,
@@ -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) {

View File

@@ -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];
} }

View File

@@ -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(.{

View File

@@ -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);
}

View File

@@ -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 -----------------

View File

@@ -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,
@@ -44,7 +44,7 @@ pub const Vertex = extern struct {
pub const Index = u16; pub const Index = u16;
pub const GlobalUniforms = extern struct { pub const GlobalUniforms = extern struct {
matrixWStoVS: vm.Matrix4x4, matrixWStoVS: [4]vm.Vector3,
matrixVStoCS: vm.Matrix4x4, matrixVStoCS: vm.Matrix4x4,
matrixSSPXtoCS: vm.Matrix3x2, matrixSSPXtoCS: vm.Matrix3x2,
@@ -93,9 +93,9 @@ pub const Material = extern struct {
}; };
pub const ObjectUniforms = extern struct { pub const ObjectUniforms = extern struct {
matrixOStoWS: vm.Matrix4x4, // Limited to a composition of translation and rotation
matrixOStoWSNormal: vm.Matrix4x4, matrixOStoWS: [4]vm.Vector3,
texCoordTransform: vm.Matrix3x2,
material: Materials.Id, material: Materials.Id,
}; };

View File

@@ -59,6 +59,49 @@ pub const Transform = enum(u3) {
mirror_rotate_cw = 5, mirror_rotate_cw = 5,
mirror_rotate_ccw = 6, mirror_rotate_ccw = 6,
mirror_rotate_180 = 7, mirror_rotate_180 = 7,
pub fn getMatrix(self: Transform) vm.Matrix3x2 {
return switch (self) {
// zig fmt: off
.identity => .identity,
.rotate_cw => .init(
0, -1,
1, 0,
0, 1,
),
.rotate_ccw => .init(
0, 1,
-1, 0,
1, 0,
),
.rotate_180 => .init(
-1, 0,
0, -1,
1, 1,
),
.mirror => .init(
-1, 0,
0, 1,
1, 0,
),
.mirror_rotate_cw => .init(
0, -1,
-1, 0,
1, 1,
),
.mirror_rotate_ccw => .init(
0, 1,
1, 0,
0, 0,
),
.mirror_rotate_180 => .init(
0, 1,
-1, 0,
1, 0,
),
// zig fmt: on
};
}
}; };
// ┌──────────────────── x // ┌──────────────────── x