diff --git a/shaders/shader.vert b/shaders/shader.vert index 5510aa3..840711c 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -6,7 +6,7 @@ layout(binding = 0) uniform UniformBufferObject { mat4 proj; } ubo; -layout(location = 0) in vec2 inPosition; +layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; layout(location = 2) in vec2 inTexCoord; @@ -14,7 +14,7 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoord; void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); fragColor = inColor; fragTexCoord = inTexCoord; } diff --git a/shaders/vert.spv b/shaders/vert.spv index 9ded648..99280dc 100644 Binary files a/shaders/vert.spv and b/shaders/vert.spv differ diff --git a/src/app.rs b/src/app.rs index 1c449c9..9ba5399 100644 --- a/src/app.rs +++ b/src/app.rs @@ -33,29 +33,49 @@ pub const MAX_FRAMES_IN_FLIGHT: usize = 2; lazy_static! { pub static ref VERTICES: Vec = vec![ Vertex::new( - glm::vec2(-0.5, -0.5), + glm::vec3(-0.5, -0.5, 0.0), glm::vec3(1.0, 0.0, 0.0), glm::vec2(1.0, 0.0) ), Vertex::new( - glm::vec2(0.5, -0.5), + glm::vec3(0.5, -0.5, 0.0), glm::vec3(0.0, 1.0, 0.0), glm::vec2(0.0, 0.0) ), Vertex::new( - glm::vec2(0.5, 0.5), + glm::vec3(0.5, 0.5, 0.0), glm::vec3(0.0, 0.0, 1.0), glm::vec2(0.0, 1.0) ), Vertex::new( - glm::vec2(-0.5, 0.5), + glm::vec3(-0.5, 0.5, 0.0), + glm::vec3(1.0, 1.0, 1.0), + glm::vec2(1.0, 1.0) + ), + Vertex::new( + glm::vec3(-0.5, -0.5, -0.5), + glm::vec3(1.0, 0.0, 0.0), + glm::vec2(1.0, 0.0) + ), + Vertex::new( + glm::vec3(0.5, -0.5, -0.5), + glm::vec3(0.0, 1.0, 0.0), + glm::vec2(0.0, 0.0) + ), + Vertex::new( + glm::vec3(0.5, 0.5, -0.5), + glm::vec3(0.0, 0.0, 1.0), + glm::vec2(0.0, 1.0) + ), + Vertex::new( + glm::vec3(-0.5, 0.5, -0.5), glm::vec3(1.0, 1.0, 1.0), glm::vec2(1.0, 1.0) ), ]; } -pub const INDICES: &[u16] = &[0, 1, 2, 2, 3, 0]; +pub const INDICES: &[u16] = &[0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4]; /// Our Vulkan app. #[derive(Clone, Debug)] @@ -194,7 +214,7 @@ impl App { &glm::vec3(0.0, 0.0, 1.0), ); - let mut proj = glm::perspective( + let mut proj = glm::perspective_rh_zo( self.data.swapchain_extent.width as f32 / self.data.swapchain_extent.height as f32, glm::radians(&glm::vec1(45.0))[0], 0.1, @@ -326,9 +346,10 @@ pub(crate) unsafe fn create_image_view( device: &Device, image: vk::Image, format: vk::Format, + aspects: vk::ImageAspectFlags, ) -> Result { let subresource_range = vk::ImageSubresourceRange::builder() - .aspect_mask(vk::ImageAspectFlags::COLOR) + .aspect_mask(aspects) .base_mip_level(0) .level_count(1) .base_array_layer(0) diff --git a/src/app/data.rs b/src/app/data.rs index 7fa6bef..a5bf641 100644 --- a/src/app/data.rs +++ b/src/app/data.rs @@ -62,6 +62,10 @@ pub(crate) struct AppData { framebuffers: Vec, // Command Pool command_pool: vk::CommandPool, + // Depth + depth_image: vk::Image, + depth_image_memory: vk::DeviceMemory, + depth_image_view: vk::ImageView, // Texture texture_image: vk::Image, texture_image_memory: vk::DeviceMemory, @@ -107,8 +111,9 @@ impl AppData { 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_depth_objects(&instance, &device)?; + self.create_framebuffers(&device)?; self.create_texture_image(&instance, &device)?; self.create_texture_image_view(&device)?; self.create_texture_sampler(&device)?; @@ -215,6 +220,9 @@ impl AppData { self.uniform_buffers_memory .iter() .for_each(|m| device.free_memory(*m, None)); + device.destroy_image_view(self.depth_image_view, None); + device.free_memory(self.depth_image_memory, None); + device.destroy_image(self.depth_image, None); self.framebuffers .iter() .for_each(|f| device.destroy_framebuffer(*f, None)); @@ -445,6 +453,7 @@ impl AppData { self.create_swapchain_image_views(device)?; self.create_render_pass(instance, device)?; self.create_pipeline(device)?; + self.create_depth_objects(instance, device)?; self.create_framebuffers(device)?; self.create_uniform_buffers(instance, device)?; self.create_descriptor_pool(device)?; @@ -461,7 +470,14 @@ impl AppData { self.swapchain_image_views = self .swapchain_images .iter() - .map(|i| create_image_view(device, *i, self.swapchain_format)) + .map(|i| { + create_image_view( + device, + *i, + self.swapchain_format, + vk::ImageAspectFlags::COLOR, + ) + }) .collect::, _>>()?; Ok(()) @@ -471,7 +487,7 @@ impl AppData { // Pipeline //================================================ - unsafe fn create_render_pass(&mut self, _instance: &Instance, device: &Device) -> Result<()> { + 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) @@ -482,23 +498,46 @@ impl AppData { .initial_layout(vk::ImageLayout::UNDEFINED) .final_layout(vk::ImageLayout::PRESENT_SRC_KHR); + let depth_stencil_attachment = vk::AttachmentDescription::builder() + .format(self.get_depth_format(instance)?) + .samples(vk::SampleCountFlags::_1) + .load_op(vk::AttachmentLoadOp::CLEAR) + .store_op(vk::AttachmentStoreOp::DONT_CARE) + .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) + .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) + .initial_layout(vk::ImageLayout::UNDEFINED) + .final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + // Subpasses let color_attachment_ref = vk::AttachmentReference::builder() .attachment(0) .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); + let depth_stencil_attachment_ref = vk::AttachmentReference::builder() + .attachment(1) + .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); let color_attachments = &[color_attachment_ref]; let subpass = vk::SubpassDescription::builder() .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) - .color_attachments(color_attachments); + .color_attachments(color_attachments) + .depth_stencil_attachment(&depth_stencil_attachment_ref); let dependency = vk::SubpassDependency::builder() .src_subpass(vk::SUBPASS_EXTERNAL) .dst_subpass(0) - .src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT) + .src_stage_mask( + vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT + | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS, + ) .src_access_mask(vk::AccessFlags::empty()) - .dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT) - .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE); + .dst_stage_mask( + vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT + | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS, + ) + .dst_access_mask( + vk::AccessFlags::COLOR_ATTACHMENT_WRITE + | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, + ); - let attachments = &[color_attachment]; + let attachments = &[color_attachment, depth_stencil_attachment]; let subpasses = &[subpass]; let dependencies = &[dependency]; let info = vk::RenderPassCreateInfo::builder() @@ -590,6 +629,13 @@ impl AppData { .sample_shading_enable(false) .rasterization_samples(vk::SampleCountFlags::_1); + let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::builder() + .depth_test_enable(true) + .depth_write_enable(true) + .depth_compare_op(vk::CompareOp::LESS) + .depth_bounds_test_enable(false) + .stencil_test_enable(false); + let attachment = vk::PipelineColorBlendAttachmentState::builder() .color_write_mask(vk::ColorComponentFlags::all()) .blend_enable(false) @@ -619,6 +665,7 @@ impl AppData { .viewport_state(&viewport_state) .rasterization_state(&rasterization_state) .multisample_state(&multisample_state) + .depth_stencil_state(&depth_stencil_state) .color_blend_state(&color_blend_state) .layout(self.pipeline_layout) .render_pass(self.render_pass) @@ -644,7 +691,7 @@ impl AppData { .swapchain_image_views .iter() .map(|i| { - let attachments = &[*i]; + let attachments = &[*i, self.depth_image_view]; let create_info = vk::FramebufferCreateInfo::builder() .render_pass(self.render_pass) .attachments(attachments) @@ -675,6 +722,77 @@ impl AppData { Ok(()) } + //================================================ + // Depth Objects + //================================================ + + unsafe fn create_depth_objects(&mut self, instance: &Instance, device: &Device) -> Result<()> { + let format = self.get_depth_format(instance)?; + + let (depth_image, depth_image_memory) = self.create_image( + instance, + device, + self.swapchain_extent.width, + self.swapchain_extent.height, + format, + vk::ImageTiling::OPTIMAL, + vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT, + vk::MemoryPropertyFlags::DEVICE_LOCAL, + )?; + + self.depth_image = depth_image; + self.depth_image_memory = depth_image_memory; + + self.depth_image_view = create_image_view( + device, + self.depth_image, + format, + vk::ImageAspectFlags::DEPTH, + )?; + + Ok(()) + } + + unsafe fn get_depth_format(&self, instance: &Instance) -> Result { + let candidates = &[ + vk::Format::D32_SFLOAT, + vk::Format::D32_SFLOAT_S8_UINT, + vk::Format::D24_UNORM_S8_UINT, + ]; + + self.get_supported_format( + instance, + candidates, + vk::ImageTiling::OPTIMAL, + vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT, + ) + } + + unsafe fn get_supported_format( + &self, + instance: &Instance, + candidates: &[vk::Format], + tiling: vk::ImageTiling, + features: vk::FormatFeatureFlags, + ) -> Result { + candidates + .iter() + .cloned() + .find(|f| { + let properties = + instance.get_physical_device_format_properties(self.physical_device, *f); + + match tiling { + vk::ImageTiling::LINEAR => properties.linear_tiling_features.contains(features), + vk::ImageTiling::OPTIMAL => { + properties.optimal_tiling_features.contains(features) + } + _ => false, + } + }) + .ok_or_else(|| anyhow!("Failed to find supported depth image format.")) + } + //================================================ // Texture //================================================ @@ -752,8 +870,12 @@ impl AppData { } unsafe fn create_texture_image_view(&mut self, device: &Device) -> Result<()> { - self.texture_image_view = - create_image_view(device, self.texture_image, vk::Format::R8G8B8A8_SRGB)?; + self.texture_image_view = create_image_view( + device, + self.texture_image, + vk::Format::R8G8B8A8_SRGB, + vk::ImageAspectFlags::COLOR, + )?; Ok(()) } @@ -981,7 +1103,14 @@ impl AppData { }, }; - let clear_values = &[color_clear_value]; + let depth_clear_value = vk::ClearValue { + depth_stencil: vk::ClearDepthStencilValue { + depth: 1.0, + stencil: 0, + }, + }; + + let clear_values = &[color_clear_value, depth_clear_value]; let info = vk::RenderPassBeginInfo::builder() .render_pass(self.render_pass) .framebuffer(self.framebuffers[i]) diff --git a/src/app/structs.rs b/src/app/structs.rs index 3fb93ea..4125466 100644 --- a/src/app/structs.rs +++ b/src/app/structs.rs @@ -97,13 +97,13 @@ impl SwapchainSupport { #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct Vertex { - pos: glm::Vec2, + pos: glm::Vec3, color: glm::Vec3, tex_coord: glm::Vec2, } impl Vertex { - pub fn new(pos: glm::Vec2, color: glm::Vec3, tex_coord: glm::Vec2) -> Self { + pub fn new(pos: glm::Vec3, color: glm::Vec3, tex_coord: glm::Vec2) -> Self { Self { pos, color, @@ -123,7 +123,7 @@ impl Vertex { let pos = vk::VertexInputAttributeDescription::builder() .binding(0) .location(0) - .format(vk::Format::R32G32_SFLOAT) + .format(vk::Format::R32G32B32_SFLOAT) .offset(0) .build(); @@ -131,14 +131,14 @@ impl Vertex { .binding(0) .location(1) .format(vk::Format::R32G32B32_SFLOAT) - .offset(size_of::() as u32) + .offset(size_of::() as u32) .build(); let tex_coord = vk::VertexInputAttributeDescription::builder() .binding(0) .location(2) .format(vk::Format::R32G32_SFLOAT) - .offset((size_of::() + size_of::()) as u32) + .offset((size_of::() + size_of::()) as u32) .build(); [pos, color, tex_coord]