Implemented dynamic storage buffers
This commit is contained in:
parent
5f07c593b3
commit
9a5ffc70a5
5 changed files with 206 additions and 42 deletions
|
|
@ -1,5 +1,11 @@
|
|||
#version 450
|
||||
|
||||
struct Transform {
|
||||
mat4 translation;
|
||||
mat4 scale;
|
||||
mat4 rotation;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec3 vertPos;
|
||||
layout(location = 1) in vec3 normal;
|
||||
layout(location = 2) in vec2 uv;
|
||||
|
|
@ -12,10 +18,8 @@ layout (binding = 1) uniform ViewUniform {
|
|||
mat4 view;
|
||||
} view;
|
||||
|
||||
layout (binding = 4) uniform TransformUniform {
|
||||
mat4 translation;
|
||||
mat4 scale;
|
||||
mat4 rotation;
|
||||
layout (binding = 4) readonly buffer TransformUniform {
|
||||
Transform transforms[];
|
||||
} transform;
|
||||
|
||||
layout(location = 2) out vec3 Normal;
|
||||
|
|
@ -23,7 +27,7 @@ layout(location = 3) out vec3 FragPos;
|
|||
layout(location = 4) out vec2 TexCoords;
|
||||
|
||||
void main() {
|
||||
mat4 transformation = transform.translation * transform.scale * transform.rotation;
|
||||
mat4 transformation = transform.transforms[0].translation * transform.transforms[0].scale * transform.transforms[0].rotation;
|
||||
vec4 out_vec = proj.proj * view.view * transformation * vec4(vertPos, 1.0);
|
||||
FragPos = vec3(transformation * vec4(vertPos, 1.0));
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ descriptor_set_layout: c.VkDescriptorSetLayout,
|
|||
projection_buffer: vk.Buffer,
|
||||
view_buffer: vk.Buffer,
|
||||
view_memory: [*c]u8,
|
||||
transform_memory: [*c]u8,
|
||||
transform_buffer: vk.DynamicBuffer(math.Transform),
|
||||
view_pos_memory: [*c]u8,
|
||||
diffuse_sampler: vk.Sampler,
|
||||
specular_sampler: vk.Sampler,
|
||||
|
|
@ -303,7 +303,7 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re
|
|||
|
||||
const transform_binding = c.VkDescriptorSetLayoutBinding{
|
||||
.binding = 4,
|
||||
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorType = c.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT,
|
||||
};
|
||||
|
|
@ -417,12 +417,17 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re
|
|||
.descriptorCount = 2,
|
||||
};
|
||||
|
||||
const sizes = [_]c.VkDescriptorPoolSize {size, sampler_size};
|
||||
const transforms_size = c.VkDescriptorPoolSize{
|
||||
.type = c.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
};
|
||||
|
||||
const sizes = [_]c.VkDescriptorPoolSize {size, sampler_size, transforms_size};
|
||||
|
||||
const descriptor_pool_info = c.VkDescriptorPoolCreateInfo{
|
||||
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.maxSets = 2,
|
||||
.poolSizeCount = 2,
|
||||
.poolSizeCount = 3,
|
||||
.pPoolSizes = sizes[0..].ptr,
|
||||
};
|
||||
|
||||
|
|
@ -505,36 +510,7 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re
|
|||
|
||||
c.vkUpdateDescriptorSets(device.handle, 1, &write_view_descriptor_set, 0, null);
|
||||
|
||||
const transform_buffer = try device.initBuffer(vk.BufferUsage{ .uniform_buffer = true, .transfer_dst = true }, vk.BufferFlags{ .device_local = true }, @sizeOf(math.Transform) - @sizeOf(math.Quaternion));
|
||||
|
||||
var transform_data: [*c]u8 = undefined;
|
||||
|
||||
try vk.mapError(c.vkMapMemory(
|
||||
device.handle,
|
||||
transform_buffer.memory,
|
||||
0,
|
||||
transform_buffer.size,
|
||||
0,
|
||||
@ptrCast(&transform_data),
|
||||
));
|
||||
|
||||
const transform_descriptor_buffer_info = c.VkDescriptorBufferInfo{
|
||||
.buffer = transform_buffer.handle,
|
||||
.offset = 0,
|
||||
.range = transform_buffer.size,
|
||||
};
|
||||
|
||||
const write_transform_descriptor_set = c.VkWriteDescriptorSet{
|
||||
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptor_set,
|
||||
.dstBinding = 4,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pBufferInfo = &transform_descriptor_buffer_info,
|
||||
};
|
||||
|
||||
c.vkUpdateDescriptorSets(device.handle, 1, &write_transform_descriptor_set, 0, null);
|
||||
const transform_buffer = try vk.DynamicBuffer(math.Transform).init(allocator, device, vk.BufferUsage{ .storage_buffer = true, .transfer_dst = true }, vk.BufferFlags{ .device_local = true }, descriptor_set, 4);
|
||||
|
||||
const directional_light_buffer = try device.initBuffer(vk.BufferUsage{ .uniform_buffer = true, .transfer_dst = true }, vk.BufferFlags{ .device_local = true }, @sizeOf(lights.DirectionalLight));
|
||||
|
||||
|
|
@ -643,7 +619,7 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re
|
|||
.view_buffer = view_buffer,
|
||||
.view_memory = view_data,
|
||||
.view_pos_memory = view_pos_data,
|
||||
.transform_memory = transform_data,
|
||||
.transform_buffer = transform_buffer,
|
||||
.diffuse_sampler = try vk.Sampler.init(device),
|
||||
.specular_sampler = try vk.Sampler.init(device),
|
||||
.textures = std.ArrayList(c.VkDescriptorSet).init(allocator),
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@ pub fn render(pool: *ecs.Pool) anyerror!void {
|
|||
|
||||
renderer.transform.rotate(math.rad(15) * delta_time, .{0.0, 1.0, 0.0});
|
||||
|
||||
const transform_memory = renderer.graphics_pipeline.transform_memory;
|
||||
@memcpy(transform_memory[0..(@sizeOf(math.Transform)-@sizeOf(math.Quaternion))], std.mem.asBytes(&renderer.transform)[0..(@sizeOf(math.Transform)-@sizeOf(math.Quaternion))]);
|
||||
const transform_memory = renderer.graphics_pipeline.transform_buffer.mapped_memory;
|
||||
transform_memory[0] = renderer.transform;
|
||||
|
||||
try renderer.device.waitFence(renderer.current_frame);
|
||||
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);
|
||||
|
|
|
|||
183
src/rendering/dynamic_buffer.zig
Normal file
183
src/rendering/dynamic_buffer.zig
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
const std = @import("std");
|
||||
const vk = @import("vulkan.zig");
|
||||
const c = vk.c;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const rendering = @import("rendering.zig");
|
||||
|
||||
pub fn DynamicBuffer(comptime T: type) type {
|
||||
return struct {
|
||||
device: vk.Device,
|
||||
usage: vk.BufferUsage,
|
||||
flags: vk.BufferFlags,
|
||||
handle: c.VkBuffer,
|
||||
memory: c.VkDeviceMemory,
|
||||
size: usize,
|
||||
len: usize,
|
||||
element_size: usize,
|
||||
free_indices: std.ArrayList(usize),
|
||||
allocator: std.mem.Allocator,
|
||||
mapped_memory: []T,
|
||||
descriptor_set: c.VkDescriptorSet,
|
||||
binding: u32,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, device: vk.Device, usage: vk.BufferUsage, flags: vk.BufferFlags, descriptor_set: c.VkDescriptorSet, binding: u32) !Self {
|
||||
const size = @sizeOf(T) * 10;
|
||||
const family_indices: []const u32 = &.{device.graphics_family};
|
||||
|
||||
const create_info: c.VkBufferCreateInfo = .{
|
||||
.sType = c.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = size,
|
||||
.sharingMode = c.VK_SHARING_MODE_EXCLUSIVE,
|
||||
.usage = @bitCast(usage),
|
||||
.queueFamilyIndexCount = 1,
|
||||
.pQueueFamilyIndices = family_indices.ptr,
|
||||
};
|
||||
|
||||
var buffer: c.VkBuffer = undefined;
|
||||
try vk.mapError(c.vkCreateBuffer(device.handle, &create_info, null, &buffer));
|
||||
|
||||
var memory_requirements: c.VkMemoryRequirements = undefined;
|
||||
c.vkGetBufferMemoryRequirements(device.handle, buffer, &memory_requirements);
|
||||
|
||||
const alloc_info: c.VkMemoryAllocateInfo = .{
|
||||
.sType = c.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = memory_requirements.size,
|
||||
.memoryTypeIndex = device.pick_memory_type(memory_requirements.memoryTypeBits, @bitCast(flags)),
|
||||
};
|
||||
|
||||
var device_memory: c.VkDeviceMemory = undefined;
|
||||
|
||||
try vk.mapError(c.vkAllocateMemory(device.handle, &alloc_info, null, &device_memory));
|
||||
|
||||
try vk.mapError(c.vkBindBufferMemory(device.handle, buffer, device_memory, 0));
|
||||
|
||||
var mapped_data: [*c]u8 = undefined;
|
||||
|
||||
try vk.mapError(c.vkMapMemory(
|
||||
device.handle,
|
||||
device_memory,
|
||||
0,
|
||||
size,
|
||||
0,
|
||||
@ptrCast(&mapped_data),
|
||||
));
|
||||
|
||||
const mapped_memory: []T = @as([*]T, @ptrCast(@alignCast(mapped_data)))[0..10];
|
||||
|
||||
const descriptor_buffer_info = c.VkDescriptorBufferInfo{
|
||||
.buffer = buffer,
|
||||
.offset = 0,
|
||||
.range = size,
|
||||
};
|
||||
|
||||
const write_descriptor_set = c.VkWriteDescriptorSet{
|
||||
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptor_set,
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = c.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.pBufferInfo = &descriptor_buffer_info,
|
||||
};
|
||||
|
||||
c.vkUpdateDescriptorSets(device.handle, 1, &write_descriptor_set, 0, null);
|
||||
|
||||
return .{
|
||||
.handle = buffer,
|
||||
.size = size,
|
||||
.memory = device_memory,
|
||||
.device = device,
|
||||
.element_size = @sizeOf(T),
|
||||
.usage = usage,
|
||||
.flags = flags,
|
||||
.allocator = allocator,
|
||||
.free_indices = std.ArrayList(usize).init(allocator),
|
||||
.mapped_memory = mapped_memory,
|
||||
.descriptor_set = descriptor_set,
|
||||
.binding = binding,
|
||||
.len = 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn elementOffset(self: Self, index: usize) usize {
|
||||
return self.element_size * index;
|
||||
}
|
||||
|
||||
pub fn items(self: Self) []T {
|
||||
return self.mapped_memory[0..self.len-1];
|
||||
}
|
||||
|
||||
pub fn remove(self: *Self, index: usize) void {
|
||||
self.free_indices.append(index);
|
||||
@memset(@as([*]u8, @ptrCast(@alignCast(self.mapped_memory[index..].ptr)))[0..self.element_size], 0);
|
||||
}
|
||||
|
||||
pub fn append(self: *Self, element: T) !void {
|
||||
if (self.free_indices.pop()) |index| {
|
||||
self.mapped_memory[index] = element;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.size + self.element_size >= self.size) self.grow();
|
||||
|
||||
self.mapped_memory[self.len] = element;
|
||||
self.len += 1;
|
||||
}
|
||||
|
||||
pub fn grow(self: *Self) !void {
|
||||
const new_size = self.size + (self.size / 2);
|
||||
const new = try Self.init(self.allocator, self.device, self.usage, self.flags, new_size);
|
||||
try self.copyTo(new, 0);
|
||||
|
||||
c.vkDestroyBuffer(self.device.handle, self.handle, null);
|
||||
c.vkUnmapMemory(self.device.handle, self.memory);
|
||||
c.vkFreeMemory(self.device.handle, self.memory, null);
|
||||
|
||||
self.size = new.size;
|
||||
self.handle = new.handle;
|
||||
self.memory = new.memory;
|
||||
self.mapped_memory = new.mapped_memory;
|
||||
|
||||
const descriptor_buffer_info = c.VkDescriptorBufferInfo{
|
||||
.buffer = self.handle,
|
||||
.offset = 0,
|
||||
.range = self.size,
|
||||
};
|
||||
|
||||
const write_descriptor_set = c.VkWriteDescriptorSet{
|
||||
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self.descriptor_set,
|
||||
.dstBinding = self.binding,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = c.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.pBufferInfo = &descriptor_buffer_info,
|
||||
};
|
||||
|
||||
c.vkUpdateDescriptorSets(self.device.handle, 1, &write_descriptor_set, 0, null);
|
||||
}
|
||||
|
||||
pub fn copyTo(self: Self, dest: Self, offset: usize) !void {
|
||||
const command_buffer = try self.device.beginSingleTimeCommands();
|
||||
|
||||
const copy_region: c.VkBufferCopy = .{
|
||||
.srcOffset = 0,
|
||||
.dstOffset = offset,
|
||||
.size = self.size,
|
||||
};
|
||||
|
||||
c.vkCmdCopyBuffer(command_buffer, self.handle, dest.handle, 1, ©_region);
|
||||
|
||||
try self.device.endSingleTimeCommands(command_buffer);
|
||||
}
|
||||
|
||||
pub fn deinit(self: Self) void {
|
||||
self.free_indices.deinit();
|
||||
c.vkDestroyBuffer(self.device.handle, self.handle, null);
|
||||
c.vkUnmapMemory(self.device.handle, self.memory);
|
||||
c.vkFreeMemory(self.device.handle, self.memory, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ pub const GraphicsPipeline = @import("GraphicsPipeline.zig");
|
|||
pub const Device = @import("Device.zig");
|
||||
pub const Swapchain = @import("Swapchain.zig");
|
||||
pub const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||
pub const DynamicBuffer = @import("dynamic_buffer.zig").DynamicBuffer;
|
||||
|
||||
const std = @import("std");
|
||||
pub const c = @cImport({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue