From fafbf868bf2501ff8b9c1152efabfcdbc600dc11 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 13 Apr 2023 10:14:10 -0400 Subject: [PATCH] Add Descriptor layout and its buffer --- Cargo.toml | 2 +- shaders/shader.vert | 8 +++- shaders/vert.spv | Bin 1080 -> 1676 bytes src/app.rs | 49 +++++++++++++++++++- src/app/data.rs | 107 +++++++++++++++++++++++++++++--------------- src/app/structs.rs | 11 +++++ 6 files changed, 138 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 868eea4..57c2281 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,5 @@ png = "0.17" pretty_env_logger = "0.4" thiserror = "1" 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" diff --git a/shaders/shader.vert b/shaders/shader.vert index 9f27f54..5ffbb2d 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -1,11 +1,17 @@ #version 450 +layout(binding = 0) uniform UniformBufferObject { + mat4 model; + mat4 view; + mat4 proj; +} ubo; + layout(location = 0) in vec2 inPosition; layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; 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; } diff --git a/shaders/vert.spv b/shaders/vert.spv index 1e4ce0c041e7ee15f8cf030b9c3e352942361e75..2b7afb085438ec62cb2bb608d0d6abffff1971b3 100644 GIT binary patch literal 1676 zcmZ9L+fEZv6o$970|){la!?Ul@QflRYD|nrH07d6F+^`0Xs2Y8VWyc*@o>c}=p*@5 z-kA7*duBJIo2;(2{&n2{9x7uS6ULk~(`LpzHu;%1V?vCuai<&2{pQvn>ux=Hx=qHc zsklUP=FE9#SM_^xU}KyaNnP?#@<>wA-q5A-IKd>0`-`e{uJ9@lAgR9 z_IhF3Iy~0>)FW^)@=lU&7)g7KeNJuog_y_Kqn{?nV9Z#M9v&vL1IM$CN7r%~y!X6xelMYHxl0q?EgAum+SDUJCpc2Fki>c>;=})&TzUe;dsBEyUxd6EBSC- z_W927*=<2x>08$fc*0(iH7;F~ENdQn;KSddekY}C63%Af^Pfe(RryoWw&b+#|(V<1M@vE z7e4umg-s71Uy;oYaB)MLyHQVmO_~@u{qgG(FzU(WZ8_e*>AbVo)ZdfMeYpqyH>Ifo zBmSVU!Re3Bd;0j6?0i-p$LD>)o{1CogdYwyzlHGaz11&wU6Q~D9K2K}_g-Y|-1t$j{*ClnyNA-q_TLmUH!fqEB z_uLbE@OMW-F0l;>JpWJ+Vs|CXB8UCp{l0|njs0GU9encG1HQKgiOpt2xJ3s0hxr}j8kznF2RA| zIiVvyxV*Zzez&IO`)Zjt`YRDxtVbEgv+{AR84*Vy%?96j5zXo&Yqb?##)IMA=yfzE zE@CNC^_2}z?ul&a0-xOK|2$O>`RAlVW|Pb^Xn-Dki$4SEmo;~q+Bw|XZQxt*_ME-l z*uO`d15OC%AMo3wX8y2_(a+`!6tuS}(5B05)POuyr$v8q1=CgwXz7`w9lcX)e1BS} t)|~W&8SU%>Yt4Crwr`oC<$X|s4RDPYx%KYUNiQf%1SYkM5I-2b0Kc}`8@>Pl diff --git a/src/app.rs b/src/app.rs index 6b25052..644d46a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -9,6 +9,8 @@ use ::anyhow::{anyhow, Result}; use ::lazy_static::lazy_static; use ::nalgebra_glm as glm; use ::std::mem::size_of; +use ::std::ptr::copy_nonoverlapping as memcpy; +use ::std::time::Instant; use ::vulkanalia::loader::{LibloadingLoader, LIBRARY}; use ::vulkanalia::prelude::v1_0::*; use ::vulkanalia::vk::{KhrSurfaceExtension, KhrSwapchainExtension}; @@ -49,6 +51,7 @@ pub struct App { pub device: Device, frame: usize, pub resized: bool, + start: Instant, } impl App { @@ -72,6 +75,7 @@ impl App { device, frame: 0, resized: false, + start: Instant::now(), }) } } @@ -82,7 +86,6 @@ impl App { /// Here be Dragons pub fn destroy(&mut self) { unsafe { - self.data.destroy_swapchain(&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.update_uniform_buffer(image_index)?; + let wait_semaphores = &[self.data.image_available_semaphores[self.frame]]; let wait_stages = &[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; let command_buffers = &[self.data.command_buffers[image_index]]; @@ -158,6 +163,48 @@ impl App { 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::() 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 /// /// # Safety diff --git a/src/app/data.rs b/src/app/data.rs index 1de55eb..cc229c9 100644 --- a/src/app/data.rs +++ b/src/app/data.rs @@ -48,12 +48,13 @@ pub(crate) struct AppData { pub(super) present_queue: vk::Queue, // Swapchain swapchain_format: vk::Format, - swapchain_extent: vk::Extent2D, + pub(super) swapchain_extent: vk::Extent2D, pub(super) swapchain: vk::SwapchainKHR, swapchain_images: Vec, swapchain_image_views: Vec, // Pipeline render_pass: vk::RenderPass, + descriptor_set_layout: vk::DescriptorSetLayout, pipeline_layout: vk::PipelineLayout, pipeline: vk::Pipeline, // Framebuffers @@ -65,6 +66,8 @@ pub(crate) struct AppData { vertex_buffer_memory: vk::DeviceMemory, index_buffer: vk::Buffer, index_buffer_memory: vk::DeviceMemory, + uniform_buffers: Vec, + pub(super) uniform_buffers_memory: Vec, // Command Buffers pub(super) command_buffers: Vec, // Sync Objects @@ -93,22 +96,20 @@ impl AppData { self.create_swapchain(window, &instance, &device)?; self.create_swapchain_image_views(&device)?; self.create_render_pass(&instance, &device)?; + self.create_descriptor_set_layout(&device)?; self.create_pipeline(&device)?; self.create_framebuffers(&device)?; self.create_command_pool(&instance, &device)?; self.create_vertex_buffer(&instance, &device)?; self.create_index_buffer(&instance, &device)?; + self.create_uniform_buffers(&instance, &device)?; self.create_command_buffers(&device)?; self.create_sync_objects(&device)?; Ok((instance, device)) } - pub(super) unsafe fn create_instance( - &mut self, - window: &Window, - entry: &Entry, - ) -> Result { + unsafe fn create_instance(&mut self, window: &Window, entry: &Entry) -> Result { // Application Info let application_info = vk::ApplicationInfo::builder() .application_name(b"Vulkan Tutorial\0") @@ -192,7 +193,13 @@ impl AppData { /// /// # Safety /// 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 .iter() .for_each(|f| device.destroy_framebuffer(*f, None)); @@ -211,6 +218,9 @@ impl AppData { /// # Safety /// Here be Dragons 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.free_memory(self.index_buffer_memory, None); device.destroy_buffer(self.vertex_buffer, None); @@ -240,7 +250,7 @@ impl AppData { // 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()? { let properties = instance.get_physical_device_properties(physical_device); @@ -279,7 +289,7 @@ impl AppData { // Logical Device //================================================ - pub(super) unsafe fn create_logical_device(&mut self, instance: &Instance) -> Result { + unsafe fn create_logical_device(&mut self, instance: &Instance) -> Result { // Queue Create Infos let indices = QueueFamilyIndices::get(instance, self, self.physical_device)?; @@ -342,7 +352,7 @@ impl AppData { // Swapchain //================================================ - pub(super) unsafe fn create_swapchain( + unsafe fn create_swapchain( &mut self, window: &Window, instance: &Instance, @@ -412,6 +422,7 @@ impl AppData { self.create_render_pass(instance, device)?; self.create_pipeline(device)?; self.create_framebuffers(device)?; + self.create_uniform_buffers(instance, device)?; self.create_command_buffers(device)?; self.images_in_flight @@ -420,7 +431,7 @@ impl AppData { 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 .swapchain_images .iter() @@ -456,11 +467,22 @@ impl AppData { // Pipeline //================================================ - pub(super) unsafe fn create_render_pass( - &mut self, - _instance: &Instance, - device: &Device, - ) -> Result<()> { + unsafe fn create_descriptor_set_layout(&mut self, device: &Device) -> Result<()> { + let ubo_binding = vk::DescriptorSetLayoutBinding::builder() + .binding(0) + .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER) + .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() .format(self.swapchain_format) .samples(vk::SampleCountFlags::_1) @@ -500,7 +522,7 @@ impl AppData { 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 frag = include_bytes!("../../shaders/frag.spv"); @@ -575,7 +597,8 @@ impl AppData { .attachments(attachments) .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)?; let stages = &[vert_stage, frag_stage]; @@ -602,7 +625,7 @@ impl AppData { Ok(()) } - pub(super) unsafe fn create_framebuffers(&mut self, device: &Device) -> Result<()> { + unsafe fn create_framebuffers(&mut self, device: &Device) -> Result<()> { self.framebuffers = self .swapchain_image_views .iter() @@ -626,11 +649,7 @@ impl AppData { // Command Pool //================================================ - pub(super) unsafe fn create_command_pool( - &mut self, - instance: &Instance, - device: &Device, - ) -> Result<()> { + unsafe fn create_command_pool(&mut self, instance: &Instance, device: &Device) -> Result<()> { let indices = QueueFamilyIndices::get(instance, self, self.physical_device)?; let info = vk::CommandPoolCreateInfo::builder() @@ -711,11 +730,7 @@ impl AppData { Ok(()) } - pub(super) unsafe fn create_vertex_buffer( - &mut self, - instance: &Instance, - device: &Device, - ) -> Result<()> { + unsafe fn create_vertex_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> { // Create staging buffer let size = (size_of::() * VERTICES.len()) as u64; let (staging_buffer, staging_buffer_memory) = self.create_buffer( @@ -753,11 +768,7 @@ impl AppData { Ok(()) } - pub(super) unsafe fn create_index_buffer( - &mut self, - instance: &Instance, - device: &Device, - ) -> Result<()> { + unsafe fn create_index_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> { let size = (size_of::() * INDICES.len()) as u64; let (staging_buffer, staging_buffer_memory) = self.create_buffer( instance, @@ -791,11 +802,35 @@ impl AppData { 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::() 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 //================================================ - 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 let allocate_info = vk::CommandBufferAllocateInfo::builder() .command_pool(self.command_pool) @@ -857,7 +892,7 @@ impl AppData { // 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 fence_info = vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED); diff --git a/src/app/structs.rs b/src/app/structs.rs index ff010cb..37f5e62 100644 --- a/src/app/structs.rs +++ b/src/app/structs.rs @@ -132,3 +132,14 @@ impl Vertex { [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, +}