From 5dcb74a71c07031154594a45ec2798441a964f91 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 7 Oct 2018 19:33:16 -0700 Subject: [PATCH] added buffer and image memory binding --- vulkan-driver/src/api_impl.rs | 207 +++++++++++++++++++++++++---- vulkan-driver/src/buffer.rs | 8 +- vulkan-driver/src/device_memory.rs | 5 +- vulkan-driver/src/handle.rs | 44 +++++- vulkan-driver/src/image.rs | 74 ++++++++++- vulkan-driver/src/xcb_swapchain.rs | 9 +- 6 files changed, 312 insertions(+), 35 deletions(-) diff --git a/vulkan-driver/src/api_impl.rs b/vulkan-driver/src/api_impl.rs index af883b5..81b610b 100644 --- a/vulkan-driver/src/api_impl.rs +++ b/vulkan-driver/src/api_impl.rs @@ -2,14 +2,15 @@ // Copyright 2018 Jacob Lifshay #![allow(dead_code)] use api; -use buffer::Buffer; +use buffer::{Buffer, BufferMemory}; use constants::*; use device_memory::{ DeviceMemory, DeviceMemoryAllocation, DeviceMemoryHeap, DeviceMemoryHeaps, DeviceMemoryLayout, DeviceMemoryType, DeviceMemoryTypes, }; use enum_map::EnumMap; -use handle::{Handle, OwnedHandle, SharedHandle}; +use handle::{Handle, MutHandle, OwnedHandle, SharedHandle}; +use image::{Image, ImageMemory, ImageMultisampleCount, ImageProperties, SupportedTilings}; use sampler; use sampler::Sampler; use shader_module::ShaderModule; @@ -3759,12 +3760,22 @@ pub unsafe extern "system" fn vkBindBufferMemory( #[allow(non_snake_case)] pub unsafe extern "system" fn vkBindImageMemory( - _device: api::VkDevice, - _image: api::VkImage, - _memory: api::VkDeviceMemory, - _memoryOffset: api::VkDeviceSize, + device: api::VkDevice, + image: api::VkImage, + memory: api::VkDeviceMemory, + memory_offset: api::VkDeviceSize, ) -> api::VkResult { - unimplemented!() + vkBindImageMemory2( + device, + 1, + &api::VkBindImageMemoryInfo { + sType: api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, + pNext: null(), + image, + memory, + memoryOffset: memory_offset, + }, + ) } #[allow(non_snake_case)] @@ -3792,11 +3803,25 @@ pub unsafe extern "system" fn vkGetBufferMemoryRequirements( #[allow(non_snake_case)] pub unsafe extern "system" fn vkGetImageMemoryRequirements( - _device: api::VkDevice, - _image: api::VkImage, - _pMemoryRequirements: *mut api::VkMemoryRequirements, + device: api::VkDevice, + image: api::VkImage, + memory_requirements: *mut api::VkMemoryRequirements, ) { - unimplemented!() + let mut memory_requirements_2 = api::VkMemoryRequirements2 { + sType: api::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + pNext: null_mut(), + memoryRequirements: mem::zeroed(), + }; + vkGetImageMemoryRequirements2( + device, + &api::VkImageMemoryRequirementsInfo2 { + sType: api::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + pNext: null(), + image, + }, + &mut memory_requirements_2, + ); + *memory_requirements = memory_requirements_2.memoryRequirements; } #[allow(non_snake_case)] @@ -4034,20 +4059,54 @@ pub unsafe extern "system" fn vkDestroyBufferView( #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateImage( _device: api::VkDevice, - _pCreateInfo: *const api::VkImageCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pImage: *mut api::VkImage, + create_info: *const api::VkImageCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + image: *mut api::VkImage, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + external_memory_image_create_info: api::VkExternalMemoryImageCreateInfo = api::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + image_swapchain_create_info: api::VkImageSwapchainCreateInfoKHR = api::VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR, + } + let ref create_info = *create_info; + if !external_memory_image_create_info.is_null() { + unimplemented!(); + } + if !image_swapchain_create_info.is_null() { + unimplemented!(); + } + *image = OwnedHandle::::new(Image { + properties: ImageProperties { + supported_tilings: match create_info.tiling { + api::VK_IMAGE_TILING_OPTIMAL => SupportedTilings::Any, + api::VK_IMAGE_TILING_LINEAR => SupportedTilings::LinearOnly, + _ => unreachable!("invalid image tiling"), + }, + format: create_info.format, + extents: create_info.extent, + array_layers: create_info.arrayLayers, + mip_levels: create_info.mipLevels, + multisample_count: match create_info.samples { + api::VK_SAMPLE_COUNT_1_BIT => ImageMultisampleCount::Count1, + api::VK_SAMPLE_COUNT_4_BIT => ImageMultisampleCount::Count4, + _ => unreachable!("invalid sample count"), + }, + swapchain_present_tiling: None, + }, + memory: None, + }) + .take(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyImage( _device: api::VkDevice, - _image: api::VkImage, - _pAllocator: *const api::VkAllocationCallbacks, + image: api::VkImage, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(image); } #[allow(non_snake_case)] @@ -4922,19 +4981,86 @@ pub unsafe extern "system" fn vkCmdExecuteCommands( #[allow(non_snake_case)] pub unsafe extern "system" fn vkBindBufferMemory2( _device: api::VkDevice, - _bindInfoCount: u32, - _pBindInfos: *const api::VkBindBufferMemoryInfo, + bind_info_count: u32, + bind_infos: *const api::VkBindBufferMemoryInfo, ) -> api::VkResult { - unimplemented!() + assert_ne!(bind_info_count, 0); + 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, + root = api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, + device_group_info: api::VkBindBufferMemoryDeviceGroupInfo = api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, + } + if !device_group_info.is_null() { + let ref device_group_info = *device_group_info; + if device_group_info.deviceIndexCount == 0 { + } else { + assert_eq!(device_group_info.deviceIndexCount, 1); + assert_eq!(*device_group_info.pDeviceIndices, 0); + } + } + let ref bind_info = *bind_info; + let mut buffer = MutHandle::from(bind_info.buffer).unwrap(); + let device_memory = SharedHandle::from(bind_info.memory).unwrap(); + let device_memory_size = device_memory.size(); + assert!(bind_info.memoryOffset < device_memory_size as u64); + let offset = bind_info.memoryOffset as usize; + assert!(buffer.size.checked_add(offset).unwrap() <= device_memory_size); + assert_eq!(offset % BUFFER_ALIGNMENT, 0); + buffer.memory = Some(BufferMemory { + device_memory, + offset, + }); + } + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkBindImageMemory2( _device: api::VkDevice, - _bindInfoCount: u32, - _pBindInfos: *const api::VkBindImageMemoryInfo, + bind_info_count: u32, + bind_infos: *const api::VkBindImageMemoryInfo, ) -> api::VkResult { - unimplemented!() + assert_ne!(bind_info_count, 0); + 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, + 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, + plane_info: api::VkBindImagePlaneMemoryInfo = api::VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, + } + if !device_group_info.is_null() { + let ref device_group_info = *device_group_info; + if device_group_info.deviceIndexCount == 0 { + } else { + assert_eq!(device_group_info.deviceIndexCount, 1); + assert_eq!(*device_group_info.pDeviceIndices, 0); + } + } + if !swapchain_info.is_null() { + unimplemented!(); + } + if !plane_info.is_null() { + unimplemented!(); + } + let ref bind_info = *bind_info; + let mut image = MutHandle::from(bind_info.image).unwrap(); + let device_memory = SharedHandle::from(bind_info.memory).unwrap(); + let device_memory_size = device_memory.size(); + let image_memory_layout = image.properties.computed_properties().memory_layout; + assert!(bind_info.memoryOffset < device_memory_size as u64); + let offset = bind_info.memoryOffset as usize; + assert!(image_memory_layout.size.checked_add(offset).unwrap() <= device_memory_size); + assert_eq!(offset % image_memory_layout.alignment, 0); + image.memory = Some(ImageMemory { + device_memory, + offset, + }); + } + api::VK_SUCCESS } #[allow(non_snake_case)] @@ -5003,10 +5129,37 @@ pub unsafe extern "system" fn vkEnumeratePhysicalDeviceGroups( #[allow(non_snake_case)] pub unsafe extern "system" fn vkGetImageMemoryRequirements2( _device: api::VkDevice, - _pInfo: *const api::VkImageMemoryRequirementsInfo2, - _pMemoryRequirements: *mut api::VkMemoryRequirements2, + info: *const api::VkImageMemoryRequirementsInfo2, + memory_requirements: *mut api::VkMemoryRequirements2, ) { - unimplemented!() + parse_next_chain_const!{ + info, + root = api::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + image_plane_memory_requirements_info: api::VkImagePlaneMemoryRequirementsInfo = api::VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, + } + parse_next_chain_mut!{ + memory_requirements, + root = api::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + dedicated_requirements: api::VkMemoryDedicatedRequirements = api::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + } + if !image_plane_memory_requirements_info.is_null() { + unimplemented!(); + } + let ref info = *info; + let image = SharedHandle::from(info.image).unwrap(); + let ref mut memory_requirements = *memory_requirements; + let layout = image.properties.computed_properties().memory_layout; + memory_requirements.memoryRequirements = api::VkMemoryRequirements { + size: layout.size as u64, + alignment: layout.alignment as u64, + memoryTypeBits: DeviceMemoryType::Main.to_bits(), + ..mem::zeroed() // for padding fields + }; + if !dedicated_requirements.is_null() { + let ref mut dedicated_requirements = *dedicated_requirements; + dedicated_requirements.prefersDedicatedAllocation = api::VK_FALSE; + dedicated_requirements.requiresDedicatedAllocation = api::VK_FALSE; + } } #[allow(non_snake_case)] diff --git a/vulkan-driver/src/buffer.rs b/vulkan-driver/src/buffer.rs index 93f2892..9ece100 100644 --- a/vulkan-driver/src/buffer.rs +++ b/vulkan-driver/src/buffer.rs @@ -1,6 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright 2018 Jacob Lifshay -pub struct BufferMemory {} +use api; +use handle::SharedHandle; + +pub struct BufferMemory { + pub device_memory: SharedHandle, + pub offset: usize, +} pub struct Buffer { pub size: usize, diff --git a/vulkan-driver/src/device_memory.rs b/vulkan-driver/src/device_memory.rs index 3100ac1..5565de4 100644 --- a/vulkan-driver/src/device_memory.rs +++ b/vulkan-driver/src/device_memory.rs @@ -170,7 +170,7 @@ impl DeviceMemoryLayout { assert!(required_alignment.is_power_of_two()); assert_ne!(required_size, 0); Self { - size: (required_size + required_alignment - 1) / required_alignment, + size: (required_size + required_alignment - 1) & !(required_alignment - 1), alignment: required_alignment, } } @@ -179,6 +179,9 @@ impl DeviceMemoryLayout { pub trait DeviceMemoryAllocation: 'static + Send + Sync + Debug { unsafe fn get(&self) -> NonNull; fn layout(&self) -> DeviceMemoryLayout; + fn size(&self) -> usize { + self.layout().size + } } #[derive(Debug)] diff --git a/vulkan-driver/src/handle.rs b/vulkan-driver/src/handle.rs index b4a976e..f1220d7 100644 --- a/vulkan-driver/src/handle.rs +++ b/vulkan-driver/src/handle.rs @@ -4,6 +4,7 @@ use api; use api_impl::{Device, Instance, PhysicalDevice, Queue}; use buffer::Buffer; use device_memory::DeviceMemory; +use image::Image; use sampler::Sampler; use sampler::SamplerYcbcrConversion; use shader_module::ShaderModule; @@ -154,6 +155,7 @@ impl Handle for NondispatchableHandle { } } +#[repr(transparent)] pub struct OwnedHandle(NonNull); impl OwnedHandle { @@ -240,6 +242,46 @@ where } } +#[repr(transparent)] +pub struct MutHandle(NonNull); + +impl MutHandle { + pub unsafe fn from(v: T) -> Option { + v.get().map(MutHandle) + } + pub unsafe fn take(self) -> T { + T::new(Some(self.0)) + } + pub unsafe fn get_handle(&self) -> T { + T::new(Some(self.0)) + } + pub fn into_nonnull(self) -> NonNull { + self.0 + } +} + +impl Deref for MutHandle { + type Target = T::Value; + fn deref(&self) -> &T::Value { + unsafe { &*self.0.as_ptr() } + } +} + +impl DerefMut for MutHandle { + fn deref_mut(&mut self) -> &mut T::Value { + unsafe { &mut *self.0.as_ptr() } + } +} + +impl fmt::Debug for MutHandle +where + T::Value: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("MutHandle").field((*self).deref()).finish() + } +} + pub type VkInstance = DispatchableHandle; impl HandleAllocFree for VkInstance {} @@ -282,8 +324,6 @@ pub type VkBuffer = NondispatchableHandle; impl HandleAllocFree for VkBuffer {} -pub struct Image {} - pub type VkImage = NondispatchableHandle; impl HandleAllocFree for VkImage {} diff --git a/vulkan-driver/src/image.rs b/vulkan-driver/src/image.rs index 21c31ae..cc626eb 100644 --- a/vulkan-driver/src/image.rs +++ b/vulkan-driver/src/image.rs @@ -1,15 +1,87 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright 2018 Jacob Lifshay use api; +use constants::IMAGE_ALIGNMENT; +use device_memory::DeviceMemoryLayout; +use handle::SharedHandle; +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum SupportedTilings { Any, LinearOnly, } -pub struct ImageDescriptor { +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum Tiling { + Linear, + Tiled, +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum ImageMultisampleCount { + Count1, + Count4, +} + +#[derive(Copy, Clone, Debug)] +pub struct ImageProperties { pub supported_tilings: SupportedTilings, pub format: api::VkFormat, pub extents: api::VkExtent3D, + pub array_layers: u32, pub mip_levels: u32, + pub multisample_count: ImageMultisampleCount, + pub swapchain_present_tiling: Option, +} + +#[derive(Copy, Clone, Debug)] +pub struct ImageComputedProperties { + pub pixel_size_in_bytes: usize, + pub memory_layout: DeviceMemoryLayout, +} + +impl ImageProperties { + pub fn computed_properties(&self) -> ImageComputedProperties { + match *self { + Self { + supported_tilings: SupportedTilings::Any, + format: api::VK_FORMAT_R8G8B8A8_UNORM, + extents, + array_layers, + mip_levels: 1, + multisample_count: ImageMultisampleCount::Count1, + swapchain_present_tiling: _, + } => { + let pixel_size_in_bytes = 4; + ImageComputedProperties { + pixel_size_in_bytes, + memory_layout: DeviceMemoryLayout::calculate( + pixel_size_in_bytes + .checked_mul(extents.width as usize) + .unwrap() + .checked_mul(extents.height as usize) + .unwrap() + .checked_mul(extents.depth as usize) + .unwrap() + .checked_mul(array_layers as usize) + .unwrap(), + IMAGE_ALIGNMENT, + ), + } + } + _ => unimplemented!("ImageProperties::computed_properties({:?})", self), + } + } +} + +#[derive(Debug)] +pub struct ImageMemory { + pub device_memory: SharedHandle, + pub offset: usize, +} + +#[derive(Debug)] +pub struct Image { + pub properties: ImageProperties, + pub memory: Option, } diff --git a/vulkan-driver/src/xcb_swapchain.rs b/vulkan-driver/src/xcb_swapchain.rs index 982f3d9..38e1ba4 100644 --- a/vulkan-driver/src/xcb_swapchain.rs +++ b/vulkan-driver/src/xcb_swapchain.rs @@ -2,7 +2,7 @@ // Copyright 2018 Jacob Lifshay use api; use handle::Handle; -use image::{ImageDescriptor, SupportedTilings}; +use image::{ImageMultisampleCount, ImageProperties, SupportedTilings, Tiling}; use libc; use std::borrow::Cow; use std::mem; @@ -141,7 +141,7 @@ struct SwapchainSetupFirstStage { image_pixel_size: usize, scanline_alignment: usize, shm_version: Option, - image_descriptor: ImageDescriptor, + image_properties: ImageProperties, } impl SwapchainSetupFirstStage { @@ -317,7 +317,7 @@ impl SwapchainSetupFirstStage { image_pixel_size, scanline_alignment, shm_version, - image_descriptor: ImageDescriptor { + image_properties: ImageProperties { supported_tilings: SupportedTilings::Any, format: api::VK_FORMAT_UNDEFINED, extents: api::VkExtent3D { @@ -325,7 +325,10 @@ impl SwapchainSetupFirstStage { height: image_extent.height, depth: 1, }, + array_layers: 1, mip_levels: 1, + multisample_count: ImageMultisampleCount::Count1, + swapchain_present_tiling: Some(Tiling::Linear), }, }) } -- 2.30.2