diff --git a/libportability-gfx/src/handle.rs b/libportability-gfx/src/handle.rs index c82d602..d2fa56f 100644 --- a/libportability-gfx/src/handle.rs +++ b/libportability-gfx/src/handle.rs @@ -1,3 +1,4 @@ +use VK_NULL_HANDLE; use std::{fmt, ops}; @@ -13,6 +14,10 @@ impl Handle { pub fn unwrap(self) -> Box { unsafe { Box::from_raw(self.0) } } + + pub fn is_null(&self) -> bool { + self.0 == VK_NULL_HANDLE as *mut T + } } impl Clone for Handle { diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 07dbe3e..bc9a2e7 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -295,14 +295,31 @@ pub extern fn gfxFreeMemory( ) { gpu.device.free_memory(*memory.unwrap()); } -extern "C" { - pub fn vkMapMemory(device: VkDevice, memory: VkDeviceMemory, - offset: VkDeviceSize, size: VkDeviceSize, - flags: VkMemoryMapFlags, - ppData: *mut *mut ::std::os::raw::c_void) -> VkResult; +#[inline] +pub extern fn gfxMapMemory( + gpu: VkDevice, + memory: VkDeviceMemory, + offset: VkDeviceSize, + size: VkDeviceSize, + _flags: VkMemoryMapFlags, + ppData: *mut *mut ::std::os::raw::c_void, +) -> VkResult { + if size == VK_WHOLE_SIZE as VkDeviceSize { + unimplemented!() + } + + unsafe { + *ppData = gpu + .device + .map_memory(&memory, offset..offset+size) + .unwrap() as *mut _; // TODO + } + + VkResult::VK_SUCCESS } -extern "C" { - pub fn vkUnmapMemory(device: VkDevice, memory: VkDeviceMemory); +#[inline] +pub extern fn gfxUnmapMemory(gpu: VkDevice, memory: VkDeviceMemory) { + gpu.device.unmap_memory(&memory); } extern "C" { pub fn vkFlushMappedMemoryRanges(device: VkDevice, memoryRangeCount: u32, @@ -323,10 +340,28 @@ extern "C" { pCommittedMemoryInBytes: *mut VkDeviceSize); } -extern "C" { - pub fn vkBindBufferMemory(device: VkDevice, buffer: VkBuffer, - memory: VkDeviceMemory, - memoryOffset: VkDeviceSize) -> VkResult; +#[inline] +pub extern fn gfxBindBufferMemory( + gpu: VkDevice, + mut buffer: VkBuffer, + memory: VkDeviceMemory, + memoryOffset: VkDeviceSize, +) -> VkResult { + let new_buffer = match *buffer.unwrap() { + Buffer::Buffer(_) => panic!("An Buffer can only be bound once!"), + Buffer::Unbound(unbound) => { + gpu.device.bind_buffer_memory( + &memory, + memoryOffset, + unbound, + ).unwrap() // TODO + } + }; + + // Replace the unbound buffer with an actual buffer under the hood. + *buffer = Buffer::Buffer(new_buffer); + + VkResult::VK_SUCCESS } #[inline] pub extern fn gfxBindImageMemory( @@ -351,10 +386,23 @@ pub extern fn gfxBindImageMemory( VkResult::VK_SUCCESS } -extern "C" { - pub fn vkGetBufferMemoryRequirements(device: VkDevice, buffer: VkBuffer, - pMemoryRequirements: - *mut VkMemoryRequirements); +#[inline] +pub extern fn gfxGetBufferMemoryRequirements( + gpu: VkDevice, + buffer: VkBuffer, + pMemoryRequirements: *mut VkMemoryRequirements, +) { + let req = match *buffer.deref() { + Buffer::Buffer(ref buffer) => unimplemented!(), + Buffer::Unbound(ref buffer) => { + gpu.device.get_buffer_requirements(buffer) + } + }; + + let memory_requirements = unsafe { &mut *pMemoryRequirements }; + memory_requirements.size = req.size; + memory_requirements.alignment = req.alignment; + memory_requirements.memoryTypeBits = req.type_mask as _; } #[inline] pub extern fn gfxGetImageMemoryRequirements( @@ -479,9 +527,18 @@ extern "C" { pAllocator: *const VkAllocationCallbacks, pBuffer: *mut VkBuffer) -> VkResult; } -extern "C" { - pub fn vkDestroyBuffer(device: VkDevice, buffer: VkBuffer, - pAllocator: *const VkAllocationCallbacks); +#[inline] +pub extern fn gfxDestroyBuffer( + gpu: VkDevice, + buffer: VkBuffer, + pAllocator: *const VkAllocationCallbacks, +) { + if !buffer.is_null() { + match *buffer.unwrap() { + Buffer::Buffer(buffer) => gpu.device.destroy_buffer(buffer), + Buffer::Unbound(_) => unimplemented!(), + } + } } extern "C" { pub fn vkCreateBufferView(device: VkDevice, @@ -515,9 +572,18 @@ pub extern fn gfxCreateImage( unsafe { *pImage = Handle::new(Image::Unbound(image)); } VkResult::VK_SUCCESS } -extern "C" { - pub fn vkDestroyImage(device: VkDevice, image: VkImage, - pAllocator: *const VkAllocationCallbacks); +#[inline] +pub extern fn gfxDestroyImage( + gpu: VkDevice, + image: VkImage, + pAllocator: *const VkAllocationCallbacks, +) { + if !image.is_null() { + match *image.unwrap() { + Image::Image(image) => gpu.device.destroy_image(image), + Image::Unbound(_) => unimplemented!(), + } + } } extern "C" { pub fn vkGetImageSubresourceLayout(device: VkDevice, image: VkImage, diff --git a/libportability-gfx/src/lib.rs b/libportability-gfx/src/lib.rs index 0bb0f9b..e45e0e8 100644 --- a/libportability-gfx/src/lib.rs +++ b/libportability-gfx/src/lib.rs @@ -39,6 +39,13 @@ pub enum Image { pub type VkImage = Handle>; pub type VkImageView = Handle<::ImageView>; +pub enum Buffer { + Buffer(B::Buffer), + Unbound(B::UnboundBuffer), +} + +pub type VkBuffer = Handle>; + //NOTE: all *KHR types have to be pure `Handle` things for compatibility with //`VK_DEFINE_NON_DISPATCHABLE_HANDLE` used in `vulkan.h` pub type VkSurfaceKHR = Handle<::Surface>; @@ -514,13 +521,6 @@ pub struct VkFence_T { _unused: [u8; 0], } pub type VkFence = *mut VkFence_T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VkBuffer_T { - _unused: [u8; 0], -} -pub type VkBuffer = *mut VkBuffer_T; - #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct VkEvent_T { diff --git a/libportability/src/lib.rs b/libportability/src/lib.rs index b3e884c..6890f65 100644 --- a/libportability/src/lib.rs +++ b/libportability/src/lib.rs @@ -81,6 +81,15 @@ pub extern fn vkBindImageMemory( gfxBindImageMemory(device, image, memory, memoryOffset) } #[no_mangle] +pub extern fn vkBindBufferMemory( + device: VkDevice, + buffer: VkBuffer, + memory: VkDeviceMemory, + memoryOffset: VkDeviceSize, +) -> VkResult { + gfxBindBufferMemory(device, buffer, memory, memoryOffset) +} +#[no_mangle] pub extern fn vkDestroyDevice( device: VkDevice, pAllocator: *const VkAllocationCallbacks, @@ -261,3 +270,54 @@ pub extern fn vkCreateWin32SurfaceKHR( ) -> VkResult { gfxCreateWin32SurfaceKHR(instance, pCreateInfos, pAllocator, pSurface) } + +#[no_mangle] +pub extern fn vkMapMemory( + device: VkDevice, + memory: VkDeviceMemory, + offset: VkDeviceSize, + size: VkDeviceSize, + flags: VkMemoryMapFlags, + ppData: *mut *mut ::std::os::raw::c_void, +) -> VkResult { + gfxMapMemory( + device, + memory, + offset, + size, + flags, + ppData, + ) +} + +#[no_mangle] +pub extern fn vkUnmapMemory(device: VkDevice, memory: VkDeviceMemory) { + gfxUnmapMemory(device, memory) +} + +#[no_mangle] +pub extern fn vkDestroyImage( + device: VkDevice, + image: VkImage, + pAllocator: *const VkAllocationCallbacks, +) { + gfxDestroyImage(device, image, pAllocator) +} + +#[no_mangle] +pub extern fn vkDestroyBuffer( + device: VkDevice, + buffer: VkBuffer, + pAllocator: *const VkAllocationCallbacks, +) { + gfxDestroyBuffer(device, buffer, pAllocator) +} + +#[no_mangle] +pub extern fn vkGetBufferMemoryRequirements( + device: VkDevice, + buffer: VkBuffer, + pMemoryRequirements: *mut VkMemoryRequirements, +) { + gfxGetBufferMemoryRequirements(device, buffer, pMemoryRequirements) +} diff --git a/native/test.cpp b/native/test.cpp index 6430ddc..2fe8c89 100644 --- a/native/test.cpp +++ b/native/test.cpp @@ -342,6 +342,56 @@ int main() { auto mvp = clip * projection * view * model; + VkBuffer uniform_buf = 0; + + VkBufferCreateInfo buf_info = {}; + buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buf_info.pNext = NULL; + buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + buf_info.size = sizeof(mvp); + buf_info.queueFamilyIndexCount = 0; + buf_info.pQueueFamilyIndices = NULL; + buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buf_info.flags = 0; + res = vkCreateBuffer(device, &buf_info, NULL, &uniform_buf); + printf("\tvkCreateBuffer: res=%d\n", res); + assert(!res); + + VkMemoryRequirements mem_reqs_uniform; + vkGetBufferMemoryRequirements(device, uniform_buf, &mem_reqs_uniform); + + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = NULL; + alloc_info.memoryTypeIndex = 0; + + alloc_info.allocationSize = mem_reqs_uniform.size; + pass = memory_type_from_properties( + memory_properties, + mem_reqs_uniform.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &alloc_info.memoryTypeIndex); + assert(pass && "No mappable, coherent memory"); + + VkDeviceMemory uniform_mem = 0; + res = vkAllocateMemory(device, &alloc_info, NULL, &uniform_mem); + printf("\tvkAllocateMemory: res=%d\n", res); + assert(!res); + + uint8_t *pData; + res = vkMapMemory(device, uniform_mem, 0, mem_reqs_uniform.size, 0, (void **)&pData); + printf("\tvkMapMemory: res=%d\n", res); + assert(!res); + + memcpy(pData, &mvp, sizeof(mvp)); + + vkUnmapMemory(device, uniform_mem); + printf("\tvkUnmapMemory"); + + res = vkBindBufferMemory(device, uniform_buf, uniform_mem, 0); + printf("\tvkBindBufferMemory: res=%d\n", res); + assert(!res); + VkCommandPool cmd_pool = 0; VkCommandPoolCreateInfo cmd_pool_info = {}; cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -370,12 +420,17 @@ int main() { } - // TODO: destroy depth image - - vkFreeMemory(device, depth_memory, NULL); + vkDestroyBuffer(device, uniform_buf, NULL); + printf("\tvkDestroyBuffer\n"); + vkFreeMemory(device, uniform_mem, NULL); printf("\tvkFreeMemory\n"); + vkDestroyImageView(device, depth_view, NULL); printf("\tvkDestroyImageView\n"); + vkDestroyImage(device, depth_image, NULL); + printf("\tvkDestroyImage\n"); + vkFreeMemory(device, depth_memory, NULL); + printf("\tvkFreeMemory\n"); for(auto view : swapchain_views) { vkDestroyImageView(device, view, NULL);