added buffer and image memory binding
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 8 Oct 2018 02:33:16 +0000 (19:33 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 8 Oct 2018 02:33:16 +0000 (19:33 -0700)
vulkan-driver/src/api_impl.rs
vulkan-driver/src/buffer.rs
vulkan-driver/src/device_memory.rs
vulkan-driver/src/handle.rs
vulkan-driver/src/image.rs
vulkan-driver/src/xcb_swapchain.rs

index af883b5bf2d84c13ca842fc5f92ee6a522d30b4d..81b610bd09e7add61ceb3a60e89e471d0c449c7e 100644 (file)
@@ -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::<api::VkImage>::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)]
index 93f28929fad6f4412d0824d9b87c1575ae77c018..9ece100210340ab9ce3af78dd597ed4a09920e1b 100644 (file)
@@ -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<api::VkDeviceMemory>,
+    pub offset: usize,
+}
 
 pub struct Buffer {
     pub size: usize,
index 3100ac1ec8b33cc246ed1c00e48f665cc628f450..5565de4bf74845fa11710eec22581a8ba5a0e2dc 100644 (file)
@@ -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<u8>;
     fn layout(&self) -> DeviceMemoryLayout;
+    fn size(&self) -> usize {
+        self.layout().size
+    }
 }
 
 #[derive(Debug)]
index b4a976e57e5d3407f42ba5e420700a580b198b7b..f1220d7add4e68b01bd3794c419f1a313a5c3723 100644 (file)
@@ -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<T> Handle for NondispatchableHandle<T> {
     }
 }
 
+#[repr(transparent)]
 pub struct OwnedHandle<T: HandleAllocFree>(NonNull<T::Value>);
 
 impl<T: HandleAllocFree> OwnedHandle<T> {
@@ -240,6 +242,46 @@ where
     }
 }
 
+#[repr(transparent)]
+pub struct MutHandle<T: Handle>(NonNull<T::Value>);
+
+impl<T: Handle> MutHandle<T> {
+    pub unsafe fn from(v: T) -> Option<Self> {
+        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<T::Value> {
+        self.0
+    }
+}
+
+impl<T: Handle> Deref for MutHandle<T> {
+    type Target = T::Value;
+    fn deref(&self) -> &T::Value {
+        unsafe { &*self.0.as_ptr() }
+    }
+}
+
+impl<T: Handle> DerefMut for MutHandle<T> {
+    fn deref_mut(&mut self) -> &mut T::Value {
+        unsafe { &mut *self.0.as_ptr() }
+    }
+}
+
+impl<T: Handle> fmt::Debug for MutHandle<T>
+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<Instance>;
 
 impl HandleAllocFree for VkInstance {}
@@ -282,8 +324,6 @@ pub type VkBuffer = NondispatchableHandle<Buffer>;
 
 impl HandleAllocFree for VkBuffer {}
 
-pub struct Image {}
-
 pub type VkImage = NondispatchableHandle<Image>;
 
 impl HandleAllocFree for VkImage {}
index 21c31ae0481f62fc1b919cd7e0259cd8d46f3467..cc626eb0942f80b23eca91d7d9e263cf54552db7 100644 (file)
@@ -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<Tiling>,
+}
+
+#[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<api::VkDeviceMemory>,
+    pub offset: usize,
+}
+
+#[derive(Debug)]
+pub struct Image {
+    pub properties: ImageProperties,
+    pub memory: Option<ImageMemory>,
 }
index 982f3d91f287f26eca7f33bd2970a92807d1236c..38e1ba405b7dc1bffd0ad7ff449ea856826c136f 100644 (file)
@@ -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<xcb::ffi::shm::xcb_shm_query_version_cookie_t>,
-    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),
             },
         })
     }