From 1bfe6e7c3520962a23b63c4e3a11de62fe5ef7a3 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 6 Nov 2018 00:34:11 -0800 Subject: [PATCH] working on getting vulkan_minimal_compute to run --- vulkan-driver/src/api_impl.rs | 232 +++++++++--- vulkan-driver/src/buffer.rs | 32 ++ vulkan-driver/src/descriptor_set.rs | 557 ++++++++++++++++++++++++++++ vulkan-driver/src/handle.rs | 25 +- vulkan-driver/src/image.rs | 122 +++++- vulkan-driver/src/lib.rs | 2 + vulkan-driver/src/render_pass.rs | 5 + vulkan-driver/src/sampler.rs | 3 + 8 files changed, 900 insertions(+), 78 deletions(-) create mode 100644 vulkan-driver/src/descriptor_set.rs create mode 100644 vulkan-driver/src/render_pass.rs diff --git a/vulkan-driver/src/api_impl.rs b/vulkan-driver/src/api_impl.rs index dc7fc4f..6168516 100644 --- a/vulkan-driver/src/api_impl.rs +++ b/vulkan-driver/src/api_impl.rs @@ -2,21 +2,26 @@ // Copyright 2018 Jacob Lifshay // allow unneeded_field_pattern to ensure fields aren't accidently missed -#![cfg_attr( - feature = "cargo-clippy", - allow(clippy::unneeded_field_pattern) -)] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::unneeded_field_pattern))] use api; use buffer::{Buffer, BufferMemory}; use constants::*; +use descriptor_set::{ + Descriptor, DescriptorLayout, DescriptorPool, DescriptorSet, DescriptorSetLayout, + DescriptorWriteArg, +}; use device_memory::{ DeviceMemory, DeviceMemoryAllocation, DeviceMemoryHeap, DeviceMemoryHeaps, DeviceMemoryLayout, DeviceMemoryType, DeviceMemoryTypes, }; use enum_map::EnumMap; use handle::{Handle, MutHandle, OwnedHandle, SharedHandle}; -use image::{Image, ImageMemory, ImageMultisampleCount, ImageProperties, SupportedTilings}; +use image::{ + ComponentMapping, Image, ImageMemory, ImageMultisampleCount, ImageProperties, ImageView, + ImageViewType, SupportedTilings, +}; +use render_pass::RenderPass; use sampler; use sampler::Sampler; use shader_module::ShaderModule; @@ -242,7 +247,7 @@ macro_rules! parse_next_chain_const { } => { $(let mut $name: *const $var_type = null();)* parse_next_chain_const( - $root as *const api::VkBaseInStructure, + $root as *const _ as *const api::VkBaseInStructure, $root_type, &[$(($struct_type, &mut $name as *mut *const $var_type as *mut *const api::VkBaseInStructure)),*] ); @@ -257,7 +262,7 @@ macro_rules! parse_next_chain_mut { } => { $(let mut $name: *mut $var_type = null_mut();)* parse_next_chain_mut( - $root as *mut api::VkBaseOutStructure, + $root as *mut _ as *mut api::VkBaseOutStructure, $root_type, &[$(($struct_type, &mut $name as *mut *mut $var_type as *mut *mut api::VkBaseOutStructure)),*] ); @@ -651,10 +656,7 @@ enum GetProcAddressScope { Device, } -#[cfg_attr( - feature = "cargo-clippy", - allow(clippy::cyclomatic_complexity) -)] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::cyclomatic_complexity))] fn get_proc_address( name: *const c_char, scope: GetProcAddressScope, @@ -1651,7 +1653,7 @@ impl Device { let mut queue_counts: Vec<_> = Vec::new(); for queue_create_info in queue_create_infos { parse_next_chain_const!{ - queue_create_info as *const api::VkDeviceQueueCreateInfo, + queue_create_info, root = api::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, } let api::VkDeviceQueueCreateInfo { @@ -3476,7 +3478,7 @@ unsafe fn get_physical_device_queue_family_properties( queue_count: u32, ) { parse_next_chain_mut!{ - queue_family_properties as *mut api::VkQueueFamilyProperties2, + queue_family_properties, root = api::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, } queue_family_properties.queueFamilyProperties = api::VkQueueFamilyProperties { @@ -4142,20 +4144,33 @@ pub unsafe extern "system" fn vkGetImageSubresourceLayout( #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateImageView( _device: api::VkDevice, - _pCreateInfo: *const api::VkImageViewCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pView: *mut api::VkImageView, + create_info: *const api::VkImageViewCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + view: *mut api::VkImageView, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + } + let create_info = &*create_info; + let new_view = OwnedHandle::::new(ImageView { + image: SharedHandle::from(create_info.image).unwrap(), + view_type: ImageViewType::from(create_info.viewType), + format: create_info.format, + component_mapping: ComponentMapping::from(create_info.components).unwrap(), + subresource_range: create_info.subresourceRange, + }); + *view = new_view.take(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyImageView( _device: api::VkDevice, - _imageView: api::VkImageView, - _pAllocator: *const api::VkAllocationCallbacks, + image_view: api::VkImageView, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(image_view); } #[allow(non_snake_case)] @@ -4338,78 +4353,171 @@ pub unsafe extern "system" fn vkDestroySampler( #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateDescriptorSetLayout( _device: api::VkDevice, - _pCreateInfo: *const api::VkDescriptorSetLayoutCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pSetLayout: *mut api::VkDescriptorSetLayout, + create_info: *const api::VkDescriptorSetLayoutCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + set_layout: *mut api::VkDescriptorSetLayout, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + } + let create_info = &*create_info; + let bindings = match create_info.bindingCount { + 0 => &[], + binding_count => slice::from_raw_parts(create_info.pBindings, binding_count as usize), + }; + let max_binding = bindings.iter().map(|v| v.binding).max().unwrap_or(0) as usize; + let mut bindings_map: Vec> = (0..=max_binding).map(|_| None).collect(); + for binding in bindings { + let bindings_map_entry = &mut bindings_map[binding.binding as usize]; + assert!( + bindings_map_entry.is_none(), + "duplicate binding: {}", + binding.binding + ); + *bindings_map_entry = Some(DescriptorLayout::from(binding)); + } + *set_layout = OwnedHandle::::new(DescriptorSetLayout { + bindings: bindings_map, + }) + .take(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyDescriptorSetLayout( _device: api::VkDevice, - _descriptorSetLayout: api::VkDescriptorSetLayout, - _pAllocator: *const api::VkAllocationCallbacks, + descriptor_set_layout: api::VkDescriptorSetLayout, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(descriptor_set_layout); } #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateDescriptorPool( _device: api::VkDevice, - _pCreateInfo: *const api::VkDescriptorPoolCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pDescriptorPool: *mut api::VkDescriptorPool, + create_info: *const api::VkDescriptorPoolCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + descriptor_pool: *mut api::VkDescriptorPool, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + } + *descriptor_pool = OwnedHandle::::new(DescriptorPool::new()).take(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyDescriptorPool( _device: api::VkDevice, - _descriptorPool: api::VkDescriptorPool, - _pAllocator: *const api::VkAllocationCallbacks, + descriptor_pool: api::VkDescriptorPool, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(descriptor_pool); } #[allow(non_snake_case)] pub unsafe extern "system" fn vkResetDescriptorPool( _device: api::VkDevice, - _descriptorPool: api::VkDescriptorPool, + descriptor_pool: api::VkDescriptorPool, _flags: api::VkDescriptorPoolResetFlags, ) -> api::VkResult { - unimplemented!() + MutHandle::from(descriptor_pool).unwrap().reset(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkAllocateDescriptorSets( _device: api::VkDevice, - _pAllocateInfo: *const api::VkDescriptorSetAllocateInfo, - _pDescriptorSets: *mut api::VkDescriptorSet, + allocate_info: *const api::VkDescriptorSetAllocateInfo, + descriptor_sets: *mut api::VkDescriptorSet, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + allocate_info, + root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + } + let allocate_info = &*allocate_info; + let mut descriptor_pool = MutHandle::from(allocate_info.descriptorPool).unwrap(); + let descriptor_sets = + slice::from_raw_parts_mut(descriptor_sets, allocate_info.descriptorSetCount as usize); + let descriptor_set_layouts = slice::from_raw_parts( + allocate_info.pSetLayouts, + allocate_info.descriptorSetCount as usize, + ); + descriptor_pool.allocate( + descriptor_set_layouts + .iter() + .map(|descriptor_set_layout| DescriptorSet { + bindings: SharedHandle::from(*descriptor_set_layout) + .unwrap() + .bindings + .iter() + .map(|layout| layout.as_ref().map(Descriptor::from)) + .collect(), + }), + descriptor_sets, + ); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkFreeDescriptorSets( _device: api::VkDevice, - _descriptorPool: api::VkDescriptorPool, - _descriptorSetCount: u32, - _pDescriptorSets: *const api::VkDescriptorSet, + descriptor_pool: api::VkDescriptorPool, + descriptor_set_count: u32, + descriptor_sets: *const api::VkDescriptorSet, ) -> api::VkResult { - unimplemented!() + let mut descriptor_pool = MutHandle::from(descriptor_pool).unwrap(); + let descriptor_sets = slice::from_raw_parts(descriptor_sets, descriptor_set_count as usize); + descriptor_pool.free(descriptor_sets); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkUpdateDescriptorSets( _device: api::VkDevice, - _descriptorWriteCount: u32, - _pDescriptorWrites: *const api::VkWriteDescriptorSet, - _descriptorCopyCount: u32, - _pDescriptorCopies: *const api::VkCopyDescriptorSet, -) { - unimplemented!() + descriptor_write_count: u32, + descriptor_writes: *const api::VkWriteDescriptorSet, + descriptor_copy_count: u32, + descriptor_copies: *const api::VkCopyDescriptorSet, +) { + let descriptor_writes = + slice::from_raw_parts(descriptor_writes, descriptor_write_count as usize); + let descriptor_copies = + slice::from_raw_parts(descriptor_copies, descriptor_copy_count as usize); + for descriptor_write in descriptor_writes { + parse_next_chain_const!{ + descriptor_write, + root = api::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + } + let mut descriptor_set = MutHandle::from(descriptor_write.dstSet).unwrap(); + let mut binding_index = descriptor_write.dstBinding as usize; + let mut elements = DescriptorWriteArg::from(descriptor_write); + let mut start_element = Some(descriptor_write.dstArrayElement as usize); + while elements.len() != 0 { + let binding = descriptor_set.bindings[binding_index].as_mut().unwrap(); + binding_index += 1; + assert_eq!(binding.descriptor_type(), descriptor_write.descriptorType); + if binding.element_count() == 0 { + assert_eq!(start_element, None); + continue; + } + let start_element = start_element.take().unwrap_or(0); + let used_elements = elements + .len() + .min(binding.element_count().checked_sub(start_element).unwrap()); + binding.write(start_element, elements.slice_to(..used_elements)); + elements = elements.slice_from(used_elements..); + } + } + for descriptor_copy in descriptor_copies { + parse_next_chain_const!{ + descriptor_copy, + root = api::VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, + } + unimplemented!() + } } #[allow(non_snake_case)] @@ -4434,20 +4542,26 @@ pub unsafe extern "system" fn vkDestroyFramebuffer( #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateRenderPass( _device: api::VkDevice, - _pCreateInfo: *const api::VkRenderPassCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pRenderPass: *mut api::VkRenderPass, + create_info: *const api::VkRenderPassCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + render_pass: *mut api::VkRenderPass, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + } + // FIXME: finish implementing + *render_pass = OwnedHandle::::new(RenderPass {}).take(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyRenderPass( _device: api::VkDevice, - _renderPass: api::VkRenderPass, - _pAllocator: *const api::VkAllocationCallbacks, + render_pass: api::VkRenderPass, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(render_pass); } #[allow(non_snake_case)] @@ -5008,7 +5122,7 @@ pub unsafe extern "system" fn vkBindBufferMemory2( let bind_infos = slice::from_raw_parts(bind_infos, bind_info_count as usize); for bind_info in bind_infos { parse_next_chain_const!{ - bind_info as *const api::VkBindBufferMemoryInfo, + bind_info, root = api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, device_group_info: api::VkBindBufferMemoryDeviceGroupInfo = api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, } @@ -5046,7 +5160,7 @@ pub unsafe extern "system" fn vkBindImageMemory2( let bind_infos = slice::from_raw_parts(bind_infos, bind_info_count as usize); for bind_info in bind_infos { parse_next_chain_const!{ - bind_info as *const api::VkBindImageMemoryInfo, + bind_info, root = api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, device_group_info: api::VkBindImageMemoryDeviceGroupInfo = api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, swapchain_info: api::VkBindImageMemorySwapchainInfoKHR = api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR, @@ -5127,7 +5241,7 @@ pub unsafe extern "system" fn vkEnumeratePhysicalDeviceGroups( iter::once(()), |physical_device_group_properties, _| { parse_next_chain_mut!{ - physical_device_group_properties as *mut api::VkPhysicalDeviceGroupProperties, + physical_device_group_properties, root = api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES, } let mut physical_devices = [Handle::null(); api::VK_MAX_DEVICE_GROUP_SIZE as usize]; diff --git a/vulkan-driver/src/buffer.rs b/vulkan-driver/src/buffer.rs index 9ece100..697d7b7 100644 --- a/vulkan-driver/src/buffer.rs +++ b/vulkan-driver/src/buffer.rs @@ -3,12 +3,44 @@ use api; use handle::SharedHandle; +#[derive(Debug)] pub struct BufferMemory { pub device_memory: SharedHandle, pub offset: usize, } +#[derive(Debug)] pub struct Buffer { pub size: usize, pub memory: Option, } + +#[derive(Debug)] +pub struct BufferSlice { + pub buffer: SharedHandle, + pub offset: usize, + pub size: usize, +} + +impl BufferSlice { + pub unsafe fn from(v: &api::VkDescriptorBufferInfo) -> Self { + let buffer = SharedHandle::from(v.buffer).unwrap(); + assert!(v.offset < buffer.size as u64); + let offset = v.offset as usize; + let size = if v.range == api::VK_WHOLE_SIZE as u64 { + buffer.size - offset + } else { + assert!(v.range != 0); + assert!(v.range.checked_add(v.offset).unwrap() <= buffer.size as u64); + v.range as usize + }; + Self { + buffer, + offset, + size, + } + } +} + +#[derive(Debug)] +pub struct BufferView {} diff --git a/vulkan-driver/src/descriptor_set.rs b/vulkan-driver/src/descriptor_set.rs new file mode 100644 index 0000000..5de5f0d --- /dev/null +++ b/vulkan-driver/src/descriptor_set.rs @@ -0,0 +1,557 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright 2018 Jacob Lifshay + +use api; +use buffer::BufferSlice; +use handle::OwnedHandle; +use handle::SharedHandle; +use image; +use std::ops; +use std::slice; + +#[derive(Debug)] +pub enum DescriptorLayout { + Sampler { + count: usize, + immutable_samplers: Option>>, + }, + CombinedImageSampler { + count: usize, + immutable_samplers: Option>>, + }, + SampledImage { + count: usize, + }, + StorageImage { + count: usize, + }, + UniformTexelBuffer { + count: usize, + }, + StorageTexelBuffer { + count: usize, + }, + UniformBuffer { + count: usize, + }, + StorageBuffer { + count: usize, + }, + UniformBufferDynamic { + count: usize, + }, + StorageBufferDynamic { + count: usize, + }, + InputAttachment { + count: usize, + }, +} + +impl DescriptorLayout { + #[allow(dead_code)] + pub fn count(&self) -> usize { + match *self { + DescriptorLayout::Sampler { count, .. } => count, + DescriptorLayout::CombinedImageSampler { count, .. } => count, + DescriptorLayout::SampledImage { count } => count, + DescriptorLayout::StorageImage { count } => count, + DescriptorLayout::UniformTexelBuffer { count } => count, + DescriptorLayout::StorageTexelBuffer { count } => count, + DescriptorLayout::UniformBuffer { count } => count, + DescriptorLayout::StorageBuffer { count } => count, + DescriptorLayout::UniformBufferDynamic { count } => count, + DescriptorLayout::StorageBufferDynamic { count } => count, + DescriptorLayout::InputAttachment { count } => count, + } + } + #[allow(dead_code)] + pub fn immutable_samplers(&self) -> Option<&[SharedHandle]> { + match self { + DescriptorLayout::Sampler { + immutable_samplers: Some(immutable_samplers), + .. + } => Some(immutable_samplers), + DescriptorLayout::CombinedImageSampler { + immutable_samplers: Some(immutable_samplers), + .. + } => Some(immutable_samplers), + _ => None, + } + } + pub fn descriptor_type(&self) -> api::VkDescriptorType { + match self { + DescriptorLayout::Sampler { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLER, + DescriptorLayout::CombinedImageSampler { .. } => { + api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + } + DescriptorLayout::SampledImage { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + DescriptorLayout::StorageImage { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + DescriptorLayout::UniformTexelBuffer { .. } => { + api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + } + DescriptorLayout::StorageTexelBuffer { .. } => { + api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + } + DescriptorLayout::UniformBuffer { .. } => api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + DescriptorLayout::StorageBuffer { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + DescriptorLayout::UniformBufferDynamic { .. } => { + api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + } + DescriptorLayout::StorageBufferDynamic { .. } => { + api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC + } + DescriptorLayout::InputAttachment { .. } => api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + } + } + pub unsafe fn from(v: &api::VkDescriptorSetLayoutBinding) -> Self { + let get_immutable_samplers = || { + if v.pImmutableSamplers.is_null() { + None + } else { + let immutable_samplers = + slice::from_raw_parts(v.pImmutableSamplers, v.descriptorCount as usize); + Some( + immutable_samplers + .iter() + .map(|sampler| SharedHandle::from(*sampler).unwrap()) + .collect(), + ) + } + }; + match v.descriptorType { + api::VK_DESCRIPTOR_TYPE_SAMPLER => DescriptorLayout::Sampler { + count: v.descriptorCount as usize, + immutable_samplers: get_immutable_samplers(), + }, + api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER => { + DescriptorLayout::CombinedImageSampler { + count: v.descriptorCount as usize, + immutable_samplers: get_immutable_samplers(), + } + } + api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE => DescriptorLayout::SampledImage { + count: v.descriptorCount as usize, + }, + api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE => DescriptorLayout::StorageImage { + count: v.descriptorCount as usize, + }, + api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER => DescriptorLayout::UniformTexelBuffer { + count: v.descriptorCount as usize, + }, + api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER => DescriptorLayout::StorageTexelBuffer { + count: v.descriptorCount as usize, + }, + api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER => DescriptorLayout::UniformBuffer { + count: v.descriptorCount as usize, + }, + api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER => DescriptorLayout::StorageBuffer { + count: v.descriptorCount as usize, + }, + api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC => { + DescriptorLayout::UniformBufferDynamic { + count: v.descriptorCount as usize, + } + } + api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => { + DescriptorLayout::StorageBufferDynamic { + count: v.descriptorCount as usize, + } + } + api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT => DescriptorLayout::InputAttachment { + count: v.descriptorCount as usize, + }, + _ => unreachable!("invalid VkDescriptorType: {}", v.descriptorType), + } + } +} + +#[derive(Debug)] +pub struct DescriptorSetLayout { + pub bindings: Vec>, +} + +#[derive(Debug)] +pub struct DescriptorPool { + descriptor_sets: Vec>, +} + +impl DescriptorPool { + pub fn new() -> Self { + Self { + descriptor_sets: Vec::new(), + } + } + pub fn reset(&mut self) { + self.descriptor_sets.clear() + } + pub unsafe fn allocate>( + &mut self, + descriptor_sets: I, + output_descriptor_sets: &mut [api::VkDescriptorSet], + ) { + let start_index = self.descriptor_sets.len(); + self.descriptor_sets + .extend(descriptor_sets.into_iter().map(OwnedHandle::new)); + assert_eq!( + self.descriptor_sets[start_index..].len(), + output_descriptor_sets.len() + ); + for (output_descriptor_set, descriptor_set) in output_descriptor_sets + .iter_mut() + .zip(self.descriptor_sets[start_index..].iter()) + { + *output_descriptor_set = descriptor_set.get_handle(); + } + } + pub unsafe fn free(&mut self, descriptor_sets: &[api::VkDescriptorSet]) { + self.descriptor_sets + .retain(|descriptor_set| !descriptor_sets.contains(&descriptor_set.get_handle())) + } +} + +#[derive(Debug)] +pub struct DescriptorImage(SharedHandle, image::Tiling); + +impl DescriptorImage { + pub unsafe fn from(v: &api::VkDescriptorImageInfo) -> Self { + let image_view = SharedHandle::from(v.imageView).unwrap(); + let tiling = image_view.image.properties.get_tiling(v.imageLayout); + DescriptorImage(image_view, tiling) + } +} + +#[derive(Debug)] +pub struct DescriptorCombinedImageSampler { + image: Option, + sampler: Option>, +} + +#[derive(Debug)] +pub enum Descriptor { + Sampler { + elements: Vec>>, + immutable_samplers: bool, + }, + CombinedImageSampler { + elements: Vec, + immutable_samplers: bool, + }, + SampledImage { + elements: Vec>, + }, + StorageImage { + elements: Vec>, + }, + UniformTexelBuffer { + elements: Vec>>, + }, + StorageTexelBuffer { + elements: Vec>>, + }, + UniformBuffer { + elements: Vec>, + }, + StorageBuffer { + elements: Vec>, + }, + UniformBufferDynamic { + elements: Vec>, + }, + StorageBufferDynamic { + elements: Vec>, + }, + InputAttachment { + elements: Vec>, + }, +} + +#[derive(Copy, Clone)] +pub enum DescriptorWriteArg<'a> { + Image(&'a [api::VkDescriptorImageInfo]), + Buffer(&'a [api::VkDescriptorBufferInfo]), + TexelBuffer(&'a [api::VkBufferView]), +} + +impl<'a> DescriptorWriteArg<'a> { + pub unsafe fn from(v: &'a api::VkWriteDescriptorSet) -> Self { + match v.descriptorType { + api::VK_DESCRIPTOR_TYPE_SAMPLER + | api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + | api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + | api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + | api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT => { + assert!(!v.pImageInfo.is_null()); + DescriptorWriteArg::Image(slice::from_raw_parts( + v.pImageInfo, + v.descriptorCount as usize, + )) + } + api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + | api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER => { + assert!(!v.pTexelBufferView.is_null()); + DescriptorWriteArg::TexelBuffer(slice::from_raw_parts( + v.pTexelBufferView, + v.descriptorCount as usize, + )) + } + api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + | api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + | api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + | api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => { + assert!(!v.pBufferInfo.is_null()); + DescriptorWriteArg::Buffer(slice::from_raw_parts( + v.pBufferInfo, + v.descriptorCount as usize, + )) + } + _ => unreachable!("invalid VkDescriptorType: {}", v.descriptorType), + } + } + pub fn len(self) -> usize { + match self { + DescriptorWriteArg::Image(v) => v.len(), + DescriptorWriteArg::Buffer(v) => v.len(), + DescriptorWriteArg::TexelBuffer(v) => v.len(), + } + } + pub fn slice(self, range: ops::Range) -> Self { + match self { + DescriptorWriteArg::Image(v) => DescriptorWriteArg::Image(&v[range]), + DescriptorWriteArg::Buffer(v) => DescriptorWriteArg::Buffer(&v[range]), + DescriptorWriteArg::TexelBuffer(v) => DescriptorWriteArg::TexelBuffer(&v[range]), + } + } + pub fn slice_from(self, range: ops::RangeFrom) -> Self { + match self { + DescriptorWriteArg::Image(v) => DescriptorWriteArg::Image(&v[range]), + DescriptorWriteArg::Buffer(v) => DescriptorWriteArg::Buffer(&v[range]), + DescriptorWriteArg::TexelBuffer(v) => DescriptorWriteArg::TexelBuffer(&v[range]), + } + } + pub fn slice_to(self, range: ops::RangeTo) -> Self { + match self { + DescriptorWriteArg::Image(v) => DescriptorWriteArg::Image(&v[range]), + DescriptorWriteArg::Buffer(v) => DescriptorWriteArg::Buffer(&v[range]), + DescriptorWriteArg::TexelBuffer(v) => DescriptorWriteArg::TexelBuffer(&v[range]), + } + } + pub fn image(self) -> Option<&'a [api::VkDescriptorImageInfo]> { + match self { + DescriptorWriteArg::Image(v) => Some(v), + _ => None, + } + } + pub fn buffer(self) -> Option<&'a [api::VkDescriptorBufferInfo]> { + match self { + DescriptorWriteArg::Buffer(v) => Some(v), + _ => None, + } + } + pub fn texel_buffer(self) -> Option<&'a [api::VkBufferView]> { + match self { + DescriptorWriteArg::TexelBuffer(v) => Some(v), + _ => None, + } + } +} + +fn descriptor_write_helper( + start_element: usize, + elements: &mut [Element], + args: &[T], + mut f: F, +) { + for (element, arg) in elements[start_element..][..args.len()] + .iter_mut() + .zip(args.iter()) + { + f(element, arg); + } +} + +impl Descriptor { + pub fn element_count(&self) -> usize { + match self { + Descriptor::Sampler { elements, .. } => elements.len(), + Descriptor::CombinedImageSampler { elements, .. } => elements.len(), + Descriptor::SampledImage { elements, .. } => elements.len(), + Descriptor::StorageImage { elements, .. } => elements.len(), + Descriptor::UniformTexelBuffer { elements, .. } => elements.len(), + Descriptor::StorageTexelBuffer { elements, .. } => elements.len(), + Descriptor::UniformBuffer { elements, .. } => elements.len(), + Descriptor::StorageBuffer { elements, .. } => elements.len(), + Descriptor::UniformBufferDynamic { elements, .. } => elements.len(), + Descriptor::StorageBufferDynamic { elements, .. } => elements.len(), + Descriptor::InputAttachment { elements, .. } => elements.len(), + } + } + pub fn from(layout: &DescriptorLayout) -> Self { + match layout { + DescriptorLayout::Sampler { + count, + immutable_samplers, + } => { + let mut elements: Vec<_> = (0..*count).map(|_| None).collect(); + let immutable_samplers = if let Some(immutable_samplers) = immutable_samplers { + assert_eq!(immutable_samplers.len(), *count); + for (element, sampler) in elements.iter_mut().zip(immutable_samplers.iter()) { + *element = Some(sampler.clone()); + } + true + } else { + false + }; + Descriptor::Sampler { + elements, + immutable_samplers, + } + } + DescriptorLayout::CombinedImageSampler { + count, + immutable_samplers, + } => { + let mut elements: Vec<_> = (0..*count) + .map(|_| DescriptorCombinedImageSampler { + image: None, + sampler: None, + }) + .collect(); + let immutable_samplers = if let Some(immutable_samplers) = immutable_samplers { + assert_eq!(immutable_samplers.len(), *count); + for (element, sampler) in elements.iter_mut().zip(immutable_samplers.iter()) { + element.sampler = Some(sampler.clone()); + } + true + } else { + false + }; + Descriptor::CombinedImageSampler { + elements, + immutable_samplers, + } + } + DescriptorLayout::SampledImage { count } => Descriptor::SampledImage { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::StorageImage { count } => Descriptor::StorageImage { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::UniformTexelBuffer { count } => Descriptor::UniformTexelBuffer { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::StorageTexelBuffer { count } => Descriptor::StorageTexelBuffer { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::UniformBuffer { count } => Descriptor::UniformBuffer { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::StorageBuffer { count } => Descriptor::StorageBuffer { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::UniformBufferDynamic { count } => Descriptor::UniformBufferDynamic { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::StorageBufferDynamic { count } => Descriptor::StorageBufferDynamic { + elements: (0..*count).map(|_| None).collect(), + }, + DescriptorLayout::InputAttachment { count } => Descriptor::InputAttachment { + elements: (0..*count).map(|_| None).collect(), + }, + } + } + pub unsafe fn write(&mut self, start_element: usize, arg: DescriptorWriteArg) { + assert_eq!(arg.len() + start_element, self.element_count()); + match self { + Descriptor::Sampler { + elements, + immutable_samplers, + } => descriptor_write_helper( + start_element, + elements, + arg.image().unwrap(), + |_element, _arg| assert!(!*immutable_samplers), + ), + Descriptor::CombinedImageSampler { + elements, + immutable_samplers, + } => descriptor_write_helper( + start_element, + elements, + arg.image().unwrap(), + |element, arg| { + if !*immutable_samplers { + element.sampler = Some(SharedHandle::from(arg.sampler).unwrap()); + } + element.image = Some(DescriptorImage::from(arg)); + }, + ), + Descriptor::SampledImage { elements } => descriptor_write_helper( + start_element, + elements, + arg.image().unwrap(), + |element, arg| { + *element = Some(DescriptorImage::from(arg)); + }, + ), + Descriptor::StorageImage { elements } => descriptor_write_helper( + start_element, + elements, + arg.image().unwrap(), + |element, arg| { + *element = Some(DescriptorImage::from(arg)); + }, + ), + Descriptor::UniformTexelBuffer { elements } => unimplemented!(), + Descriptor::StorageTexelBuffer { elements } => unimplemented!(), + Descriptor::UniformBuffer { elements } => descriptor_write_helper( + start_element, + elements, + arg.buffer().unwrap(), + |element, arg| *element = Some(BufferSlice::from(arg)), + ), + Descriptor::StorageBuffer { elements } => descriptor_write_helper( + start_element, + elements, + arg.buffer().unwrap(), + |element, arg| *element = Some(BufferSlice::from(arg)), + ), + Descriptor::UniformBufferDynamic { elements } => unimplemented!(), + Descriptor::StorageBufferDynamic { elements } => unimplemented!(), + Descriptor::InputAttachment { elements } => descriptor_write_helper( + start_element, + elements, + arg.image().unwrap(), + |element, arg| { + *element = Some(DescriptorImage::from(arg)); + }, + ), + } + } + pub fn descriptor_type(&self) -> api::VkDescriptorType { + match self { + Descriptor::Sampler { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLER, + Descriptor::CombinedImageSampler { .. } => { + api::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + } + Descriptor::SampledImage { .. } => api::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + Descriptor::StorageImage { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + Descriptor::UniformTexelBuffer { .. } => api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + Descriptor::StorageTexelBuffer { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + Descriptor::UniformBuffer { .. } => api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + Descriptor::StorageBuffer { .. } => api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + Descriptor::UniformBufferDynamic { .. } => { + api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + } + Descriptor::StorageBufferDynamic { .. } => { + api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC + } + Descriptor::InputAttachment { .. } => api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + } + } +} + +#[derive(Debug)] +pub struct DescriptorSet { + pub bindings: Vec>, +} diff --git a/vulkan-driver/src/handle.rs b/vulkan-driver/src/handle.rs index 624593c..33b31ad 100644 --- a/vulkan-driver/src/handle.rs +++ b/vulkan-driver/src/handle.rs @@ -2,9 +2,11 @@ // Copyright 2018 Jacob Lifshay use api; use api_impl::{Device, Instance, PhysicalDevice, Queue}; -use buffer::Buffer; +use buffer::{Buffer, BufferView}; +use descriptor_set::{DescriptorPool, DescriptorSet, DescriptorSetLayout}; use device_memory::DeviceMemory; -use image::Image; +use image::{Image, ImageView}; +use render_pass::RenderPass; use sampler::Sampler; use sampler::SamplerYcbcrConversion; use shader_module::ShaderModule; @@ -205,10 +207,15 @@ where } } -#[derive(Copy, Clone)] #[repr(transparent)] pub struct SharedHandle(NonNull); +impl Clone for SharedHandle { + fn clone(&self) -> Self { + SharedHandle(self.0) + } +} + impl SharedHandle { pub unsafe fn from(v: T) -> Option { v.get().map(SharedHandle) @@ -344,14 +351,10 @@ pub type VkQueryPool = NondispatchableHandle; impl HandleAllocFree for VkQueryPool {} -pub struct BufferView {} - pub type VkBufferView = NondispatchableHandle; impl HandleAllocFree for VkBufferView {} -pub struct ImageView {} - pub type VkImageView = NondispatchableHandle; impl HandleAllocFree for VkImageView {} @@ -372,8 +375,6 @@ pub type VkPipelineLayout = NondispatchableHandle; impl HandleAllocFree for VkPipelineLayout {} -pub struct RenderPass {} - pub type VkRenderPass = NondispatchableHandle; impl HandleAllocFree for VkRenderPass {} @@ -384,8 +385,6 @@ pub type VkPipeline = NondispatchableHandle; impl HandleAllocFree for VkPipeline {} -pub struct DescriptorSetLayout {} - pub type VkDescriptorSetLayout = NondispatchableHandle; impl HandleAllocFree for VkDescriptorSetLayout {} @@ -394,14 +393,10 @@ pub type VkSampler = NondispatchableHandle; impl HandleAllocFree for VkSampler {} -pub struct DescriptorPool {} - pub type VkDescriptorPool = NondispatchableHandle; impl HandleAllocFree for VkDescriptorPool {} -pub struct DescriptorSet {} - pub type VkDescriptorSet = NondispatchableHandle; impl HandleAllocFree for VkDescriptorSet {} diff --git a/vulkan-driver/src/image.rs b/vulkan-driver/src/image.rs index c847997..681b526 100644 --- a/vulkan-driver/src/image.rs +++ b/vulkan-driver/src/image.rs @@ -1,13 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright 2018 Jacob Lifshay -#![cfg_attr( - feature = "cargo-clippy", - allow(clippy::unneeded_field_pattern) -)] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::unneeded_field_pattern))] use api; use constants::IMAGE_ALIGNMENT; use device_memory::DeviceMemoryLayout; use handle::SharedHandle; +use std::error; +use std::fmt; #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum SupportedTilings { @@ -46,6 +45,16 @@ pub struct ImageComputedProperties { } impl ImageProperties { + pub fn get_tiling(&self, image_layout: api::VkImageLayout) -> Tiling { + if image_layout == api::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR { + self.swapchain_present_tiling.unwrap() + } else { + match self.supported_tilings { + SupportedTilings::LinearOnly => Tiling::Linear, + SupportedTilings::Any => Tiling::Tiled, + } + } + } pub fn computed_properties(&self) -> ImageComputedProperties { match *self { Self { @@ -90,3 +99,108 @@ pub struct Image { pub properties: ImageProperties, pub memory: Option, } + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum ImageViewType { + Type1D, + Type2D, + Type3D, + Cube, + Array1D, + Array2D, + CubeArray, +} + +impl ImageViewType { + pub fn from(v: api::VkImageViewType) -> Self { + match v { + api::VK_IMAGE_VIEW_TYPE_1D => ImageViewType::Type1D, + api::VK_IMAGE_VIEW_TYPE_2D => ImageViewType::Type2D, + api::VK_IMAGE_VIEW_TYPE_3D => ImageViewType::Type3D, + api::VK_IMAGE_VIEW_TYPE_CUBE => ImageViewType::Cube, + api::VK_IMAGE_VIEW_TYPE_1D_ARRAY => ImageViewType::Array1D, + api::VK_IMAGE_VIEW_TYPE_2D_ARRAY => ImageViewType::Array2D, + api::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY => ImageViewType::CubeArray, + _ => unreachable!(), + } + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum ComponentSwizzle { + Zero, + One, + X, + Y, + Z, + W, +} + +#[derive(Debug)] +pub struct InvalidVkComponentSwizzle; + +impl fmt::Display for InvalidVkComponentSwizzle { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid VkComponentSwizzle") + } +} + +impl error::Error for InvalidVkComponentSwizzle {} + +impl ComponentSwizzle { + pub fn from( + v: api::VkComponentSwizzle, + identity: Self, + ) -> Result { + match v { + api::VK_COMPONENT_SWIZZLE_IDENTITY => Ok(identity), + api::VK_COMPONENT_SWIZZLE_ZERO => Ok(ComponentSwizzle::Zero), + api::VK_COMPONENT_SWIZZLE_ONE => Ok(ComponentSwizzle::One), + api::VK_COMPONENT_SWIZZLE_R => Ok(ComponentSwizzle::X), + api::VK_COMPONENT_SWIZZLE_G => Ok(ComponentSwizzle::Y), + api::VK_COMPONENT_SWIZZLE_B => Ok(ComponentSwizzle::Z), + api::VK_COMPONENT_SWIZZLE_A => Ok(ComponentSwizzle::W), + _ => Err(InvalidVkComponentSwizzle), + } + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct ComponentMapping { + pub x: ComponentSwizzle, + pub y: ComponentSwizzle, + pub z: ComponentSwizzle, + pub w: ComponentSwizzle, +} + +impl ComponentMapping { + pub const IDENTITY: ComponentMapping = ComponentMapping { + x: ComponentSwizzle::X, + y: ComponentSwizzle::Y, + z: ComponentSwizzle::Z, + w: ComponentSwizzle::W, + }; + pub fn from(v: api::VkComponentMapping) -> Result { + Ok(Self { + x: ComponentSwizzle::from(v.r, ComponentSwizzle::X)?, + y: ComponentSwizzle::from(v.g, ComponentSwizzle::Y)?, + z: ComponentSwizzle::from(v.b, ComponentSwizzle::Z)?, + w: ComponentSwizzle::from(v.a, ComponentSwizzle::W)?, + }) + } +} + +impl Default for ComponentMapping { + fn default() -> Self { + Self::IDENTITY + } +} + +#[derive(Debug)] +pub struct ImageView { + pub image: SharedHandle, + pub view_type: ImageViewType, + pub format: api::VkFormat, + pub component_mapping: ComponentMapping, + pub subresource_range: api::VkImageSubresourceRange, +} diff --git a/vulkan-driver/src/lib.rs b/vulkan-driver/src/lib.rs index 0879956..b920b61 100644 --- a/vulkan-driver/src/lib.rs +++ b/vulkan-driver/src/lib.rs @@ -15,9 +15,11 @@ extern crate xcb; mod api; mod api_impl; mod buffer; +mod descriptor_set; mod device_memory; mod handle; mod image; +mod render_pass; mod sampler; mod shader_module; #[cfg(target_os = "linux")] diff --git a/vulkan-driver/src/render_pass.rs b/vulkan-driver/src/render_pass.rs new file mode 100644 index 0000000..779273f --- /dev/null +++ b/vulkan-driver/src/render_pass.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright 2018 Jacob Lifshay + +#[derive(Debug)] +pub struct RenderPass {} diff --git a/vulkan-driver/src/sampler.rs b/vulkan-driver/src/sampler.rs index 58dda14..b9afd21 100644 --- a/vulkan-driver/src/sampler.rs +++ b/vulkan-driver/src/sampler.rs @@ -3,10 +3,12 @@ use api; use handle::SharedHandle; +#[derive(Debug)] pub struct AnisotropySettings { pub max: f32, } +#[derive(Debug)] pub struct Sampler { pub mag_filter: api::VkFilter, pub min_filter: api::VkFilter, @@ -22,4 +24,5 @@ pub struct Sampler { pub sampler_ycbcr_conversion: Option>, } +#[derive(Debug)] pub struct SamplerYcbcrConversion {} -- 2.30.2