Create descriptor set layout, pipeline, vertex buffer and index buffer
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
.zig-cache
|
.zig-cache
|
||||||
zig-out
|
zig-out
|
||||||
|
*.spv
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ layout(set = 0, binding = 2, scalar) readonly buffer DirectionalLights {
|
|||||||
DirectionalLight lights[];
|
DirectionalLight lights[];
|
||||||
} _DirectionalLights;
|
} _DirectionalLights;
|
||||||
|
|
||||||
layout(set = 0, binding = 3) uniform sampler _Sampler;
|
layout(set = 0, binding = 3, scalar) readonly buffer Materials {
|
||||||
layout(set = 0, binding = 4) uniform texture2D _Textures[];
|
|
||||||
|
|
||||||
layout(set = 0, binding = 5, scalar) readonly buffer Materials {
|
|
||||||
Material _Materials[];
|
Material _Materials[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 4) uniform sampler _Sampler;
|
||||||
|
layout(set = 0, binding = 5) uniform texture2D _Textures[];
|
||||||
|
|
||||||
// --- SET 1 --- PER OBJECT ----------------------------------------------------
|
// --- SET 1 --- PER OBJECT ----------------------------------------------------
|
||||||
|
|
||||||
layout(set = 1, binding = 0, scalar) uniform ObjectUniforms {
|
layout(set = 1, binding = 0, scalar) uniform ObjectUniforms {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
"assets",
|
||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"src",
|
||||||
|
|||||||
5
compile_shaders.sh
Normal file
5
compile_shaders.sh
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
glslc --target-env=vulkan1.2 assets/shaders/equirect_to_cube.comp -o src/shaders/equirect_to_cube_comp.spv
|
||||||
|
glslc --target-env=vulkan1.2 assets/shaders/main.frag -o src/shaders/main_frag.spv
|
||||||
|
glslc --target-env=vulkan1.2 assets/shaders/main.vert -o src/shaders/main_vert.spv
|
||||||
364
src/Game.zig
364
src/Game.zig
@@ -2,6 +2,7 @@ const Game = @This();
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const glfw = @import("zglfw");
|
const glfw = @import("zglfw");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
const math = @import("math.zig");
|
const math = @import("math.zig");
|
||||||
|
|
||||||
@@ -9,14 +10,32 @@ const Atoms = @import("assets/Atoms.zig");
|
|||||||
const Textures = @import("assets/Textures.zig");
|
const Textures = @import("assets/Textures.zig");
|
||||||
const Materials = @import("assets/Materials.zig");
|
const Materials = @import("assets/Materials.zig");
|
||||||
const Swapchain = @import("engine/Swapchain.zig");
|
const Swapchain = @import("engine/Swapchain.zig");
|
||||||
|
const VertexBuffer = @import("engine/VertexBuffer.zig");
|
||||||
|
const IndexBuffer = @import("engine/IndexBuffer.zig");
|
||||||
const Iterator3 = math.Iterator3;
|
const Iterator3 = math.Iterator3;
|
||||||
const Matrix4x4 = math.Matrix4x4;
|
const Matrix4x4 = math.Matrix4x4;
|
||||||
const Quaternion = math.Quaternion;
|
const Quaternion = math.Quaternion;
|
||||||
const Vector2 = math.Vector2;
|
const Vector2 = math.Vector2;
|
||||||
const Vector3 = math.Vector3;
|
const Vector3 = math.Vector3;
|
||||||
|
|
||||||
|
const Vertex = extern struct {
|
||||||
|
positionOS: [3]f32,
|
||||||
|
texCoord: [2]u16,
|
||||||
|
normalOS: [3]i8,
|
||||||
|
tangentOS: [4]i8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main_vert_spv align(4) = @embedFile("shaders/main_vert.spv").*;
|
||||||
|
const main_frag_spv align(4) = @embedFile("shaders/main_frag.spv").*;
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
swapchain: *Swapchain,
|
swapchain: *Swapchain,
|
||||||
|
global_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||||
|
per_object_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||||
|
pipeline_layout: vk.PipelineLayout,
|
||||||
|
pipeline: vk.Pipeline,
|
||||||
|
vertex_buffer: VertexBuffer,
|
||||||
|
index_buffer: IndexBuffer,
|
||||||
|
|
||||||
atoms: Atoms,
|
atoms: Atoms,
|
||||||
materials: Materials,
|
materials: Materials,
|
||||||
@@ -52,6 +71,271 @@ pub fn init(allocator: std.mem.Allocator, swapchain: *Swapchain) !Game {
|
|||||||
errdefer textures.deinit(swapchain.engine);
|
errdefer textures.deinit(swapchain.engine);
|
||||||
|
|
||||||
_ = try materials.getOrLoadId(swapchain.engine, &textures, &atoms, try atoms.getOrPutAtom("Bricks.json"));
|
_ = try materials.getOrLoadId(swapchain.engine, &textures, &atoms, try atoms.getOrPutAtom("Bricks.json"));
|
||||||
|
_ = try materials.getOrLoadId(swapchain.engine, &textures, &atoms, try atoms.getOrPutAtom("Dirt.json"));
|
||||||
|
_ = try materials.getOrLoadId(swapchain.engine, &textures, &atoms, try atoms.getOrPutAtom("Gold.json"));
|
||||||
|
_ = try materials.getOrLoadId(swapchain.engine, &textures, &atoms, try atoms.getOrPutAtom("Stone.json"));
|
||||||
|
|
||||||
|
const device = swapchain.engine.device;
|
||||||
|
const interface = &swapchain.engine.vk_allocator.interface;
|
||||||
|
|
||||||
|
const global_descriptor_set_layout_bindings = [_]vk.DescriptorSetLayoutBinding{
|
||||||
|
.{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptor_type = .uniform_buffer,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.binding = 1,
|
||||||
|
.descriptor_type = .storage_buffer,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.binding = 2,
|
||||||
|
.descriptor_type = .storage_buffer,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.binding = 3,
|
||||||
|
.descriptor_type = .storage_buffer,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.binding = 4,
|
||||||
|
.descriptor_type = .sampler,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.binding = 5,
|
||||||
|
.descriptor_type = .sampled_image,
|
||||||
|
.descriptor_count = 1024,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const global_descriptor_set_layout_bindings_flags = [_]vk.DescriptorBindingFlags{
|
||||||
|
.{},
|
||||||
|
.{},
|
||||||
|
.{},
|
||||||
|
.{},
|
||||||
|
.{},
|
||||||
|
.{ .variable_descriptor_count_bit = true },
|
||||||
|
};
|
||||||
|
|
||||||
|
std.debug.assert(global_descriptor_set_layout_bindings.len == global_descriptor_set_layout_bindings_flags.len);
|
||||||
|
|
||||||
|
const global_descriptor_set_layout = try device.createDescriptorSetLayout(&.{
|
||||||
|
.p_next = &vk.DescriptorSetLayoutBindingFlagsCreateInfo{
|
||||||
|
.binding_count = global_descriptor_set_layout_bindings_flags.len,
|
||||||
|
.p_binding_flags = &global_descriptor_set_layout_bindings_flags,
|
||||||
|
},
|
||||||
|
.binding_count = global_descriptor_set_layout_bindings.len,
|
||||||
|
.p_bindings = &global_descriptor_set_layout_bindings,
|
||||||
|
}, interface);
|
||||||
|
errdefer device.destroyDescriptorSetLayout(global_descriptor_set_layout, interface);
|
||||||
|
|
||||||
|
const per_object_descriptor_set_layout_bindings = [_]vk.DescriptorSetLayoutBinding{
|
||||||
|
.{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptor_type = .uniform_buffer_dynamic,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const per_object_descriptor_set_layout = try device.createDescriptorSetLayout(&.{
|
||||||
|
.binding_count = per_object_descriptor_set_layout_bindings.len,
|
||||||
|
.p_bindings = &per_object_descriptor_set_layout_bindings,
|
||||||
|
}, interface);
|
||||||
|
errdefer device.destroyDescriptorSetLayout(per_object_descriptor_set_layout, interface);
|
||||||
|
|
||||||
|
const descriptor_set_layouts = [_]vk.DescriptorSetLayout{
|
||||||
|
global_descriptor_set_layout,
|
||||||
|
per_object_descriptor_set_layout,
|
||||||
|
};
|
||||||
|
|
||||||
|
const pipeline_layout = try device.createPipelineLayout(&.{
|
||||||
|
.set_layout_count = descriptor_set_layouts.len,
|
||||||
|
.p_set_layouts = &descriptor_set_layouts,
|
||||||
|
}, interface);
|
||||||
|
errdefer device.destroyPipelineLayout(pipeline_layout, interface);
|
||||||
|
|
||||||
|
const vertex_shader = try device.createShaderModule(&.{
|
||||||
|
.code_size = main_vert_spv.len,
|
||||||
|
.p_code = @ptrCast(&main_vert_spv),
|
||||||
|
}, interface);
|
||||||
|
defer device.destroyShaderModule(vertex_shader, interface);
|
||||||
|
|
||||||
|
const fragment_shader = try device.createShaderModule(&.{
|
||||||
|
.code_size = main_frag_spv.len,
|
||||||
|
.p_code = @ptrCast(&main_frag_spv),
|
||||||
|
}, interface);
|
||||||
|
defer device.destroyShaderModule(fragment_shader, interface);
|
||||||
|
|
||||||
|
var vertex_buffer: VertexBuffer = try .init(swapchain.engine, Vertex, 4);
|
||||||
|
errdefer vertex_buffer.deinit(swapchain.engine);
|
||||||
|
try vertex_buffer.write(Vertex, swapchain.engine, &.{
|
||||||
|
.{
|
||||||
|
.positionOS = .{ -0.5, -0.5, 0 },
|
||||||
|
.texCoord = .{ 0, 65535 },
|
||||||
|
.normalOS = .{ 127, 0, 0 },
|
||||||
|
.tangentOS = .{ 127, 0, 0, -127 },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.positionOS = .{ 0.5, -0.5, 0 },
|
||||||
|
.texCoord = .{ 65535, 65535 },
|
||||||
|
.normalOS = .{ 127, 0, 0 },
|
||||||
|
.tangentOS = .{ 127, 0, 0, -127 },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.positionOS = .{ -0.5, 0.5, 0 },
|
||||||
|
.texCoord = .{ 0, 0 },
|
||||||
|
.normalOS = .{ 127, 0, 0 },
|
||||||
|
.tangentOS = .{ 127, 0, 0, -127 },
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.positionOS = .{ 0.5, 0.5, 0 },
|
||||||
|
.texCoord = .{ 65535, 0 },
|
||||||
|
.normalOS = .{ 127, 0, 0 },
|
||||||
|
.tangentOS = .{ 127, 0, 0, -127 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var index_buffer: IndexBuffer = try .init(swapchain.engine, 6);
|
||||||
|
errdefer index_buffer.deinit(swapchain.engine);
|
||||||
|
try index_buffer.write(swapchain.engine, &.{ 0, 1, 2, 2, 1, 3 });
|
||||||
|
|
||||||
|
const pipeline_shader_stages = [_]vk.PipelineShaderStageCreateInfo{
|
||||||
|
.{
|
||||||
|
.stage = .{ .vertex_bit = true },
|
||||||
|
.module = vertex_shader,
|
||||||
|
.p_name = "main",
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.stage = .{ .fragment_bit = true },
|
||||||
|
.module = fragment_shader,
|
||||||
|
.p_name = "main",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vertex_input_binding_descriptions = [_]vk.VertexInputBindingDescription{
|
||||||
|
.{
|
||||||
|
.binding = 0,
|
||||||
|
.stride = @sizeOf(Vertex),
|
||||||
|
.input_rate = .vertex,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vertex_input_attribute_descriptions = [_]vk.VertexInputAttributeDescription{
|
||||||
|
.{
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = .r32g32b32_sfloat,
|
||||||
|
.offset = @offsetOf(Vertex, "positionOS"),
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = .r16g16_unorm,
|
||||||
|
.offset = @offsetOf(Vertex, "texCoord"),
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.location = 2,
|
||||||
|
.binding = 0,
|
||||||
|
.format = .r8g8b8_snorm,
|
||||||
|
.offset = @offsetOf(Vertex, "normalOS"),
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.location = 3,
|
||||||
|
.binding = 0,
|
||||||
|
.format = .r8g8b8a8_snorm,
|
||||||
|
.offset = @offsetOf(Vertex, "tangentOS"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const pipeline_color_blend_attachment_states = [_]vk.PipelineColorBlendAttachmentState{
|
||||||
|
.{
|
||||||
|
.blend_enable = .false,
|
||||||
|
.src_color_blend_factor = .one,
|
||||||
|
.dst_color_blend_factor = .zero,
|
||||||
|
.color_blend_op = .add,
|
||||||
|
.src_alpha_blend_factor = .one,
|
||||||
|
.dst_alpha_blend_factor = .zero,
|
||||||
|
.alpha_blend_op = .add,
|
||||||
|
.color_write_mask = .{
|
||||||
|
.r_bit = true,
|
||||||
|
.g_bit = true,
|
||||||
|
.b_bit = true,
|
||||||
|
.a_bit = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const dynamic_states = [_]vk.DynamicState{ .viewport, .scissor };
|
||||||
|
|
||||||
|
var pipeline: vk.Pipeline = undefined;
|
||||||
|
_ = try device.createGraphicsPipelines(.null_handle, 1, &.{
|
||||||
|
.{
|
||||||
|
.stage_count = pipeline_shader_stages.len,
|
||||||
|
.p_stages = &pipeline_shader_stages,
|
||||||
|
.p_vertex_input_state = &.{
|
||||||
|
.vertex_binding_description_count = vertex_input_binding_descriptions.len,
|
||||||
|
.p_vertex_binding_descriptions = &vertex_input_binding_descriptions,
|
||||||
|
.vertex_attribute_description_count = vertex_input_attribute_descriptions.len,
|
||||||
|
.p_vertex_attribute_descriptions = &vertex_input_attribute_descriptions,
|
||||||
|
},
|
||||||
|
.p_input_assembly_state = &.{
|
||||||
|
.topology = .triangle_list,
|
||||||
|
.primitive_restart_enable = .false,
|
||||||
|
},
|
||||||
|
.p_viewport_state = &.{
|
||||||
|
.viewport_count = 1,
|
||||||
|
.p_viewports = undefined,
|
||||||
|
.scissor_count = 1,
|
||||||
|
.p_scissors = undefined,
|
||||||
|
},
|
||||||
|
.p_rasterization_state = &.{
|
||||||
|
.depth_clamp_enable = .false,
|
||||||
|
.rasterizer_discard_enable = .false,
|
||||||
|
.polygon_mode = .fill,
|
||||||
|
.cull_mode = .{ .back_bit = true },
|
||||||
|
.front_face = .counter_clockwise,
|
||||||
|
.depth_bias_enable = .false,
|
||||||
|
.depth_bias_constant_factor = 0,
|
||||||
|
.depth_bias_clamp = 0,
|
||||||
|
.depth_bias_slope_factor = 0,
|
||||||
|
.line_width = 1,
|
||||||
|
},
|
||||||
|
.p_multisample_state = &.{
|
||||||
|
.rasterization_samples = .{ .@"1_bit" = true },
|
||||||
|
.sample_shading_enable = .false,
|
||||||
|
.min_sample_shading = 1,
|
||||||
|
.alpha_to_coverage_enable = .false,
|
||||||
|
.alpha_to_one_enable = .false,
|
||||||
|
},
|
||||||
|
.p_depth_stencil_state = null,
|
||||||
|
.p_color_blend_state = &.{
|
||||||
|
.logic_op_enable = .false,
|
||||||
|
.logic_op = .copy,
|
||||||
|
.attachment_count = pipeline_color_blend_attachment_states.len,
|
||||||
|
.p_attachments = &pipeline_color_blend_attachment_states,
|
||||||
|
.blend_constants = .{ 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
.p_dynamic_state = &.{
|
||||||
|
.dynamic_state_count = dynamic_states.len,
|
||||||
|
.p_dynamic_states = &dynamic_states,
|
||||||
|
},
|
||||||
|
.layout = pipeline_layout,
|
||||||
|
.render_pass = swapchain.render_pass,
|
||||||
|
.subpass = 0,
|
||||||
|
.base_pipeline_index = -1,
|
||||||
|
},
|
||||||
|
}, interface, @ptrCast(&pipeline));
|
||||||
|
errdefer device.destroyPipeline(pipeline, interface);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
@@ -59,10 +343,27 @@ pub fn init(allocator: std.mem.Allocator, swapchain: *Swapchain) !Game {
|
|||||||
.atoms = atoms,
|
.atoms = atoms,
|
||||||
.materials = materials,
|
.materials = materials,
|
||||||
.textures = textures,
|
.textures = textures,
|
||||||
|
.global_descriptor_set_layout = global_descriptor_set_layout,
|
||||||
|
.per_object_descriptor_set_layout = per_object_descriptor_set_layout,
|
||||||
|
.pipeline_layout = pipeline_layout,
|
||||||
|
.pipeline = pipeline,
|
||||||
|
.vertex_buffer = vertex_buffer,
|
||||||
|
.index_buffer = index_buffer,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Game) void {
|
pub fn deinit(self: *Game) void {
|
||||||
|
const device = self.swapchain.engine.device;
|
||||||
|
const interface = &self.swapchain.engine.vk_allocator.interface;
|
||||||
|
|
||||||
|
self.vertex_buffer.deinit(self.swapchain.engine);
|
||||||
|
self.index_buffer.deinit(self.swapchain.engine);
|
||||||
|
|
||||||
|
device.destroyPipeline(self.pipeline, interface);
|
||||||
|
device.destroyPipelineLayout(self.pipeline_layout, interface);
|
||||||
|
device.destroyDescriptorSetLayout(self.per_object_descriptor_set_layout, interface);
|
||||||
|
device.destroyDescriptorSetLayout(self.global_descriptor_set_layout, interface);
|
||||||
|
|
||||||
self.textures.deinit(self.swapchain.engine);
|
self.textures.deinit(self.swapchain.engine);
|
||||||
self.materials.deinit(self.swapchain.engine);
|
self.materials.deinit(self.swapchain.engine);
|
||||||
self.atoms.deinit();
|
self.atoms.deinit();
|
||||||
@@ -76,6 +377,10 @@ pub fn update(self: *Game, dt: f32) void {
|
|||||||
).rotate(self.camera_yaw).mulScalar(player_speed * dt);
|
).rotate(self.camera_yaw).mulScalar(player_speed * dt);
|
||||||
|
|
||||||
self.camera_position = Vector3.add(self.camera_position, camera_d.asVector3(0));
|
self.camera_position = Vector3.add(self.camera_position, camera_d.asVector3(0));
|
||||||
|
|
||||||
|
self.render() catch |err| {
|
||||||
|
std.log.err("Failed to render: {s}", .{@errorName(err)});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onKeyDown(self: *Game, key_code: glfw.Key, mods: glfw.Mods) void {
|
pub fn onKeyDown(self: *Game, key_code: glfw.Key, mods: glfw.Mods) void {
|
||||||
@@ -127,3 +432,62 @@ pub fn onMouseMove(self: *Game, dx: f32, dy: f32) void {
|
|||||||
self.camera_pitch = std.math.clamp(self.camera_pitch, -0.5 * std.math.pi, 0.5 * std.math.pi);
|
self.camera_pitch = std.math.clamp(self.camera_pitch, -0.5 * std.math.pi, 0.5 * std.math.pi);
|
||||||
self.camera_yaw = @mod(self.camera_yaw, 2 * std.math.pi);
|
self.camera_yaw = @mod(self.camera_yaw, 2 * std.math.pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render(self: *Game) !void {
|
||||||
|
const engine = self.swapchain.engine;
|
||||||
|
|
||||||
|
const fence = try engine.device.createFence(&.{}, &engine.vk_allocator.interface);
|
||||||
|
defer engine.device.destroyFence(fence, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
|
const command_buffer = try engine.allocateGraphicsCommandBuffer();
|
||||||
|
defer engine.freeGraphicsCommandBuffer(command_buffer);
|
||||||
|
try command_buffer.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } });
|
||||||
|
|
||||||
|
const viewports = [_]vk.Viewport{
|
||||||
|
.{
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = 0,
|
||||||
|
.height = 0,
|
||||||
|
.min_depth = 0,
|
||||||
|
.max_depth = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
command_buffer.setViewport(0, viewports.len, &viewports);
|
||||||
|
|
||||||
|
const scissors = [_]vk.Rect2D{
|
||||||
|
.{
|
||||||
|
.offset = .{ .x = 0, .y = 0 },
|
||||||
|
.extent = .{ .width = 0, .height = 0 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
command_buffer.setScissor(0, scissors.len, &scissors);
|
||||||
|
|
||||||
|
{
|
||||||
|
const clear_values = [_]vk.ClearValue{
|
||||||
|
.{ .color = .{ .float_32 = .{ 0, 0, 0, 1 } } },
|
||||||
|
};
|
||||||
|
|
||||||
|
command_buffer.beginRenderPass(&.{
|
||||||
|
.render_pass = self.swapchain.render_pass,
|
||||||
|
.framebuffer = self.swapchain.swapchain_images[0].framebuffer,
|
||||||
|
.render_area = .{
|
||||||
|
.offset = .{ .x = 0, .y = 0 },
|
||||||
|
.extent = .{ .width = 0, .height = 0 },
|
||||||
|
},
|
||||||
|
.clear_value_count = clear_values.len,
|
||||||
|
.p_clear_values = &clear_values,
|
||||||
|
}, .@"inline");
|
||||||
|
defer command_buffer.endRenderPass();
|
||||||
|
|
||||||
|
command_buffer.bindPipeline(.graphics, self.pipeline);
|
||||||
|
|
||||||
|
command_buffer.bindVertexBuffers(0, 1, @ptrCast(&self.vertex_buffer.buffer), &.{0});
|
||||||
|
command_buffer.bindIndexBuffer(self.index_buffer.buffer, 0, .uint16);
|
||||||
|
command_buffer.drawIndexed(@intCast(self.index_buffer.index_count), 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
try command_buffer.endCommandBuffer();
|
||||||
|
try engine.submitGraphicsCommandBuffer(command_buffer, fence);
|
||||||
|
_ = try engine.device.waitForFences(1, @ptrCast(&fence), .true, std.math.maxInt(u64));
|
||||||
|
}
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, atoms: *
|
|||||||
};
|
};
|
||||||
|
|
||||||
const filename = atoms.getString(key).?;
|
const filename = atoms.getString(key).?;
|
||||||
|
std.log.debug("Loading material \"{s}\"...", .{filename});
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.fs.cwd();
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine) !Textures {
|
|||||||
|
|
||||||
try empty_base_color_texture.write([4]u8, engine, &.{.{ 255, 255, 255, 255 }});
|
try empty_base_color_texture.write([4]u8, engine, &.{.{ 255, 255, 255, 255 }});
|
||||||
try empty_emissive_texture.write([4]f16, engine, &.{.{ 1.0, 1.0, 1.0, 1.0 }});
|
try empty_emissive_texture.write([4]f16, engine, &.{.{ 1.0, 1.0, 1.0, 1.0 }});
|
||||||
try empty_normal_texture.write([4]u8, engine, &.{.{ 128, 128, 255, 255 }});
|
try empty_normal_texture.write([4]i8, engine, &.{.{ 0, 0, 127, 127 }});
|
||||||
try empty_occlusuion_roughness_metallic_texture.write([4]u8, engine, &.{.{ 255, 255, 255, 255 }});
|
try empty_occlusuion_roughness_metallic_texture.write([4]u8, engine, &.{.{ 255, 255, 255, 255 }});
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
@@ -112,6 +112,8 @@ pub fn getOrLoadId(self: *Textures, engine: *Engine, atoms: *Atoms, key: Key) !I
|
|||||||
|
|
||||||
fn loadTexture(self: *Textures, engine: *Engine, atoms: *Atoms, key: Key) !Texture {
|
fn loadTexture(self: *Textures, engine: *Engine, atoms: *Atoms, key: Key) !Texture {
|
||||||
const filename = atoms.getString(key.atom).?;
|
const filename = atoms.getString(key.atom).?;
|
||||||
|
std.log.debug("Loading texture \"{s}\" as {s}...", .{ filename, @tagName(key.usage) });
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.fs.cwd();
|
||||||
|
|
||||||
var dir = try cwd.openDir("assets/textures", .{});
|
var dir = try cwd.openDir("assets/textures", .{});
|
||||||
|
|||||||
@@ -281,7 +281,15 @@ pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
|
|||||||
try enabled_extensions.appendBounded(vk.extensions.khr_swapchain.name);
|
try enabled_extensions.appendBounded(vk.extensions.khr_swapchain.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var enabled_features_vulkan12: vk.PhysicalDeviceVulkan12Features = .{
|
||||||
|
.descriptor_binding_partially_bound = .true,
|
||||||
|
.descriptor_binding_variable_descriptor_count = .true,
|
||||||
|
.runtime_descriptor_array = .true,
|
||||||
|
.scalar_block_layout = .true,
|
||||||
|
};
|
||||||
|
|
||||||
break :blk try instance.createDevice(physical_device, &.{
|
break :blk try instance.createDevice(physical_device, &.{
|
||||||
|
.p_next = &enabled_features_vulkan12,
|
||||||
.queue_create_info_count = @intCast(queue_create_info.items.len),
|
.queue_create_info_count = @intCast(queue_create_info.items.len),
|
||||||
.p_queue_create_infos = queue_create_info.items.ptr,
|
.p_queue_create_infos = queue_create_info.items.ptr,
|
||||||
.enabled_extension_count = @intCast(enabled_extensions.items.len),
|
.enabled_extension_count = @intCast(enabled_extensions.items.len),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub fn init(engine: *Engine, index_count: usize) !IndexBuffer {
|
|||||||
.queue_family_index_count = qsm.queue_family_index_count,
|
.queue_family_index_count = qsm.queue_family_index_count,
|
||||||
.p_queue_family_indices = qsm.p_queue_family_indices,
|
.p_queue_family_indices = qsm.p_queue_family_indices,
|
||||||
}, &engine.vk_allocator.interface);
|
}, &engine.vk_allocator.interface);
|
||||||
errdefer engine.device.destroyBuffer(buffer);
|
errdefer engine.device.destroyBuffer(buffer, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
||||||
const memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
const memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||||
@@ -42,7 +42,7 @@ pub fn init(engine: *Engine, index_count: usize) !IndexBuffer {
|
|||||||
|
|
||||||
pub fn deinit(self: *IndexBuffer, engine: *Engine) void {
|
pub fn deinit(self: *IndexBuffer, engine: *Engine) void {
|
||||||
engine.device.freeMemory(self.memory, &engine.vk_allocator.interface);
|
engine.device.freeMemory(self.memory, &engine.vk_allocator.interface);
|
||||||
engine.device.destroyBuffer(self.buffer);
|
engine.device.destroyBuffer(self.buffer, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
@@ -50,12 +50,12 @@ pub fn deinit(self: *IndexBuffer, engine: *Engine) void {
|
|||||||
pub fn write(self: IndexBuffer, engine: *Engine, indices: []const u16) !void {
|
pub fn write(self: IndexBuffer, engine: *Engine, indices: []const u16) !void {
|
||||||
std.debug.assert(indices.len == self.index_count);
|
std.debug.assert(indices.len == self.index_count);
|
||||||
|
|
||||||
const fence = try engine.device.createFence(.{}, &engine.vk_allocator.interface);
|
const fence = try engine.device.createFence(&.{}, &engine.vk_allocator.interface);
|
||||||
defer engine.device.destroyFence(fence, &engine.vk_allocator.interface);
|
defer engine.device.destroyFence(fence, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
const size = std.mem.sliceAsBytes(indices).len;
|
const size = std.mem.sliceAsBytes(indices).len;
|
||||||
|
|
||||||
const staging_buffer: StagingBuffer = .init(engine, std.mem.sliceAsBytes(indices), engine.graphics_queue.allocation.family);
|
var staging_buffer: StagingBuffer = try .init(engine, std.mem.sliceAsBytes(indices), engine.graphics_queue.allocation.family);
|
||||||
defer staging_buffer.deinit(engine);
|
defer staging_buffer.deinit(engine);
|
||||||
|
|
||||||
const command_buffer = try engine.allocateTransferCommandBuffer();
|
const command_buffer = try engine.allocateTransferCommandBuffer();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub fn init(engine: *Engine, comptime VertexType: type, vertex_count: usize) !Ve
|
|||||||
.queue_family_index_count = qsm.queue_family_index_count,
|
.queue_family_index_count = qsm.queue_family_index_count,
|
||||||
.p_queue_family_indices = qsm.p_queue_family_indices,
|
.p_queue_family_indices = qsm.p_queue_family_indices,
|
||||||
}, &engine.vk_allocator.interface);
|
}, &engine.vk_allocator.interface);
|
||||||
errdefer engine.device.destroyBuffer(buffer);
|
errdefer engine.device.destroyBuffer(buffer, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
||||||
const memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
const memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||||
@@ -45,7 +45,7 @@ pub fn init(engine: *Engine, comptime VertexType: type, vertex_count: usize) !Ve
|
|||||||
|
|
||||||
pub fn deinit(self: *VertexBuffer, engine: *Engine) void {
|
pub fn deinit(self: *VertexBuffer, engine: *Engine) void {
|
||||||
engine.device.freeMemory(self.memory, &engine.vk_allocator.interface);
|
engine.device.freeMemory(self.memory, &engine.vk_allocator.interface);
|
||||||
engine.device.destroyBuffer(self.buffer);
|
engine.device.destroyBuffer(self.buffer, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
@@ -54,12 +54,12 @@ pub fn write(self: VertexBuffer, comptime VertexType: type, engine: *Engine, ver
|
|||||||
std.debug.assert(vertices.len == self.vertex_count);
|
std.debug.assert(vertices.len == self.vertex_count);
|
||||||
std.debug.assert(@sizeOf(VertexType) == self.vertex_size);
|
std.debug.assert(@sizeOf(VertexType) == self.vertex_size);
|
||||||
|
|
||||||
const fence = try engine.device.createFence(.{}, &engine.vk_allocator.interface);
|
const fence = try engine.device.createFence(&.{}, &engine.vk_allocator.interface);
|
||||||
defer engine.device.destroyFence(fence, &engine.vk_allocator.interface);
|
defer engine.device.destroyFence(fence, &engine.vk_allocator.interface);
|
||||||
|
|
||||||
const size = std.mem.sliceAsBytes(vertices).len;
|
const size = std.mem.sliceAsBytes(vertices).len;
|
||||||
|
|
||||||
const staging_buffer: StagingBuffer = .init(engine, std.mem.sliceAsBytes(vertices), engine.graphics_queue.allocation.family);
|
var staging_buffer: StagingBuffer = try .init(engine, std.mem.sliceAsBytes(vertices), engine.graphics_queue.allocation.family);
|
||||||
defer staging_buffer.deinit(engine);
|
defer staging_buffer.deinit(engine);
|
||||||
|
|
||||||
const command_buffer = try engine.allocateTransferCommandBuffer();
|
const command_buffer = try engine.allocateTransferCommandBuffer();
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const sokol = @import("sokol");
|
|
||||||
|
|
||||||
const sg = sokol.gfx;
|
|
||||||
|
|
||||||
const main = @import("main.zig");
|
|
||||||
|
|
||||||
pub var sampler_cache: std.AutoHashMapUnmanaged(Descriptor, sg.Sampler) = .{};
|
|
||||||
|
|
||||||
pub const Descriptor = struct {
|
|
||||||
wrap_u: sg.Wrap = .REPEAT,
|
|
||||||
wrap_v: sg.Wrap = .REPEAT,
|
|
||||||
wrap_w: sg.Wrap = .REPEAT,
|
|
||||||
min_filter: sg.Filter = .LINEAR,
|
|
||||||
mag_filter: sg.Filter = .LINEAR,
|
|
||||||
mipmap_filter: sg.Filter = .LINEAR,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn getOrCreateSampler(descriptor: Descriptor) !sg.Sampler {
|
|
||||||
const entry = try sampler_cache.getOrPut(main.allocator, descriptor);
|
|
||||||
|
|
||||||
if (entry.found_existing) {
|
|
||||||
return entry.value_ptr.*;
|
|
||||||
} else {
|
|
||||||
const sampler = sg.makeSampler(.{
|
|
||||||
.wrap_u = descriptor.wrap_u,
|
|
||||||
.wrap_v = descriptor.wrap_v,
|
|
||||||
.wrap_w = descriptor.wrap_w,
|
|
||||||
.min_filter = descriptor.min_filter,
|
|
||||||
.mag_filter = descriptor.mag_filter,
|
|
||||||
.mipmap_filter = descriptor.mipmap_filter,
|
|
||||||
});
|
|
||||||
|
|
||||||
entry.key_ptr.* = descriptor;
|
|
||||||
entry.value_ptr.* = sampler;
|
|
||||||
|
|
||||||
return sampler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit() void {
|
|
||||||
var sampler_cache_it = sampler_cache.valueIterator();
|
|
||||||
while (sampler_cache_it.next()) |sampler| {
|
|
||||||
sg.destroySampler(sampler.*);
|
|
||||||
}
|
|
||||||
|
|
||||||
sampler_cache.deinit(main.allocator);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user