Compare commits
2 commits
6f4f600fda
...
849f6b2dae
Author | SHA1 | Date | |
---|---|---|---|
849f6b2dae | |||
32a3accb85 |
7 changed files with 445 additions and 337 deletions
|
@ -1,5 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const sdl = @import("sdl");
|
const sdl = @import("libs/sdl/build.zig");
|
||||||
const vkgen = @import("vulkan_zig");
|
const vkgen = @import("vulkan_zig");
|
||||||
|
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
|
@ -34,7 +34,7 @@ pub fn build(b: *std.Build) void {
|
||||||
|
|
||||||
// SDL2
|
// SDL2
|
||||||
const sdl_sdk = sdl.init(b, null, null);
|
const sdl_sdk = sdl.init(b, null, null);
|
||||||
sdl_sdk.link(exe, .dynamic, .SDL2);
|
sdl_sdk.link(exe, .dynamic, sdl.Library.SDL2);
|
||||||
exe.root_module.addImport("sdl2", sdl_sdk.getWrapperModuleVulkan(vkzig_bindings));
|
exe.root_module.addImport("sdl2", sdl_sdk.getWrapperModuleVulkan(vkzig_bindings));
|
||||||
|
|
||||||
// zmath
|
// zmath
|
||||||
|
|
|
@ -9,18 +9,15 @@
|
||||||
.url = "https://github.com/Snektron/vulkan-zig/archive/9f6e6177b1fdb3ed22231d9216a24480e84cfa5e.tar.gz",
|
.url = "https://github.com/Snektron/vulkan-zig/archive/9f6e6177b1fdb3ed22231d9216a24480e84cfa5e.tar.gz",
|
||||||
.hash = "1220f2961df224f7d35dee774b26194b8b937cc252fa8e4023407776c58521d53e38",
|
.hash = "1220f2961df224f7d35dee774b26194b8b937cc252fa8e4023407776c58521d53e38",
|
||||||
},
|
},
|
||||||
.sdl = .{
|
// .sdl = .{
|
||||||
.url = "https://github.com/MasterQ32/SDL.zig/archive/1432ed3f6a020973906fbc996868131ae1d631be.tar.gz",
|
// .url = "https://github.com/ikskuh/SDL.zig/archive/9663dc70c19b13afcb4b9f596c928d7b2838e548.tar.gz",
|
||||||
.hash = "1220ebeeaade31e207a56977aff537a65e6338cddc68d50217ddf30bbc58fb27d367",
|
// .hash = "12202141beb92d68ef5088538ff761d5c3ecd2d4e11867c89fbbdcd9f814b8cba8ee",
|
||||||
},
|
// },
|
||||||
},
|
},
|
||||||
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"src",
|
||||||
// For example...
|
|
||||||
//"LICENSE",
|
|
||||||
//"README.md",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
1
libs/sdl
Submodule
1
libs/sdl
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 9663dc70c19b13afcb4b9f596c928d7b2838e548
|
|
@ -6,11 +6,11 @@ const Utilities = @import("utilities.zig");
|
||||||
const Vertex = Utilities.Vertex;
|
const Vertex = Utilities.Vertex;
|
||||||
const Device = @import("vulkan_renderer.zig").Device;
|
const Device = @import("vulkan_renderer.zig").Device;
|
||||||
const Instance = @import("vulkan_renderer.zig").Instance;
|
const Instance = @import("vulkan_renderer.zig").Instance;
|
||||||
const UboModel = @import("vulkan_renderer.zig").UboModel;
|
const Model = @import("vulkan_renderer.zig").Model;
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
ubo_model: UboModel,
|
ubo_model: Model,
|
||||||
|
|
||||||
vertex_count: u32,
|
vertex_count: u32,
|
||||||
vertex_buffer: vk.Buffer,
|
vertex_buffer: vk.Buffer,
|
||||||
|
|
|
@ -3,18 +3,18 @@
|
||||||
layout(location = 0) in vec3 pos;
|
layout(location = 0) in vec3 pos;
|
||||||
layout(location = 1) in vec3 col;
|
layout(location = 1) in vec3 col;
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 fragCol;
|
||||||
|
|
||||||
layout(binding = 0) uniform UboViewProjection {
|
layout(binding = 0) uniform UboViewProjection {
|
||||||
mat4 projection;
|
mat4 projection;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
} uboViewProjection;
|
} uboViewProjection;
|
||||||
|
|
||||||
layout(binding = 1) uniform UboModel {
|
layout(push_constant) uniform PushModel {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
} uboModel;
|
} pushModel;
|
||||||
|
|
||||||
layout(location = 0) out vec3 fragCol;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = uboViewProjection.projection * uboViewProjection.view * uboModel.model * vec4(pos, 1.0);
|
gl_Position = uboViewProjection.projection * uboViewProjection.view * pushModel.model * vec4(pos, 1.0);
|
||||||
fragCol = col;
|
fragCol = col;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ const UboViewProjection = struct {
|
||||||
view: zm.Mat align(16),
|
view: zm.Mat align(16),
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const UboModel = struct {
|
pub const Model = struct {
|
||||||
model: zm.Mat align(16),
|
model: zm.Mat align(16),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ pub const VulkanRenderer = struct {
|
||||||
|
|
||||||
// Descriptors
|
// Descriptors
|
||||||
descriptor_set_layout: vk.DescriptorSetLayout,
|
descriptor_set_layout: vk.DescriptorSetLayout,
|
||||||
|
push_constant_range: vk.PushConstantRange,
|
||||||
|
|
||||||
descriptor_pool: vk.DescriptorPool,
|
descriptor_pool: vk.DescriptorPool,
|
||||||
descriptor_sets: []vk.DescriptorSet,
|
descriptor_sets: []vk.DescriptorSet,
|
||||||
|
@ -88,9 +89,6 @@ pub const VulkanRenderer = struct {
|
||||||
vp_uniform_buffer: []vk.Buffer,
|
vp_uniform_buffer: []vk.Buffer,
|
||||||
vp_uniform_buffer_memory: []vk.DeviceMemory,
|
vp_uniform_buffer_memory: []vk.DeviceMemory,
|
||||||
|
|
||||||
model_duniform_buffer: []vk.Buffer,
|
|
||||||
model_duniform_buffer_memory: []vk.DeviceMemory,
|
|
||||||
|
|
||||||
// Pipeline
|
// Pipeline
|
||||||
graphics_pipeline: vk.Pipeline,
|
graphics_pipeline: vk.Pipeline,
|
||||||
pipeline_layout: vk.PipelineLayout,
|
pipeline_layout: vk.PipelineLayout,
|
||||||
|
@ -103,10 +101,6 @@ pub const VulkanRenderer = struct {
|
||||||
swapchain_image_format: vk.Format,
|
swapchain_image_format: vk.Format,
|
||||||
extent: vk.Extent2D,
|
extent: vk.Extent2D,
|
||||||
|
|
||||||
min_uniform_buffer_offset: vk.DeviceSize,
|
|
||||||
model_uniform_alignment: usize,
|
|
||||||
model_transfer_space: [MAX_OBJECTS]UboModel,
|
|
||||||
|
|
||||||
// Synchronisation
|
// Synchronisation
|
||||||
image_available: [MAX_FRAME_DRAWS]vk.Semaphore,
|
image_available: [MAX_FRAME_DRAWS]vk.Semaphore,
|
||||||
render_finished: [MAX_FRAME_DRAWS]vk.Semaphore,
|
render_finished: [MAX_FRAME_DRAWS]vk.Semaphore,
|
||||||
|
@ -134,6 +128,7 @@ pub const VulkanRenderer = struct {
|
||||||
try self.createSwapchain();
|
try self.createSwapchain();
|
||||||
try self.createRenderPass();
|
try self.createRenderPass();
|
||||||
try self.createDescriptorSetLayout();
|
try self.createDescriptorSetLayout();
|
||||||
|
try self.createPushConstantRange();
|
||||||
try self.createGraphicsPipeline();
|
try self.createGraphicsPipeline();
|
||||||
try self.createFramebuffers();
|
try self.createFramebuffers();
|
||||||
try self.createCommandPool();
|
try self.createCommandPool();
|
||||||
|
@ -201,12 +196,10 @@ pub const VulkanRenderer = struct {
|
||||||
self.meshes = [_]Mesh{ first_mesh, second_mesh };
|
self.meshes = [_]Mesh{ first_mesh, second_mesh };
|
||||||
|
|
||||||
try self.createCommandBuffers();
|
try self.createCommandBuffers();
|
||||||
try self.allocateDynamicBufferTransferSpace();
|
|
||||||
try self.createUniformBuffers();
|
try self.createUniformBuffers();
|
||||||
try self.createDescriptorPool();
|
try self.createDescriptorPool();
|
||||||
try self.createDescriptorSets();
|
try self.createDescriptorSets();
|
||||||
|
|
||||||
try self.recordCommands();
|
|
||||||
try self.createSynchronisation();
|
try self.createSynchronisation();
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -220,7 +213,12 @@ pub const VulkanRenderer = struct {
|
||||||
|
|
||||||
pub fn draw(self: *Self) !void {
|
pub fn draw(self: *Self) !void {
|
||||||
// Wait for given fence to signal (open) from last draw before continuing
|
// Wait for given fence to signal (open) from last draw before continuing
|
||||||
_ = try self.device.waitForFences(1, @ptrCast(&self.draw_fences[self.current_frame]), vk.TRUE, std.math.maxInt(u64));
|
_ = try self.device.waitForFences(
|
||||||
|
1,
|
||||||
|
@ptrCast(&self.draw_fences[self.current_frame]),
|
||||||
|
vk.TRUE,
|
||||||
|
std.math.maxInt(u64),
|
||||||
|
);
|
||||||
// Manually reset (close) fences
|
// Manually reset (close) fences
|
||||||
try self.device.resetFences(1, @ptrCast(&self.draw_fences[self.current_frame]));
|
try self.device.resetFences(1, @ptrCast(&self.draw_fences[self.current_frame]));
|
||||||
|
|
||||||
|
@ -233,6 +231,7 @@ pub const VulkanRenderer = struct {
|
||||||
.null_handle,
|
.null_handle,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try self.recordCommands(image_index_result.image_index);
|
||||||
try self.updateUniformBuffers(image_index_result.image_index);
|
try self.updateUniformBuffers(image_index_result.image_index);
|
||||||
|
|
||||||
// -- Submit command buffer to render
|
// -- Submit command buffer to render
|
||||||
|
@ -281,13 +280,9 @@ pub const VulkanRenderer = struct {
|
||||||
for (0..self.swapchain_images.len) |i| {
|
for (0..self.swapchain_images.len) |i| {
|
||||||
self.device.destroyBuffer(self.vp_uniform_buffer[i], null);
|
self.device.destroyBuffer(self.vp_uniform_buffer[i], null);
|
||||||
self.device.freeMemory(self.vp_uniform_buffer_memory[i], null);
|
self.device.freeMemory(self.vp_uniform_buffer_memory[i], null);
|
||||||
self.device.destroyBuffer(self.model_duniform_buffer[i], null);
|
|
||||||
self.device.freeMemory(self.model_duniform_buffer_memory[i], null);
|
|
||||||
}
|
}
|
||||||
self.allocator.free(self.vp_uniform_buffer);
|
self.allocator.free(self.vp_uniform_buffer);
|
||||||
self.allocator.free(self.vp_uniform_buffer_memory);
|
self.allocator.free(self.vp_uniform_buffer_memory);
|
||||||
self.allocator.free(self.model_duniform_buffer);
|
|
||||||
self.allocator.free(self.model_duniform_buffer_memory);
|
|
||||||
self.allocator.free(self.descriptor_sets);
|
self.allocator.free(self.descriptor_sets);
|
||||||
|
|
||||||
for (self.meshes) |mesh| {
|
for (self.meshes) |mesh| {
|
||||||
|
@ -576,16 +571,7 @@ pub const VulkanRenderer = struct {
|
||||||
.p_immutable_samplers = null, // For texture: can make smapler data immutable by specifying in layout
|
.p_immutable_samplers = null, // For texture: can make smapler data immutable by specifying in layout
|
||||||
};
|
};
|
||||||
|
|
||||||
// Model binding info
|
const layout_bindings = [_]vk.DescriptorSetLayoutBinding{vp_layout_binding};
|
||||||
const model_layout_binding: vk.DescriptorSetLayoutBinding = .{
|
|
||||||
.binding = 1,
|
|
||||||
.descriptor_type = .uniform_buffer_dynamic,
|
|
||||||
.descriptor_count = 1,
|
|
||||||
.stage_flags = .{ .vertex_bit = true },
|
|
||||||
.p_immutable_samplers = null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const layout_bindings = [_]vk.DescriptorSetLayoutBinding{ vp_layout_binding, model_layout_binding };
|
|
||||||
|
|
||||||
// Create descriptor set layout with given bindings
|
// Create descriptor set layout with given bindings
|
||||||
const layout_create_info: vk.DescriptorSetLayoutCreateInfo = .{
|
const layout_create_info: vk.DescriptorSetLayoutCreateInfo = .{
|
||||||
|
@ -597,6 +583,15 @@ pub const VulkanRenderer = struct {
|
||||||
self.descriptor_set_layout = try self.device.createDescriptorSetLayout(&layout_create_info, null);
|
self.descriptor_set_layout = try self.device.createDescriptorSetLayout(&layout_create_info, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn createPushConstantRange(self: *Self) !void {
|
||||||
|
// Define push constant values (no 'create' needed)
|
||||||
|
self.push_constant_range = .{
|
||||||
|
.stage_flags = .{ .vertex_bit = true }, // Shader stage push constant will go to
|
||||||
|
.offset = 0, // Offset into given data to pass to push constant
|
||||||
|
.size = @sizeOf(Model), // Size of data being passed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn createGraphicsPipeline(self: *Self) !void {
|
fn createGraphicsPipeline(self: *Self) !void {
|
||||||
// Create shader modules
|
// Create shader modules
|
||||||
const vert = try self.device.createShaderModule(&.{
|
const vert = try self.device.createShaderModule(&.{
|
||||||
|
@ -757,6 +752,8 @@ pub const VulkanRenderer = struct {
|
||||||
const pipeline_layout_create_info: vk.PipelineLayoutCreateInfo = .{
|
const pipeline_layout_create_info: vk.PipelineLayoutCreateInfo = .{
|
||||||
.set_layout_count = 1,
|
.set_layout_count = 1,
|
||||||
.p_set_layouts = @ptrCast(&self.descriptor_set_layout),
|
.p_set_layouts = @ptrCast(&self.descriptor_set_layout),
|
||||||
|
.push_constant_range_count = 1,
|
||||||
|
.p_push_constant_ranges = @ptrCast(&self.push_constant_range),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.pipeline_layout = try self.device.createPipelineLayout(&pipeline_layout_create_info, null);
|
self.pipeline_layout = try self.device.createPipelineLayout(&pipeline_layout_create_info, null);
|
||||||
|
@ -820,6 +817,7 @@ pub const VulkanRenderer = struct {
|
||||||
const pool_create_info: vk.CommandPoolCreateInfo = .{
|
const pool_create_info: vk.CommandPoolCreateInfo = .{
|
||||||
// Queue family type that buffers from this command pool will use
|
// Queue family type that buffers from this command pool will use
|
||||||
.queue_family_index = queue_family_indices.graphics_family.?,
|
.queue_family_index = queue_family_indices.graphics_family.?,
|
||||||
|
.flags = .{ .reset_command_buffer_bit = true },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a graphics queue family command pool
|
// Create a graphics queue family command pool
|
||||||
|
@ -861,14 +859,9 @@ pub const VulkanRenderer = struct {
|
||||||
// View projection buffer size
|
// View projection buffer size
|
||||||
const vp_buffer_size: vk.DeviceSize = @sizeOf(UboViewProjection);
|
const vp_buffer_size: vk.DeviceSize = @sizeOf(UboViewProjection);
|
||||||
|
|
||||||
// Model buffer size
|
|
||||||
const model_buffer_size: vk.DeviceSize = self.model_uniform_alignment * MAX_OBJECTS;
|
|
||||||
|
|
||||||
// One uniform buffer for each image (and by extension, command buffer)
|
// One uniform buffer for each image (and by extension, command buffer)
|
||||||
self.vp_uniform_buffer = try self.allocator.alloc(vk.Buffer, self.swapchain_images.len);
|
self.vp_uniform_buffer = try self.allocator.alloc(vk.Buffer, self.swapchain_images.len);
|
||||||
self.vp_uniform_buffer_memory = try self.allocator.alloc(vk.DeviceMemory, self.swapchain_images.len);
|
self.vp_uniform_buffer_memory = try self.allocator.alloc(vk.DeviceMemory, self.swapchain_images.len);
|
||||||
self.model_duniform_buffer = try self.allocator.alloc(vk.Buffer, self.swapchain_images.len);
|
|
||||||
self.model_duniform_buffer_memory = try self.allocator.alloc(vk.DeviceMemory, self.swapchain_images.len);
|
|
||||||
|
|
||||||
// Create the uniform buffers
|
// Create the uniform buffers
|
||||||
for (0..self.vp_uniform_buffer.len) |i| {
|
for (0..self.vp_uniform_buffer.len) |i| {
|
||||||
|
@ -882,17 +875,6 @@ pub const VulkanRenderer = struct {
|
||||||
&self.vp_uniform_buffer[i],
|
&self.vp_uniform_buffer[i],
|
||||||
&self.vp_uniform_buffer_memory[i],
|
&self.vp_uniform_buffer_memory[i],
|
||||||
);
|
);
|
||||||
|
|
||||||
try Utilities.createBuffer(
|
|
||||||
self.physical_device,
|
|
||||||
self.instance,
|
|
||||||
self.device,
|
|
||||||
model_buffer_size,
|
|
||||||
.{ .uniform_buffer_bit = true },
|
|
||||||
.{ .host_visible_bit = true, .host_coherent_bit = true },
|
|
||||||
&self.model_duniform_buffer[i],
|
|
||||||
&self.model_duniform_buffer_memory[i],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,14 +886,8 @@ pub const VulkanRenderer = struct {
|
||||||
.descriptor_count = @intCast(self.vp_uniform_buffer.len),
|
.descriptor_count = @intCast(self.vp_uniform_buffer.len),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Model pool (dynamic)
|
|
||||||
const model_pool_size: vk.DescriptorPoolSize = .{
|
|
||||||
.type = .uniform_buffer_dynamic,
|
|
||||||
.descriptor_count = @intCast(self.model_duniform_buffer.len),
|
|
||||||
};
|
|
||||||
|
|
||||||
// List of pool sizes
|
// List of pool sizes
|
||||||
const descriptor_pool_sizes = [_]vk.DescriptorPoolSize{ vp_pool_size, model_pool_size };
|
const descriptor_pool_sizes = [_]vk.DescriptorPoolSize{vp_pool_size};
|
||||||
|
|
||||||
// Data to create descriptor pool
|
// Data to create descriptor pool
|
||||||
const pool_create_info: vk.DescriptorPoolCreateInfo = .{
|
const pool_create_info: vk.DescriptorPoolCreateInfo = .{
|
||||||
|
@ -966,27 +942,8 @@ pub const VulkanRenderer = struct {
|
||||||
.p_texel_buffer_view = undefined,
|
.p_texel_buffer_view = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
// -- Model descriptor
|
|
||||||
// Model buffer binding info
|
|
||||||
const model_buffer_info: vk.DescriptorBufferInfo = .{
|
|
||||||
.buffer = self.model_duniform_buffer[i],
|
|
||||||
.offset = 0,
|
|
||||||
.range = self.model_uniform_alignment,
|
|
||||||
};
|
|
||||||
|
|
||||||
const model_set_write: vk.WriteDescriptorSet = .{
|
|
||||||
.dst_set = self.descriptor_sets[i],
|
|
||||||
.dst_binding = 1,
|
|
||||||
.dst_array_element = 0,
|
|
||||||
.descriptor_type = .uniform_buffer_dynamic,
|
|
||||||
.descriptor_count = 1,
|
|
||||||
.p_buffer_info = @ptrCast(&model_buffer_info),
|
|
||||||
.p_image_info = undefined,
|
|
||||||
.p_texel_buffer_view = undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
// List of descriptor set writes
|
// List of descriptor set writes
|
||||||
const set_writes = [_]vk.WriteDescriptorSet{ vp_set_write, model_set_write };
|
const set_writes = [_]vk.WriteDescriptorSet{vp_set_write};
|
||||||
|
|
||||||
// Update the descriptor sets with new buffer/binding info
|
// Update the descriptor sets with new buffer/binding info
|
||||||
self.device.updateDescriptorSets(@intCast(set_writes.len), &set_writes, 0, null);
|
self.device.updateDescriptorSets(@intCast(set_writes.len), &set_writes, 0, null);
|
||||||
|
@ -995,7 +952,7 @@ pub const VulkanRenderer = struct {
|
||||||
|
|
||||||
fn updateUniformBuffers(self: *Self, image_index: u32) !void {
|
fn updateUniformBuffers(self: *Self, image_index: u32) !void {
|
||||||
// Copy VP data
|
// Copy VP data
|
||||||
var data = try self.device.mapMemory(
|
const data = try self.device.mapMemory(
|
||||||
self.vp_uniform_buffer_memory[image_index],
|
self.vp_uniform_buffer_memory[image_index],
|
||||||
0,
|
0,
|
||||||
@sizeOf(UboViewProjection),
|
@sizeOf(UboViewProjection),
|
||||||
|
@ -1005,26 +962,9 @@ pub const VulkanRenderer = struct {
|
||||||
const vp_data: *UboViewProjection = @ptrCast(@alignCast(data));
|
const vp_data: *UboViewProjection = @ptrCast(@alignCast(data));
|
||||||
vp_data.* = self.ubo_view_projection;
|
vp_data.* = self.ubo_view_projection;
|
||||||
self.device.unmapMemory(self.vp_uniform_buffer_memory[image_index]);
|
self.device.unmapMemory(self.vp_uniform_buffer_memory[image_index]);
|
||||||
|
|
||||||
// Copy model data
|
|
||||||
for (self.meshes, 0..) |mesh, i| {
|
|
||||||
self.model_transfer_space[i] = mesh.ubo_model;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the list of model data
|
|
||||||
data = try self.device.mapMemory(
|
|
||||||
self.model_duniform_buffer_memory[image_index],
|
|
||||||
0,
|
|
||||||
self.model_uniform_alignment * self.meshes.len,
|
|
||||||
.{},
|
|
||||||
);
|
|
||||||
|
|
||||||
const model_data: [*]UboModel = @ptrCast(@alignCast(data));
|
|
||||||
@memcpy(model_data, self.model_transfer_space[0..self.meshes.len]);
|
|
||||||
self.device.unmapMemory(self.model_duniform_buffer_memory[image_index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recordCommands(self: *Self) !void {
|
fn recordCommands(self: *Self, current_image: u32) !void {
|
||||||
// Information about how to begin each command
|
// Information about how to begin each command
|
||||||
const buffer_begin_info: vk.CommandBufferBeginInfo = .{
|
const buffer_begin_info: vk.CommandBufferBeginInfo = .{
|
||||||
// Buffer can be resubmitted when it has already been submitted and is awaiting execution
|
// Buffer can be resubmitted when it has already been submitted and is awaiting execution
|
||||||
|
@ -1047,59 +987,64 @@ pub const VulkanRenderer = struct {
|
||||||
.framebuffer = undefined,
|
.framebuffer = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (self.command_buffers, 0..) |command_buffer, i| {
|
render_pass_begin_info.framebuffer = self.swapchain_framebuffers[current_image];
|
||||||
render_pass_begin_info.framebuffer = self.swapchain_framebuffers[i];
|
const command_buffer = self.command_buffers[current_image];
|
||||||
|
|
||||||
// Start recording commands to command buffer
|
// Start recording commands to command buffer
|
||||||
try command_buffer.beginCommandBuffer(&buffer_begin_info);
|
try command_buffer.beginCommandBuffer(&buffer_begin_info);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Begin render pass
|
// Begin render pass
|
||||||
command_buffer.beginRenderPass(&render_pass_begin_info, vk.SubpassContents.@"inline");
|
command_buffer.beginRenderPass(&render_pass_begin_info, vk.SubpassContents.@"inline");
|
||||||
|
|
||||||
// Needed when using dynamic state
|
// Needed when using dynamic state
|
||||||
command_buffer.setViewport(0, 1, @ptrCast(&self.viewport));
|
command_buffer.setViewport(0, 1, @ptrCast(&self.viewport));
|
||||||
command_buffer.setScissor(0, 1, @ptrCast(&self.scissor));
|
command_buffer.setScissor(0, 1, @ptrCast(&self.scissor));
|
||||||
|
|
||||||
for (self.meshes, 0..) |mesh, j| {
|
for (self.meshes) |mesh| {
|
||||||
// Bind pipeline to be used in render pass
|
// Bind pipeline to be used in render pass
|
||||||
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
|
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
|
||||||
|
|
||||||
// Buffers to bind
|
// Buffers to bind
|
||||||
const vertex_buffers = [_]vk.Buffer{mesh.vertex_buffer};
|
const vertex_buffers = [_]vk.Buffer{mesh.vertex_buffer};
|
||||||
// Offsets into buffers being bound
|
// Offsets into buffers being bound
|
||||||
const offsets = [_]vk.DeviceSize{0};
|
const offsets = [_]vk.DeviceSize{0};
|
||||||
// Command to bind vertex buffer before drawing with them
|
// Command to bind vertex buffer before drawing with them
|
||||||
command_buffer.bindVertexBuffers(0, 1, &vertex_buffers, &offsets);
|
command_buffer.bindVertexBuffers(0, 1, &vertex_buffers, &offsets);
|
||||||
|
|
||||||
// Bind mesh index buffer, with 0 offset and using the uint32 type
|
// Bind mesh index buffer, with 0 offset and using the uint32 type
|
||||||
command_buffer.bindIndexBuffer(mesh.index_buffer, 0, .uint32);
|
command_buffer.bindIndexBuffer(mesh.index_buffer, 0, .uint32);
|
||||||
|
|
||||||
// Dynamic offset amount
|
// Push constants to given shader stage directly (no buffer)
|
||||||
const dynamic_offset: u32 = @intCast(self.model_uniform_alignment * j);
|
command_buffer.pushConstants(
|
||||||
|
self.pipeline_layout,
|
||||||
|
.{ .vertex_bit = true }, // Stage to push constants to
|
||||||
|
0, // Offset of push constants to update
|
||||||
|
@sizeOf(Model), // Size of data being pushed
|
||||||
|
@ptrCast(&mesh.ubo_model.model), // Actual data being pushed (can be array)
|
||||||
|
);
|
||||||
|
|
||||||
// Bind descriptor sets
|
// Bind descriptor sets
|
||||||
command_buffer.bindDescriptorSets(
|
command_buffer.bindDescriptorSets(
|
||||||
.graphics,
|
.graphics,
|
||||||
self.pipeline_layout,
|
self.pipeline_layout,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ptrCast(&self.descriptor_sets[i]),
|
@ptrCast(&self.descriptor_sets[current_image]),
|
||||||
1,
|
0,
|
||||||
@ptrCast(&dynamic_offset),
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Execute a pipeline
|
// Execute a pipeline
|
||||||
command_buffer.drawIndexed(mesh.index_count, 1, 0, 0, 0);
|
command_buffer.drawIndexed(mesh.index_count, 1, 0, 0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
// End render pass
|
|
||||||
command_buffer.endRenderPass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop recording to command buffer
|
// End render pass
|
||||||
try command_buffer.endCommandBuffer();
|
command_buffer.endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop recording to command buffer
|
||||||
|
try command_buffer.endCommandBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getPhysicalDevice(self: *Self) !void {
|
fn getPhysicalDevice(self: *Self) !void {
|
||||||
|
@ -1120,21 +1065,6 @@ pub const VulkanRenderer = struct {
|
||||||
// TODO Obviously needs to be something else
|
// TODO Obviously needs to be something else
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get properties of our new device
|
|
||||||
const device_props = self.instance.getPhysicalDeviceProperties(self.physical_device);
|
|
||||||
|
|
||||||
self.min_uniform_buffer_offset = device_props.limits.min_uniform_buffer_offset_alignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn allocateDynamicBufferTransferSpace(self: *Self) !void {
|
|
||||||
// TODO Needed in zig (we have align())?
|
|
||||||
// Calculate alignment of model data
|
|
||||||
self.model_uniform_alignment =
|
|
||||||
(@sizeOf(UboModel) + self.min_uniform_buffer_offset - 1) & ~(self.min_uniform_buffer_offset - 1);
|
|
||||||
|
|
||||||
// Create space in memory to hold dynamic buffer that is aligned to our required alignment and holds MAX_OBJECTS
|
|
||||||
// self.model_transfer_space = try self.allocator.create(UboModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getRequiredExtensions(self: Self) ![][*:0]const u8 {
|
fn getRequiredExtensions(self: Self) ![][*:0]const u8 {
|
||||||
|
|
Loading…
Reference in a new issue