Add Descriptor layout and its buffer

This commit is contained in:
Timothy Warren 2023-04-13 10:14:10 -04:00
parent 399cce3d81
commit fafbf868bf
6 changed files with 138 additions and 39 deletions

View File

@ -14,5 +14,5 @@ png = "0.17"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"
thiserror = "1" thiserror = "1"
tobj = { version = "3", features = ["log"] } tobj = { version = "3", features = ["log"] }
vulkanalia = { version = "=0.16.0", features = ["libloading", "window", "provisional"] } vulkanalia = { version = "0.16.0", features = ["libloading", "window", "provisional"] }
winit = "0.27" winit = "0.27"

View File

@ -1,11 +1,17 @@
#version 450 #version 450
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec2 inPosition; layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor; layout(location = 0) out vec3 fragColor;
void main() { void main() {
gl_Position = vec4(inPosition, 0.0, 1.0); gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
fragColor = inColor; fragColor = inColor;
} }

Binary file not shown.

View File

@ -9,6 +9,8 @@ use ::anyhow::{anyhow, Result};
use ::lazy_static::lazy_static; use ::lazy_static::lazy_static;
use ::nalgebra_glm as glm; use ::nalgebra_glm as glm;
use ::std::mem::size_of; use ::std::mem::size_of;
use ::std::ptr::copy_nonoverlapping as memcpy;
use ::std::time::Instant;
use ::vulkanalia::loader::{LibloadingLoader, LIBRARY}; use ::vulkanalia::loader::{LibloadingLoader, LIBRARY};
use ::vulkanalia::prelude::v1_0::*; use ::vulkanalia::prelude::v1_0::*;
use ::vulkanalia::vk::{KhrSurfaceExtension, KhrSwapchainExtension}; use ::vulkanalia::vk::{KhrSurfaceExtension, KhrSwapchainExtension};
@ -49,6 +51,7 @@ pub struct App {
pub device: Device, pub device: Device,
frame: usize, frame: usize,
pub resized: bool, pub resized: bool,
start: Instant,
} }
impl App { impl App {
@ -72,6 +75,7 @@ impl App {
device, device,
frame: 0, frame: 0,
resized: false, resized: false,
start: Instant::now(),
}) })
} }
} }
@ -82,7 +86,6 @@ impl App {
/// Here be Dragons /// Here be Dragons
pub fn destroy(&mut self) { pub fn destroy(&mut self) {
unsafe { unsafe {
self.data.destroy_swapchain(&self.device);
self.data.destroy(&self.instance, &self.device); self.data.destroy(&self.instance, &self.device);
} }
} }
@ -117,6 +120,8 @@ impl App {
self.data.images_in_flight[image_index] = in_flight_fence; self.data.images_in_flight[image_index] = in_flight_fence;
self.update_uniform_buffer(image_index)?;
let wait_semaphores = &[self.data.image_available_semaphores[self.frame]]; let wait_semaphores = &[self.data.image_available_semaphores[self.frame]];
let wait_stages = &[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; let wait_stages = &[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
let command_buffers = &[self.data.command_buffers[image_index]]; let command_buffers = &[self.data.command_buffers[image_index]];
@ -158,6 +163,48 @@ impl App {
Ok(()) Ok(())
} }
unsafe fn update_uniform_buffer(&self, image_index: usize) -> Result<()> {
let time = self.start.elapsed().as_secs_f32();
let model = glm::rotate(
&glm::identity(),
time * glm::radians(&glm::vec1(90.0))[0],
&glm::vec3(0.0, 0.0, 1.0),
);
let view = glm::look_at(
&glm::vec3(2.0, 2.0, 2.0),
&glm::vec3(0.0, 0.0, 0.0),
&glm::vec3(0.0, 0.0, 1.0),
);
let mut proj = glm::perspective(
self.data.swapchain_extent.width as f32 / self.data.swapchain_extent.height as f32,
glm::radians(&glm::vec1(45.0))[0],
0.1,
10.0,
);
// Flip the image right-side-up
proj[(1, 1)] *= -1.0;
let ubo = UniformBufferObject { model, view, proj };
let memory = self.device.map_memory(
self.data.uniform_buffers_memory[image_index],
0,
size_of::<UniformBufferObject>() as u64,
vk::MemoryMapFlags::empty(),
)?;
memcpy(&ubo, memory.cast(), 1);
self.device
.unmap_memory(self.data.uniform_buffers_memory[image_index]);
Ok(())
}
/// Recreates the swapchain /// Recreates the swapchain
/// ///
/// # Safety /// # Safety

View File

@ -48,12 +48,13 @@ pub(crate) struct AppData {
pub(super) present_queue: vk::Queue, pub(super) present_queue: vk::Queue,
// Swapchain // Swapchain
swapchain_format: vk::Format, swapchain_format: vk::Format,
swapchain_extent: vk::Extent2D, pub(super) swapchain_extent: vk::Extent2D,
pub(super) swapchain: vk::SwapchainKHR, pub(super) swapchain: vk::SwapchainKHR,
swapchain_images: Vec<vk::Image>, swapchain_images: Vec<vk::Image>,
swapchain_image_views: Vec<vk::ImageView>, swapchain_image_views: Vec<vk::ImageView>,
// Pipeline // Pipeline
render_pass: vk::RenderPass, render_pass: vk::RenderPass,
descriptor_set_layout: vk::DescriptorSetLayout,
pipeline_layout: vk::PipelineLayout, pipeline_layout: vk::PipelineLayout,
pipeline: vk::Pipeline, pipeline: vk::Pipeline,
// Framebuffers // Framebuffers
@ -65,6 +66,8 @@ pub(crate) struct AppData {
vertex_buffer_memory: vk::DeviceMemory, vertex_buffer_memory: vk::DeviceMemory,
index_buffer: vk::Buffer, index_buffer: vk::Buffer,
index_buffer_memory: vk::DeviceMemory, index_buffer_memory: vk::DeviceMemory,
uniform_buffers: Vec<vk::Buffer>,
pub(super) uniform_buffers_memory: Vec<vk::DeviceMemory>,
// Command Buffers // Command Buffers
pub(super) command_buffers: Vec<vk::CommandBuffer>, pub(super) command_buffers: Vec<vk::CommandBuffer>,
// Sync Objects // Sync Objects
@ -93,22 +96,20 @@ impl AppData {
self.create_swapchain(window, &instance, &device)?; self.create_swapchain(window, &instance, &device)?;
self.create_swapchain_image_views(&device)?; self.create_swapchain_image_views(&device)?;
self.create_render_pass(&instance, &device)?; self.create_render_pass(&instance, &device)?;
self.create_descriptor_set_layout(&device)?;
self.create_pipeline(&device)?; self.create_pipeline(&device)?;
self.create_framebuffers(&device)?; self.create_framebuffers(&device)?;
self.create_command_pool(&instance, &device)?; self.create_command_pool(&instance, &device)?;
self.create_vertex_buffer(&instance, &device)?; self.create_vertex_buffer(&instance, &device)?;
self.create_index_buffer(&instance, &device)?; self.create_index_buffer(&instance, &device)?;
self.create_uniform_buffers(&instance, &device)?;
self.create_command_buffers(&device)?; self.create_command_buffers(&device)?;
self.create_sync_objects(&device)?; self.create_sync_objects(&device)?;
Ok((instance, device)) Ok((instance, device))
} }
pub(super) unsafe fn create_instance( unsafe fn create_instance(&mut self, window: &Window, entry: &Entry) -> Result<Instance> {
&mut self,
window: &Window,
entry: &Entry,
) -> Result<Instance> {
// Application Info // Application Info
let application_info = vk::ApplicationInfo::builder() let application_info = vk::ApplicationInfo::builder()
.application_name(b"Vulkan Tutorial\0") .application_name(b"Vulkan Tutorial\0")
@ -192,7 +193,13 @@ impl AppData {
/// ///
/// # Safety /// # Safety
/// Here be Dragons /// Here be Dragons
pub(super) unsafe fn destroy_swapchain(&mut self, device: &Device) { unsafe fn destroy_swapchain(&mut self, device: &Device) {
self.uniform_buffers
.iter()
.for_each(|b| device.destroy_buffer(*b, None));
self.uniform_buffers_memory
.iter()
.for_each(|m| device.free_memory(*m, None));
self.framebuffers self.framebuffers
.iter() .iter()
.for_each(|f| device.destroy_framebuffer(*f, None)); .for_each(|f| device.destroy_framebuffer(*f, None));
@ -211,6 +218,9 @@ impl AppData {
/// # Safety /// # Safety
/// Here be Dragons /// Here be Dragons
pub unsafe fn destroy(&mut self, instance: &Instance, device: &Device) { pub unsafe fn destroy(&mut self, instance: &Instance, device: &Device) {
self.destroy_swapchain(device);
device.destroy_descriptor_set_layout(self.descriptor_set_layout, None);
device.destroy_buffer(self.index_buffer, None); device.destroy_buffer(self.index_buffer, None);
device.free_memory(self.index_buffer_memory, None); device.free_memory(self.index_buffer_memory, None);
device.destroy_buffer(self.vertex_buffer, None); device.destroy_buffer(self.vertex_buffer, None);
@ -240,7 +250,7 @@ impl AppData {
// Physical Device // Physical Device
//================================================ //================================================
pub(super) unsafe fn pick_physical_device(&mut self, instance: &Instance) -> Result<()> { unsafe fn pick_physical_device(&mut self, instance: &Instance) -> Result<()> {
for physical_device in instance.enumerate_physical_devices()? { for physical_device in instance.enumerate_physical_devices()? {
let properties = instance.get_physical_device_properties(physical_device); let properties = instance.get_physical_device_properties(physical_device);
@ -279,7 +289,7 @@ impl AppData {
// Logical Device // Logical Device
//================================================ //================================================
pub(super) unsafe fn create_logical_device(&mut self, instance: &Instance) -> Result<Device> { unsafe fn create_logical_device(&mut self, instance: &Instance) -> Result<Device> {
// Queue Create Infos // Queue Create Infos
let indices = QueueFamilyIndices::get(instance, self, self.physical_device)?; let indices = QueueFamilyIndices::get(instance, self, self.physical_device)?;
@ -342,7 +352,7 @@ impl AppData {
// Swapchain // Swapchain
//================================================ //================================================
pub(super) unsafe fn create_swapchain( unsafe fn create_swapchain(
&mut self, &mut self,
window: &Window, window: &Window,
instance: &Instance, instance: &Instance,
@ -412,6 +422,7 @@ impl AppData {
self.create_render_pass(instance, device)?; self.create_render_pass(instance, device)?;
self.create_pipeline(device)?; self.create_pipeline(device)?;
self.create_framebuffers(device)?; self.create_framebuffers(device)?;
self.create_uniform_buffers(instance, device)?;
self.create_command_buffers(device)?; self.create_command_buffers(device)?;
self.images_in_flight self.images_in_flight
@ -420,7 +431,7 @@ impl AppData {
Ok(()) Ok(())
} }
pub(super) unsafe fn create_swapchain_image_views(&mut self, device: &Device) -> Result<()> { unsafe fn create_swapchain_image_views(&mut self, device: &Device) -> Result<()> {
self.swapchain_image_views = self self.swapchain_image_views = self
.swapchain_images .swapchain_images
.iter() .iter()
@ -456,11 +467,22 @@ impl AppData {
// Pipeline // Pipeline
//================================================ //================================================
pub(super) unsafe fn create_render_pass( unsafe fn create_descriptor_set_layout(&mut self, device: &Device) -> Result<()> {
&mut self, let ubo_binding = vk::DescriptorSetLayoutBinding::builder()
_instance: &Instance, .binding(0)
device: &Device, .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
) -> Result<()> { .descriptor_count(1)
.stage_flags(vk::ShaderStageFlags::VERTEX);
let bindings = &[ubo_binding];
let info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(bindings);
self.descriptor_set_layout = device.create_descriptor_set_layout(&info, None)?;
Ok(())
}
unsafe fn create_render_pass(&mut self, _instance: &Instance, device: &Device) -> Result<()> {
let color_attachment = vk::AttachmentDescription::builder() let color_attachment = vk::AttachmentDescription::builder()
.format(self.swapchain_format) .format(self.swapchain_format)
.samples(vk::SampleCountFlags::_1) .samples(vk::SampleCountFlags::_1)
@ -500,7 +522,7 @@ impl AppData {
Ok(()) Ok(())
} }
pub(super) unsafe fn create_pipeline(&mut self, device: &Device) -> Result<()> { unsafe fn create_pipeline(&mut self, device: &Device) -> Result<()> {
let vert = include_bytes!("../../shaders/vert.spv"); let vert = include_bytes!("../../shaders/vert.spv");
let frag = include_bytes!("../../shaders/frag.spv"); let frag = include_bytes!("../../shaders/frag.spv");
@ -575,7 +597,8 @@ impl AppData {
.attachments(attachments) .attachments(attachments)
.blend_constants([0.0, 0.0, 0.0, 0.0]); .blend_constants([0.0, 0.0, 0.0, 0.0]);
let layout_info = vk::PipelineLayoutCreateInfo::builder(); let set_layouts = &[self.descriptor_set_layout];
let layout_info = vk::PipelineLayoutCreateInfo::builder().set_layouts(set_layouts);
self.pipeline_layout = device.create_pipeline_layout(&layout_info, None)?; self.pipeline_layout = device.create_pipeline_layout(&layout_info, None)?;
let stages = &[vert_stage, frag_stage]; let stages = &[vert_stage, frag_stage];
@ -602,7 +625,7 @@ impl AppData {
Ok(()) Ok(())
} }
pub(super) unsafe fn create_framebuffers(&mut self, device: &Device) -> Result<()> { unsafe fn create_framebuffers(&mut self, device: &Device) -> Result<()> {
self.framebuffers = self self.framebuffers = self
.swapchain_image_views .swapchain_image_views
.iter() .iter()
@ -626,11 +649,7 @@ impl AppData {
// Command Pool // Command Pool
//================================================ //================================================
pub(super) unsafe fn create_command_pool( unsafe fn create_command_pool(&mut self, instance: &Instance, device: &Device) -> Result<()> {
&mut self,
instance: &Instance,
device: &Device,
) -> Result<()> {
let indices = QueueFamilyIndices::get(instance, self, self.physical_device)?; let indices = QueueFamilyIndices::get(instance, self, self.physical_device)?;
let info = vk::CommandPoolCreateInfo::builder() let info = vk::CommandPoolCreateInfo::builder()
@ -711,11 +730,7 @@ impl AppData {
Ok(()) Ok(())
} }
pub(super) unsafe fn create_vertex_buffer( unsafe fn create_vertex_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> {
&mut self,
instance: &Instance,
device: &Device,
) -> Result<()> {
// Create staging buffer // Create staging buffer
let size = (size_of::<Vertex>() * VERTICES.len()) as u64; let size = (size_of::<Vertex>() * VERTICES.len()) as u64;
let (staging_buffer, staging_buffer_memory) = self.create_buffer( let (staging_buffer, staging_buffer_memory) = self.create_buffer(
@ -753,11 +768,7 @@ impl AppData {
Ok(()) Ok(())
} }
pub(super) unsafe fn create_index_buffer( unsafe fn create_index_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> {
&mut self,
instance: &Instance,
device: &Device,
) -> Result<()> {
let size = (size_of::<u16>() * INDICES.len()) as u64; let size = (size_of::<u16>() * INDICES.len()) as u64;
let (staging_buffer, staging_buffer_memory) = self.create_buffer( let (staging_buffer, staging_buffer_memory) = self.create_buffer(
instance, instance,
@ -791,11 +802,35 @@ impl AppData {
Ok(()) Ok(())
} }
unsafe fn create_uniform_buffers(
&mut self,
instance: &Instance,
device: &Device,
) -> Result<()> {
self.uniform_buffers.clear();
self.uniform_buffers_memory.clear();
for _ in 0..self.swapchain_images.len() {
let (uniform_buffer, uniform_buffer_memory) = self.create_buffer(
instance,
device,
size_of::<UniformBufferObject>() as u64,
vk::BufferUsageFlags::UNIFORM_BUFFER,
vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE,
)?;
self.uniform_buffers.push(uniform_buffer);
self.uniform_buffers_memory.push(uniform_buffer_memory);
}
Ok(())
}
//================================================ //================================================
// Command Buffers // Command Buffers
//================================================ //================================================
pub(super) unsafe fn create_command_buffers(&mut self, device: &Device) -> Result<()> { unsafe fn create_command_buffers(&mut self, device: &Device) -> Result<()> {
// Create the buffers // Create the buffers
let allocate_info = vk::CommandBufferAllocateInfo::builder() let allocate_info = vk::CommandBufferAllocateInfo::builder()
.command_pool(self.command_pool) .command_pool(self.command_pool)
@ -857,7 +892,7 @@ impl AppData {
// Sync Objects // Sync Objects
//================================================ //================================================
pub(super) unsafe fn create_sync_objects(&mut self, device: &Device) -> Result<()> { unsafe fn create_sync_objects(&mut self, device: &Device) -> Result<()> {
let semaphore_info = vk::SemaphoreCreateInfo::builder(); let semaphore_info = vk::SemaphoreCreateInfo::builder();
let fence_info = vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED); let fence_info = vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED);

View File

@ -132,3 +132,14 @@ impl Vertex {
[pos, color] [pos, color]
} }
} }
// ----------------------------------------------------------------------------
// Resource Descriptors
// ----------------------------------------------------------------------------
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct UniformBufferObject {
pub(crate) model: glm::Mat4,
pub(crate) view: glm::Mat4,
pub(crate) proj: glm::Mat4,
}