use std::sync::Arc; use ash::vk; use crate::*; /// `DescriptorSetLayout` defines the linkage to the shader. /// It describes which resources are defined in the shader and how they must be binded. /// This structure does not need shader directly, it defines only linking rules. /// It can be reused between different pipelines and shaders with the same layout. #[derive(Clone)] pub struct DescriptorSetLayout { // Device that owns the descriptor set layout. device: Arc, // Bindings for uniform buffers. // It contains index defined in the shader. uniform_buffer_bindings: Vec, // Bindings for storage buffers. // It contains index defined in the shader. storage_buffer_bindings: Vec, // Native Vulkan descriptor set layout handle. vk_descriptor_set_layout: vk::DescriptorSetLayout, } pub struct DescriptorSetLayoutBuilder { uniform_buffer_bindings: Vec, storage_buffer_bindings: Vec, } impl DescriptorSetLayoutBuilder { pub fn add_uniform_buffer(mut self, binding: usize) -> Self { self.uniform_buffer_bindings.push(binding); self } pub fn add_storage_buffer(mut self, binding: usize) -> Self { self.storage_buffer_bindings.push(binding); self } pub fn build(&self, device: Arc) -> GpuResult> { let mut descriptor_set_layout_bindings = Vec::new(); for binding in &self.uniform_buffer_bindings { descriptor_set_layout_bindings.push( vk::DescriptorSetLayoutBinding::default() .binding(*binding as u32) .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER) .descriptor_count(1) .stage_flags(vk::ShaderStageFlags::COMPUTE), ); } for binding in &self.storage_buffer_bindings { descriptor_set_layout_bindings.push( vk::DescriptorSetLayoutBinding::default() .binding(*binding as u32) .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) .descriptor_count(1) .stage_flags(vk::ShaderStageFlags::COMPUTE), ); } let descriptor_set_layout_create_info = vk::DescriptorSetLayoutCreateInfo::default().bindings(&descriptor_set_layout_bindings); let vk_descriptor_set_layout = unsafe { device.vk_device().create_descriptor_set_layout( &descriptor_set_layout_create_info, device.cpu_allocation_callbacks(), )? }; Ok(Arc::new(DescriptorSetLayout { device, uniform_buffer_bindings: self.uniform_buffer_bindings.clone(), storage_buffer_bindings: self.storage_buffer_bindings.clone(), vk_descriptor_set_layout, })) } } impl Drop for DescriptorSetLayout { fn drop(&mut self) { unsafe { if self.vk_descriptor_set_layout != vk::DescriptorSetLayout::null() { self.device.vk_device().destroy_descriptor_set_layout( self.vk_descriptor_set_layout, self.device.cpu_allocation_callbacks(), ); self.vk_descriptor_set_layout = vk::DescriptorSetLayout::null(); } self.storage_buffer_bindings.clear(); self.uniform_buffer_bindings.clear(); } } } impl DescriptorSetLayout { pub fn builder() -> DescriptorSetLayoutBuilder { DescriptorSetLayoutBuilder { uniform_buffer_bindings: Vec::new(), storage_buffer_bindings: Vec::new(), } } pub fn vk_descriptor_set_layout(&self) -> vk::DescriptorSetLayout { self.vk_descriptor_set_layout } pub fn device(&self) -> Arc { self.device.clone() } }