Add dynamic uniform buffers
This commit is contained in:
parent
b1bbd65aaa
commit
6f4f600fda
4 changed files with 206 additions and 69 deletions
|
@ -1,12 +1,17 @@
|
|||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const zm = @import("zmath");
|
||||
|
||||
const Utilities = @import("utilities.zig");
|
||||
const Vertex = Utilities.Vertex;
|
||||
const Device = @import("vulkan_renderer.zig").Device;
|
||||
const Instance = @import("vulkan_renderer.zig").Instance;
|
||||
const UboModel = @import("vulkan_renderer.zig").UboModel;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
ubo_model: UboModel,
|
||||
|
||||
vertex_count: u32,
|
||||
vertex_buffer: vk.Buffer,
|
||||
vertex_buffer_memory: vk.DeviceMemory,
|
||||
|
@ -44,6 +49,8 @@ pub fn new(
|
|||
try self.createVertexBuffer(transfer_queue, transfer_command_pool, vertices);
|
||||
try self.createIndexBuffer(transfer_queue, transfer_command_pool, indices);
|
||||
|
||||
self.ubo_model = .{ .model = zm.identity() };
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
12
src/main.zig
12
src/main.zig
|
@ -47,7 +47,17 @@ pub fn main() !void {
|
|||
angle -= 360.0;
|
||||
}
|
||||
|
||||
try vulkan_renderer.updateModel(zm.rotationZ(angle));
|
||||
var first_model = zm.identity();
|
||||
var second_model = zm.identity();
|
||||
|
||||
first_model = zm.mul(first_model, zm.rotationZ(angle));
|
||||
first_model = zm.mul(first_model, zm.translation(-2.0, 0.0, -5.0));
|
||||
|
||||
second_model = zm.mul(second_model, zm.rotationZ(-angle * 2));
|
||||
second_model = zm.mul(second_model, zm.translation(2.0, 0.0, -5.0));
|
||||
|
||||
try vulkan_renderer.updateModel(0, first_model);
|
||||
try vulkan_renderer.updateModel(1, second_model);
|
||||
|
||||
try vulkan_renderer.draw();
|
||||
}
|
||||
|
|
|
@ -3,15 +3,18 @@
|
|||
layout(location = 0) in vec3 pos;
|
||||
layout(location = 1) in vec3 col;
|
||||
|
||||
layout(binding = 0) uniform MVP {
|
||||
layout(binding = 0) uniform UboViewProjection {
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
} uboViewProjection;
|
||||
|
||||
layout(binding = 1) uniform UboModel {
|
||||
mat4 model;
|
||||
} mvp;
|
||||
} uboModel;
|
||||
|
||||
layout(location = 0) out vec3 fragCol;
|
||||
|
||||
void main() {
|
||||
gl_Position = mvp.projection * mvp.view * mvp.model * vec4(pos, 1.0);
|
||||
gl_Position = uboViewProjection.projection * uboViewProjection.view * uboModel.model * vec4(pos, 1.0);
|
||||
fragCol = col;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ const enable_validation_layers = builtin.mode == .Debug;
|
|||
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
||||
|
||||
const MAX_FRAME_DRAWS: u32 = 2;
|
||||
const MAX_OBJECTS: u32 = 2;
|
||||
|
||||
const apis: []const vk.ApiInfo = &.{
|
||||
vk.features.version_1_0,
|
||||
|
@ -37,15 +38,18 @@ pub const Device = vk.DeviceProxy(apis);
|
|||
pub const Queue = vk.QueueProxy(apis);
|
||||
pub const CommandBuffer = vk.CommandBufferProxy(apis);
|
||||
|
||||
const UboViewProjection = struct {
|
||||
projection: zm.Mat align(16),
|
||||
view: zm.Mat align(16),
|
||||
};
|
||||
|
||||
pub const UboModel = struct {
|
||||
model: zm.Mat align(16),
|
||||
};
|
||||
|
||||
pub const VulkanRenderer = struct {
|
||||
const Self = @This();
|
||||
|
||||
const Mvp = struct {
|
||||
projection: zm.Mat,
|
||||
view: zm.Mat,
|
||||
model: zm.Mat,
|
||||
};
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
|
||||
vkb: BaseDispatch,
|
||||
|
@ -58,7 +62,7 @@ pub const VulkanRenderer = struct {
|
|||
meshes: [2]Mesh,
|
||||
|
||||
// Scene settings
|
||||
mvp: Mvp,
|
||||
ubo_view_projection: UboViewProjection,
|
||||
|
||||
// Main
|
||||
instance: Instance,
|
||||
|
@ -81,8 +85,11 @@ pub const VulkanRenderer = struct {
|
|||
descriptor_pool: vk.DescriptorPool,
|
||||
descriptor_sets: []vk.DescriptorSet,
|
||||
|
||||
uniform_buffer: []vk.Buffer,
|
||||
uniform_buffer_memory: []vk.DeviceMemory,
|
||||
vp_uniform_buffer: []vk.Buffer,
|
||||
vp_uniform_buffer_memory: []vk.DeviceMemory,
|
||||
|
||||
model_duniform_buffer: []vk.Buffer,
|
||||
model_duniform_buffer_memory: []vk.DeviceMemory,
|
||||
|
||||
// Pipeline
|
||||
graphics_pipeline: vk.Pipeline,
|
||||
|
@ -96,6 +103,10 @@ pub const VulkanRenderer = struct {
|
|||
swapchain_image_format: vk.Format,
|
||||
extent: vk.Extent2D,
|
||||
|
||||
min_uniform_buffer_offset: vk.DeviceSize,
|
||||
model_uniform_alignment: usize,
|
||||
model_transfer_space: [MAX_OBJECTS]UboModel,
|
||||
|
||||
// Synchronisation
|
||||
image_available: [MAX_FRAME_DRAWS]vk.Semaphore,
|
||||
render_finished: [MAX_FRAME_DRAWS]vk.Semaphore,
|
||||
|
@ -128,36 +139,35 @@ pub const VulkanRenderer = struct {
|
|||
try self.createCommandPool();
|
||||
|
||||
const aspect: f32 = @as(f32, @floatFromInt(self.extent.width)) / @as(f32, @floatFromInt(self.extent.height));
|
||||
self.mvp.projection = zm.perspectiveFovRh(
|
||||
self.ubo_view_projection.projection = zm.perspectiveFovRh(
|
||||
std.math.degreesToRadians(45.0),
|
||||
aspect,
|
||||
0.1,
|
||||
100.0,
|
||||
);
|
||||
self.mvp.view = zm.lookAtRh(
|
||||
self.ubo_view_projection.view = zm.lookAtRh(
|
||||
zm.Vec{ 0.0, 0.0, 2.0, 0.0 },
|
||||
zm.Vec{ 0.0, 0.0, 0.0, 0.0 },
|
||||
zm.Vec{ 0.0, 1.0, 0.0, 0.0 },
|
||||
);
|
||||
self.mvp.model = zm.identity();
|
||||
|
||||
// Invert y scale
|
||||
self.mvp.projection[1][1] *= -1;
|
||||
self.ubo_view_projection.projection[1][1] *= -1;
|
||||
|
||||
// Create meshes
|
||||
// Vertex Data
|
||||
var mesh_vertices = [_]Vertex{
|
||||
.{ .pos = .{ -0.1, -0.4, 0.0 }, .col = .{ 1.0, 0.0, 0.0 } }, // 0
|
||||
.{ .pos = .{ -0.1, 0.4, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 1
|
||||
.{ .pos = .{ -0.9, 0.4, 0.0 }, .col = .{ 0.0, 0.0, 1.0 } }, // 2
|
||||
.{ .pos = .{ -0.9, -0.4, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 3
|
||||
.{ .pos = .{ -0.4, 0.4, 0.0 }, .col = .{ 1.0, 0.0, 0.0 } }, // 0
|
||||
.{ .pos = .{ -0.4, -0.4, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 1
|
||||
.{ .pos = .{ 0.4, -0.4, 0.0 }, .col = .{ 0.0, 0.0, 1.0 } }, // 2
|
||||
.{ .pos = .{ 0.4, 0.4, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 3
|
||||
};
|
||||
|
||||
var mesh_vertices2 = [_]Vertex{
|
||||
.{ .pos = .{ 0.9, -0.3, 0.0 }, .col = .{ 1.0, 0.0, 0.0 } }, // 0
|
||||
.{ .pos = .{ 0.9, 0.1, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 1
|
||||
.{ .pos = .{ 0.1, 0.3, 0.0 }, .col = .{ 0.0, 0.0, 1.0 } }, // 2
|
||||
.{ .pos = .{ 0.1, -0.3, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 3
|
||||
.{ .pos = .{ -0.25, 0.6, 0.0 }, .col = .{ 1.0, 0.0, 0.0 } }, // 0
|
||||
.{ .pos = .{ -0.25, -0.6, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 1
|
||||
.{ .pos = .{ 0.25, -0.6, 0.0 }, .col = .{ 0.0, 0.0, 1.0 } }, // 2
|
||||
.{ .pos = .{ 0.25, 0.6, 0.0 }, .col = .{ 0.0, 1.0, 0.0 } }, // 3
|
||||
};
|
||||
|
||||
// Index Data
|
||||
|
@ -191,7 +201,7 @@ pub const VulkanRenderer = struct {
|
|||
self.meshes = [_]Mesh{ first_mesh, second_mesh };
|
||||
|
||||
try self.createCommandBuffers();
|
||||
|
||||
try self.allocateDynamicBufferTransferSpace();
|
||||
try self.createUniformBuffers();
|
||||
try self.createDescriptorPool();
|
||||
try self.createDescriptorSets();
|
||||
|
@ -202,8 +212,10 @@ pub const VulkanRenderer = struct {
|
|||
return self;
|
||||
}
|
||||
|
||||
pub fn updateModel(self: *Self, new_model: zm.Mat) !void {
|
||||
self.mvp.model = new_model;
|
||||
pub fn updateModel(self: *Self, model_id: u32, new_model: zm.Mat) !void {
|
||||
if (model_id < self.meshes.len) {
|
||||
self.meshes[model_id].ubo_model.model = new_model;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(self: *Self) !void {
|
||||
|
@ -221,7 +233,7 @@ pub const VulkanRenderer = struct {
|
|||
.null_handle,
|
||||
);
|
||||
|
||||
try self.updateUniformBuffer(image_index_result.image_index);
|
||||
try self.updateUniformBuffers(image_index_result.image_index);
|
||||
|
||||
// -- Submit command buffer to render
|
||||
// Queue submission information
|
||||
|
@ -266,12 +278,16 @@ pub const VulkanRenderer = struct {
|
|||
self.device.destroyDescriptorPool(self.descriptor_pool, null);
|
||||
self.device.destroyDescriptorSetLayout(self.descriptor_set_layout, null);
|
||||
|
||||
for (self.uniform_buffer, self.uniform_buffer_memory) |buffer, buffer_memory| {
|
||||
self.device.destroyBuffer(buffer, null);
|
||||
self.device.freeMemory(buffer_memory, null);
|
||||
for (0..self.swapchain_images.len) |i| {
|
||||
self.device.destroyBuffer(self.vp_uniform_buffer[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.uniform_buffer);
|
||||
self.allocator.free(self.uniform_buffer_memory);
|
||||
self.allocator.free(self.vp_uniform_buffer);
|
||||
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);
|
||||
|
||||
for (self.meshes) |mesh| {
|
||||
|
@ -551,8 +567,8 @@ pub const VulkanRenderer = struct {
|
|||
}
|
||||
|
||||
fn createDescriptorSetLayout(self: *Self) !void {
|
||||
// MVP binding info
|
||||
const mvp_layout_binding: vk.DescriptorSetLayoutBinding = .{
|
||||
// UboViewProjection binding info
|
||||
const vp_layout_binding: vk.DescriptorSetLayoutBinding = .{
|
||||
.binding = 0, // Binding point in shader (designated by binding number in shader)
|
||||
.descriptor_type = .uniform_buffer, // Type of descriptor (unifor, dynamic uniform, image sampler, etc)
|
||||
.descriptor_count = 1, // Number of descriptors for binding
|
||||
|
@ -560,10 +576,21 @@ pub const VulkanRenderer = struct {
|
|||
.p_immutable_samplers = null, // For texture: can make smapler data immutable by specifying in layout
|
||||
};
|
||||
|
||||
// Model binding info
|
||||
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
|
||||
const layout_create_info: vk.DescriptorSetLayoutCreateInfo = .{
|
||||
.binding_count = 1, // Number of binding infos
|
||||
.p_bindings = @ptrCast(&mvp_layout_binding), // Array of binding infos
|
||||
.binding_count = @intCast(layout_bindings.len), // Number of binding infos
|
||||
.p_bindings = &layout_bindings, // Array of binding infos
|
||||
};
|
||||
|
||||
// Create descriptor set layout
|
||||
|
@ -831,40 +858,66 @@ pub const VulkanRenderer = struct {
|
|||
}
|
||||
|
||||
fn createUniformBuffers(self: *Self) !void {
|
||||
// Buffer size will be size of all three variables (will offset to access)
|
||||
const buffer_size: vk.DeviceSize = @sizeOf(@TypeOf(self.mvp));
|
||||
// View projection buffer size
|
||||
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)
|
||||
self.uniform_buffer = try self.allocator.alloc(vk.Buffer, self.swapchain_images.len);
|
||||
self.uniform_buffer_memory = try self.allocator.alloc(vk.DeviceMemory, 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.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
|
||||
for (0..self.uniform_buffer.len) |i| {
|
||||
for (0..self.vp_uniform_buffer.len) |i| {
|
||||
try Utilities.createBuffer(
|
||||
self.physical_device,
|
||||
self.instance,
|
||||
self.device,
|
||||
buffer_size,
|
||||
vp_buffer_size,
|
||||
.{ .uniform_buffer_bit = true },
|
||||
.{ .host_visible_bit = true, .host_coherent_bit = true },
|
||||
&self.uniform_buffer[i],
|
||||
&self.uniform_buffer_memory[i],
|
||||
&self.vp_uniform_buffer[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],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn createDescriptorPool(self: *Self) !void {
|
||||
// Type of descriptors + how many descriptors (!= descriptor sets) (combined makes the pool size)
|
||||
const pool_size: vk.DescriptorPoolSize = .{
|
||||
// View projection pool
|
||||
const vp_pool_size: vk.DescriptorPoolSize = .{
|
||||
.type = .uniform_buffer,
|
||||
.descriptor_count = @intCast(self.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
|
||||
const descriptor_pool_sizes = [_]vk.DescriptorPoolSize{ vp_pool_size, model_pool_size };
|
||||
|
||||
// Data to create descriptor pool
|
||||
const pool_create_info: vk.DescriptorPoolCreateInfo = .{
|
||||
.max_sets = @intCast(self.uniform_buffer.len), // Maximum number of descriptor sets that can be created from pool
|
||||
.pool_size_count = 1, // Amount of pool sizes being passed
|
||||
.p_pool_sizes = @ptrCast(&pool_size), // Pool sizes to create pool with
|
||||
.max_sets = @intCast(self.swapchain_images.len), // Maximum number of descriptor sets that can be created from pool
|
||||
.pool_size_count = @intCast(descriptor_pool_sizes.len), // Amount of pool sizes being passed
|
||||
.p_pool_sizes = &descriptor_pool_sizes, // Pool sizes to create pool with
|
||||
};
|
||||
|
||||
// Create descriptor pool
|
||||
|
@ -873,9 +926,9 @@ pub const VulkanRenderer = struct {
|
|||
|
||||
fn createDescriptorSets(self: *Self) !void {
|
||||
// One descriptor set for every buffer
|
||||
self.descriptor_sets = try self.allocator.alloc(vk.DescriptorSet, self.uniform_buffer.len);
|
||||
self.descriptor_sets = try self.allocator.alloc(vk.DescriptorSet, self.swapchain_images.len);
|
||||
|
||||
var set_layouts = try self.allocator.alloc(vk.DescriptorSetLayout, self.uniform_buffer.len);
|
||||
var set_layouts = try self.allocator.alloc(vk.DescriptorSetLayout, self.swapchain_images.len);
|
||||
defer self.allocator.free(set_layouts);
|
||||
for (0..set_layouts.len) |i| {
|
||||
set_layouts[i] = self.descriptor_set_layout;
|
||||
|
@ -884,7 +937,7 @@ pub const VulkanRenderer = struct {
|
|||
// Descriptor set allocation info
|
||||
const set_alloc_info: vk.DescriptorSetAllocateInfo = .{
|
||||
.descriptor_pool = self.descriptor_pool, // Pool to allocate descriptor set from
|
||||
.descriptor_set_count = @intCast(self.descriptor_sets.len), // Number of sets to allocate
|
||||
.descriptor_set_count = @intCast(self.swapchain_images.len), // Number of sets to allocate
|
||||
.p_set_layouts = set_layouts.ptr, // Layouts to use to allocate sets (1:1 relationship)
|
||||
};
|
||||
|
||||
|
@ -892,37 +945,83 @@ pub const VulkanRenderer = struct {
|
|||
try self.device.allocateDescriptorSets(&set_alloc_info, self.descriptor_sets.ptr);
|
||||
|
||||
// Update all of descriptor set buffer bindings
|
||||
for (0..self.descriptor_sets.len) |i| {
|
||||
for (0..self.swapchain_images.len) |i| {
|
||||
// -- View projection descriptor
|
||||
// Buffer info and data offset info
|
||||
const mvp_buffer_info: vk.DescriptorBufferInfo = .{
|
||||
.buffer = self.uniform_buffer[i], // Bufer to get data from
|
||||
const vp_buffer_info: vk.DescriptorBufferInfo = .{
|
||||
.buffer = self.vp_uniform_buffer[i], // Bufer to get data from
|
||||
.offset = 0, // Position of start of data
|
||||
.range = @sizeOf(@TypeOf(self.mvp)), // Size of data
|
||||
.range = @sizeOf(UboViewProjection), // Size of data
|
||||
};
|
||||
|
||||
// Data about connection between binding and buffer
|
||||
const mvp_set_write: vk.WriteDescriptorSet = .{
|
||||
const vp_set_write: vk.WriteDescriptorSet = .{
|
||||
.dst_set = self.descriptor_sets[i], // Descriptor set to update
|
||||
.dst_binding = 0, // Binding to update (matches with binding on layout/shader)
|
||||
.dst_array_element = 0, // Index in array to update
|
||||
.descriptor_type = .uniform_buffer, // Type of descriptor
|
||||
.descriptor_count = 1, // Amount to update
|
||||
.p_buffer_info = @ptrCast(&mvp_buffer_info), // Information about buffer data to bind
|
||||
.p_buffer_info = @ptrCast(&vp_buffer_info), // Information about buffer data to bind
|
||||
.p_image_info = 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
|
||||
const set_writes = [_]vk.WriteDescriptorSet{ vp_set_write, model_set_write };
|
||||
|
||||
// Update the descriptor sets with new buffer/binding info
|
||||
self.device.updateDescriptorSets(1, @ptrCast(&mvp_set_write), 0, null);
|
||||
self.device.updateDescriptorSets(@intCast(set_writes.len), &set_writes, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
fn updateUniformBuffer(self: Self, image_index: u32) !void {
|
||||
const data = try self.device.mapMemory(self.uniform_buffer_memory[image_index], 0, @sizeOf(Mvp), .{});
|
||||
fn updateUniformBuffers(self: *Self, image_index: u32) !void {
|
||||
// Copy VP data
|
||||
var data = try self.device.mapMemory(
|
||||
self.vp_uniform_buffer_memory[image_index],
|
||||
0,
|
||||
@sizeOf(UboViewProjection),
|
||||
.{},
|
||||
);
|
||||
|
||||
const mvp_data: *Mvp = @ptrCast(@alignCast(data));
|
||||
mvp_data.* = self.mvp;
|
||||
self.device.unmapMemory(self.uniform_buffer_memory[image_index]);
|
||||
const vp_data: *UboViewProjection = @ptrCast(@alignCast(data));
|
||||
vp_data.* = self.ubo_view_projection;
|
||||
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 {
|
||||
|
@ -962,7 +1061,7 @@ pub const VulkanRenderer = struct {
|
|||
command_buffer.setViewport(0, 1, @ptrCast(&self.viewport));
|
||||
command_buffer.setScissor(0, 1, @ptrCast(&self.scissor));
|
||||
|
||||
for (self.meshes) |mesh| {
|
||||
for (self.meshes, 0..) |mesh, j| {
|
||||
// Bind pipeline to be used in render pass
|
||||
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
|
||||
|
||||
|
@ -976,6 +1075,9 @@ pub const VulkanRenderer = struct {
|
|||
// Bind mesh index buffer, with 0 offset and using the uint32 type
|
||||
command_buffer.bindIndexBuffer(mesh.index_buffer, 0, .uint32);
|
||||
|
||||
// Dynamic offset amount
|
||||
const dynamic_offset: u32 = @intCast(self.model_uniform_alignment * j);
|
||||
|
||||
// Bind descriptor sets
|
||||
command_buffer.bindDescriptorSets(
|
||||
.graphics,
|
||||
|
@ -983,8 +1085,8 @@ pub const VulkanRenderer = struct {
|
|||
0,
|
||||
1,
|
||||
@ptrCast(&self.descriptor_sets[i]),
|
||||
0,
|
||||
null,
|
||||
1,
|
||||
@ptrCast(&dynamic_offset),
|
||||
);
|
||||
|
||||
// Execute a pipeline
|
||||
|
@ -1018,6 +1120,21 @@ pub const VulkanRenderer = struct {
|
|||
// TODO Obviously needs to be something else
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue