├── .gitignore ├── .gitmodules ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── rustfmt.toml ├── src ├── enums.rs ├── functions.rs ├── lib.rs ├── structs.rs ├── types.rs └── utils.rs └── vk-mem-alloc-sys ├── Cargo.toml ├── README.md ├── build.rs ├── src └── lib.rs └── wrapper └── vk_mem_alloc.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | bin/ 3 | .idea/ 4 | Cargo.lock 5 | gen/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vk-mem-alloc-sys/vendor/VulkanMemoryAllocator"] 2 | path = vk-mem-alloc-sys/vendor/VulkanMemoryAllocator 3 | url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator 4 | [submodule "vk-mem-alloc-sys/vendor/Vulkan-Headers"] 5 | path = vk-mem-alloc-sys/vendor/Vulkan-Headers 6 | url = https://github.com/KhronosGroup/Vulkan-Headers 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vk-mem-alloc" 3 | version = "0.2.0" 4 | edition = "2021" 5 | 6 | authors = [ "Lorenz Klaus ", "Marlon Klaus " ] 7 | description = "A very lightweight wrapper around the Vulkan Memory Allocator" 8 | homepage = "https://github.com/projectkml/vk-mem-alloc-rs" 9 | repository = "https://github.com/projectkml/vk-mem-alloc-rs" 10 | documentation = "https://docs.rs/vk-mem-alloc" 11 | readme = "README.md" 12 | keywords = [ "vulkan", "vk", "ash", "memory", "allocator" ] 13 | categories = [ "api-bindings", "rendering", "rendering::engine", "rendering::graphics-api" ] 14 | license = "MIT/Apache-2.0" 15 | include = [ 16 | "src/*.rs", 17 | "Cargo.toml", 18 | ] 19 | 20 | [dependencies] 21 | ash = "0.38.0+1.3.281" 22 | bitflags = "2.5.0" 23 | libc = "0.2.153" 24 | static_assertions = "1.1.0" 25 | vk-mem-alloc-sys = { path = "vk-mem-alloc-sys" } 26 | 27 | [features] 28 | recording = ["vk-mem-alloc-sys/recording"] 29 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Graham Wihlidal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | # `🌋 vk-mem-alloc-rs` 7 | 8 | **A very lightweight wrapper around the Vulkan Memory Allocator 🦀** 9 | 10 | [![crates][crates-badge]][crates-url] 11 | [![license][license-badge]][license-url] 12 | [![vma][vma-badge]][vma-url] 13 | [![dependency-status][dependency-badge]][dependency-url] 14 | 15 | [crates-badge]: https://img.shields.io/crates/v/vk-mem-alloc.svg 16 | [crates-url]: https://crates.io/crates/vk-mem-alloc 17 | 18 | [license-badge]: https://img.shields.io/badge/License-MIT/Apache_2.0-blue.svg 19 | [license-url]: LICENSE-MIT 20 | 21 | [vma-badge]: https://img.shields.io/badge/Vulkan%20Memory%20Allocator-3.0.1-orange 22 | [vma-url]: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator 23 | 24 | [dependency-badge]: https://deps.rs/repo/github/projectkml/vk-mem-alloc-rs/status.svg 25 | [dependency-url]: https://deps.rs/repo/github/projectkml/vk-mem-alloc-rs 26 | 27 |
28 | 29 | ```TOML 30 | [dependencies] 31 | vk-mem-alloc = "0.2.0" 32 | ``` 33 | 34 | ### Simple Vulkan Memory Allocator example 35 | ```Rust 36 | // Create the allocator 37 | let allocator = vk_mem_alloc::create_allocator(&instance, physical_device, &device, None).unwrap(); 38 | 39 | let buffer_create_info = vk::BufferCreateInfo { 40 | size, 41 | usage: vk::BufferUsageFlags::STORAGE_BUFFER, 42 | ..Default::default() 43 | }; 44 | 45 | let allocation_create_info = vk_mem_alloc::AllocationCreateInfo { 46 | usage: vk_mem_alloc::MemoryUsage::AUTO_PREFER_DEVICE, 47 | ..Default::default() 48 | }; 49 | 50 | // Create the buffer 51 | let (buffer, allocation, allocation_info) = vk_mem_alloc::create_buffer(allocator, &buffer_create_info, &allocation_create_info).unwrap(); 52 | 53 | .... 54 | 55 | // Destroy the buffer 56 | vk_mem_alloc::destroy_buffer(allocator, buffer, allocation); 57 | 58 | // Destroy the allocator 59 | vk_mem_alloc::destroy_allocator(allocator); 60 | ``` 61 | 62 | ### Credits 63 | * [AMD](https://gpuopen.com/vulkan-memory-allocator/) for creating the Vulkan Memory Allocator. 64 | * [The Ash community](https://github.com/ash-rs/ash) for creating such an awesome rust wrapper around Vulkan. 65 | * [Graham Wihlidal](https://github.com/gwihlidal/vk-mem-rs) for creating `vk-mem`, my buildscript is based on its build script. 66 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | force_multiline_blocks = true 3 | format_code_in_doc_comments = true 4 | group_imports = "StdExternalCrate" 5 | imports_granularity = "Crate" 6 | max_width = 187 7 | reorder_imports = true 8 | trailing_comma = "Never" 9 | trailing_semicolon = false 10 | unstable_features = true -------------------------------------------------------------------------------- /src/enums.rs: -------------------------------------------------------------------------------- 1 | use bitflags::bitflags; 2 | 3 | use crate::ffi; 4 | 5 | bitflags! { 6 | #[repr(transparent)] 7 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 8 | pub struct AllocatorCreateFlags : u32 { 9 | const EXTERNALLY_SYNCHRONIZED = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT as _; 10 | const KHR_DEDICATED_ALLOCATION = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT as _; 11 | const KHR_BIND_MEMORY2 = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT as _; 12 | const EXT_MEMORY_BUDGET = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT as _; 13 | const AMD_DEVICE_COHERENT_MEMORY = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT as _; 14 | const BUFFER_DEVICE_ADDRESS = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT as _; 15 | const EXT_MEMORY_PRIORITY = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT as _; 16 | } 17 | } 18 | 19 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 20 | pub struct MemoryUsage(pub u32); 21 | 22 | impl MemoryUsage { 23 | pub const UNKNOWN: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_UNKNOWN as _); 24 | #[deprecated] 25 | pub const GPU_ONLY: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_ONLY as _); 26 | #[deprecated] 27 | pub const CPU_ONLY: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_ONLY as _); 28 | #[deprecated] 29 | pub const CPU_TO_GPU: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_TO_GPU as _); 30 | #[deprecated] 31 | pub const GPU_TO_CPU: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_TO_CPU as _); 32 | #[deprecated] 33 | pub const CPU_COPY: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_ONLY as _); 34 | #[deprecated] 35 | pub const GPU_LAZILY_ALLOCATED: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED as _); 36 | pub const AUTO: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_AUTO as _); 37 | pub const AUTO_PREFER_DEVICE: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE as _); 38 | pub const AUTO_PREFER_HOST: Self = Self(ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_AUTO_PREFER_HOST as _); 39 | } 40 | 41 | bitflags! { 42 | #[repr(transparent)] 43 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 44 | pub struct AllocationCreateFlags : u32 { 45 | const DEDICATED_MEMORY = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT as _; 46 | const NEVER_ALLOCATE = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT as _; 47 | const MAPPED = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_MAPPED_BIT as _; 48 | const USER_DATA_COPY_STRING = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT as _; 49 | const UPPER_ADDRESS = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT as _; 50 | const DONT_BIND = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_DONT_BIND_BIT as _; 51 | const WITHIN_BUDGET = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT as _; 52 | const CAN_ALIAS = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT as _; 53 | const HOST_ACCESS_SEQUENTIAL_WRITE = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT as _; 54 | const HOST_ACCESS_RANDOM = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT as _; 55 | const HOST_ACCESS_ALLOW_TRANSFER_INSTEAD = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT as _; 56 | const STRATEGY_MIN_MEMORY = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as _; 57 | const STRATEGY_MIN_TIME = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as _; 58 | const STRATEGY_MIN_OFFSET = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT as _; 59 | const STRATEGY_BEST_FIT = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT as _; 60 | const STRATEGY_FIRST_FIT = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT as _; 61 | const STRATEGY_MASK = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MASK as _; 62 | } 63 | } 64 | 65 | bitflags! { 66 | #[repr(transparent)] 67 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 68 | pub struct PoolCreateFlags: u32 { 69 | const IGNORE_BUFFER_IMAGE_GRANULARITY = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT as _; 70 | const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT as _; 71 | const ALGORITHM_MASK = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_ALGORITHM_MASK as _; 72 | } 73 | } 74 | 75 | bitflags! { 76 | #[repr(transparent)] 77 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 78 | pub struct DefragmentationFlags: u32 { 79 | const ALGORITHM_FAST = ffi::VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT as _; 80 | const ALGORITHM_BALANCED = ffi::VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT as _; 81 | const ALGORITHM_FULL = ffi::VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT as _; 82 | const ALGORITHM_EXTENSIVE = ffi::VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT as _; 83 | const ALGORITHM_MASK = ffi::VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK as _; 84 | } 85 | } 86 | 87 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 88 | pub struct DefragmentationMoveOperation(i32); 89 | 90 | impl DefragmentationMoveOperation { 91 | pub const COPY: Self = Self(ffi::VmaDefragmentationMoveOperation_VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY as _); 92 | pub const IGNORE: Self = Self(ffi::VmaDefragmentationMoveOperation_VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE as _); 93 | pub const DESTROY: Self = Self(ffi::VmaDefragmentationMoveOperation_VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY as _); 94 | } 95 | 96 | bitflags! { 97 | #[repr(transparent)] 98 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 99 | pub struct VirtualBlockCreateFlags: u32 { 100 | const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT as _; 101 | const ALGORITHM_MASK = ffi::VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK as _; 102 | } 103 | } 104 | 105 | bitflags! { 106 | #[repr(transparent)] 107 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] 108 | pub struct VirtualAllocationCreateFlags: u32 { 109 | const UPPER_ADDRESS = ffi::VmaVirtualAllocationCreateFlagBits_VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT as _; 110 | const STRATEGY_MIN_MEMORY = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as _; 111 | const STRATEGY_MIN_TIME = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as _; 112 | const STRATEGY_MIN_OFFSET = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT as _; 113 | const STRATEGY_MASK = ffi::VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MASK as _; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/functions.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | ffi::{c_char, c_void}, 3 | mem::MaybeUninit, 4 | ptr 5 | }; 6 | 7 | use ash::{prelude::VkResult, vk, Device, Instance}; 8 | 9 | use crate::*; 10 | 11 | #[inline] 12 | fn result_from_ffi(result: vk::Result) -> VkResult<()> { 13 | match result { 14 | vk::Result::SUCCESS => Ok(()), 15 | _ => Err(result) 16 | } 17 | } 18 | 19 | pub unsafe fn create_allocator(instance: &Instance, physical_device: vk::PhysicalDevice, device: &Device, allocator_create_info: Option<&AllocatorCreateInfo>) -> VkResult { 20 | unsafe extern "system" fn get_instance_proc_addr_stub(_instance: vk::Instance, _name: *const c_char) -> vk::PFN_vkVoidFunction { 21 | panic!("VMA_DYNAMIC_VULKAN_FUNCTIONS is unsupported") 22 | } 23 | 24 | unsafe extern "system" fn get_get_device_proc_stub(_device: vk::Device, _name: *const c_char) -> vk::PFN_vkVoidFunction { 25 | panic!("VMA_DYNAMIC_VULKAN_FUNCTIONS is unsupported") 26 | } 27 | 28 | let vulkan_functions = VulkanFunctions { 29 | vk_get_instance_proc_addr: get_instance_proc_addr_stub, 30 | vk_get_device_proc_addr: get_get_device_proc_stub, 31 | vk_get_physical_device_properties: instance.fp_v1_0().get_physical_device_properties, 32 | vk_get_physical_device_memory_properties: instance.fp_v1_0().get_physical_device_memory_properties, 33 | vk_allocate_memory: device.fp_v1_0().allocate_memory, 34 | vk_free_memory: device.fp_v1_0().free_memory, 35 | vk_map_memory: device.fp_v1_0().map_memory, 36 | vk_unmap_memory: device.fp_v1_0().unmap_memory, 37 | vk_flush_mapped_memory_ranges: device.fp_v1_0().flush_mapped_memory_ranges, 38 | vk_invalidate_mapped_memory_ranges: device.fp_v1_0().invalidate_mapped_memory_ranges, 39 | vk_bind_buffer_memory: device.fp_v1_0().bind_buffer_memory, 40 | vk_bind_image_memory: device.fp_v1_0().bind_image_memory, 41 | vk_get_buffer_memory_requirements: device.fp_v1_0().get_buffer_memory_requirements, 42 | vk_get_image_memory_requirements: device.fp_v1_0().get_image_memory_requirements, 43 | vk_create_buffer: device.fp_v1_0().create_buffer, 44 | vk_destroy_buffer: device.fp_v1_0().destroy_buffer, 45 | vk_create_image: device.fp_v1_0().create_image, 46 | vk_destroy_image: device.fp_v1_0().destroy_image, 47 | vk_cmd_copy_buffer: device.fp_v1_0().cmd_copy_buffer, 48 | vk_get_buffer_memory_requirements_2_khr: device.fp_v1_1().get_buffer_memory_requirements2, 49 | vk_get_image_memory_requirements_2_kr: device.fp_v1_1().get_image_memory_requirements2, 50 | vk_bind_buffer_memory_2_khr: device.fp_v1_1().bind_buffer_memory2, 51 | vk_bind_image_memory_2_khr: device.fp_v1_1().bind_image_memory2, 52 | vk_get_physical_device_memory_properties_2_khr: instance.fp_v1_1().get_physical_device_memory_properties2, 53 | vk_get_device_buffer_memory_requirements: device.fp_v1_3().get_device_buffer_memory_requirements, 54 | vk_get_device_image_memory_requirements: device.fp_v1_3().get_device_image_memory_requirements 55 | }; 56 | 57 | let mut allocator_create_info = allocator_create_info 58 | .map(|i| { 59 | assert_eq!(i.instance, vk::Instance::null()); 60 | assert_eq!(i.physical_device, vk::PhysicalDevice::null()); 61 | assert_eq!(i.device, vk::Device::null()); 62 | assert_eq!(i.vulkan_functions, ptr::null()); 63 | *i 64 | }) 65 | .unwrap_or_default(); 66 | allocator_create_info.instance = instance.handle(); 67 | allocator_create_info.physical_device = physical_device; 68 | allocator_create_info.device = device.handle(); 69 | allocator_create_info.vulkan_functions = &vulkan_functions; 70 | 71 | create_allocator_raw(&allocator_create_info) 72 | } 73 | 74 | #[inline] 75 | pub unsafe fn create_allocator_raw(allocator_create_info: &AllocatorCreateInfo) -> VkResult { 76 | let mut allocator = MaybeUninit::uninit(); 77 | result_from_ffi(ffi::vmaCreateAllocator( 78 | allocator_create_info as *const AllocatorCreateInfo as *const _, 79 | &mut allocator as *mut _ as *mut _ 80 | ))?; 81 | Ok(allocator.assume_init()) 82 | } 83 | 84 | #[inline] 85 | pub unsafe fn destroy_allocator(allocator: Allocator) { 86 | ffi::vmaDestroyAllocator(allocator.as_raw() as _); 87 | } 88 | 89 | #[inline] 90 | pub unsafe fn get_allocator_info(allocator: Allocator) -> AllocatorInfo { 91 | let mut allocator_info = MaybeUninit::uninit(); 92 | ffi::vmaGetAllocatorInfo(allocator.as_raw() as _, &mut allocator_info as *mut _ as *mut _); 93 | allocator_info.assume_init() 94 | } 95 | 96 | #[inline] 97 | pub unsafe fn get_physical_device_properties(allocator: Allocator) -> *const vk::PhysicalDeviceProperties { 98 | let mut physical_device_properties = MaybeUninit::uninit(); 99 | ffi::vmaGetPhysicalDeviceProperties(allocator.as_raw() as _, &mut physical_device_properties as *mut _ as *mut _); 100 | physical_device_properties.assume_init() 101 | } 102 | 103 | #[inline] 104 | pub unsafe fn get_memory_properties(allocator: Allocator) -> *const vk::PhysicalDeviceMemoryProperties { 105 | let mut memory_properties = MaybeUninit::uninit(); 106 | ffi::vmaGetMemoryProperties(allocator.as_raw() as _, &mut memory_properties as *mut _ as *mut _); 107 | memory_properties.assume_init() 108 | } 109 | 110 | #[inline] 111 | pub unsafe fn get_memory_type_properties(allocator: Allocator, memory_type_index: u32) -> vk::MemoryPropertyFlags { 112 | let mut memory_property_flags = MaybeUninit::uninit(); 113 | ffi::vmaGetMemoryTypeProperties(allocator.as_raw() as _, memory_type_index, &mut memory_property_flags as *mut _ as *mut _); 114 | memory_property_flags.assume_init() 115 | } 116 | 117 | #[inline] 118 | pub unsafe fn set_current_frame_index(allocator: Allocator, frame_index: u32) { 119 | ffi::vmaSetCurrentFrameIndex(allocator.as_raw() as _, frame_index); 120 | } 121 | 122 | #[inline] 123 | pub unsafe fn calculate_statistics(allocator: Allocator) -> TotalStatistics { 124 | let mut total_statistics = MaybeUninit::uninit(); 125 | ffi::vmaCalculateStatistics(allocator.as_raw() as _, &mut total_statistics as *mut _ as *mut _); 126 | total_statistics.assume_init() 127 | } 128 | 129 | #[inline] 130 | pub unsafe fn get_heap_budgets(allocator: Allocator) -> Vec { 131 | let len = (*get_memory_properties(allocator)).memory_heap_count as _; 132 | 133 | let mut budgets = Vec::with_capacity(len); 134 | ffi::vmaGetHeapBudgets(allocator.as_raw() as _, budgets.as_mut_ptr() as *mut _); 135 | budgets.set_len(len); 136 | 137 | budgets 138 | } 139 | 140 | #[inline] 141 | pub unsafe fn find_memory_type_index(allocator: Allocator, memory_type_bits: u32, allocation_create_info: &AllocationCreateInfo) -> VkResult { 142 | let mut memory_type_index = MaybeUninit::uninit(); 143 | result_from_ffi(ffi::vmaFindMemoryTypeIndex( 144 | allocator.as_raw() as _, 145 | memory_type_bits, 146 | allocation_create_info as *const AllocationCreateInfo as *const _, 147 | &mut memory_type_index as *mut _ as *mut _ 148 | ))?; 149 | Ok(memory_type_index.assume_init()) 150 | } 151 | 152 | #[inline] 153 | pub unsafe fn find_memory_type_index_for_buffer_info(allocator: Allocator, buffer_create_info: &vk::BufferCreateInfo, allocation_create_info: &AllocationCreateInfo) -> VkResult { 154 | let mut memory_type_index = MaybeUninit::uninit(); 155 | result_from_ffi(ffi::vmaFindMemoryTypeIndexForBufferInfo( 156 | allocator.as_raw() as _, 157 | buffer_create_info as *const _, 158 | allocation_create_info as *const AllocationCreateInfo as *const _, 159 | &mut memory_type_index as *mut _ as *mut _ 160 | ))?; 161 | Ok(memory_type_index.assume_init()) 162 | } 163 | 164 | #[inline] 165 | pub unsafe fn find_memory_type_index_for_image_info(allocator: Allocator, image_create_info: &vk::ImageCreateInfo, allocation_create_info: &AllocationCreateInfo) -> VkResult { 166 | let mut memory_type_index = MaybeUninit::uninit(); 167 | result_from_ffi(ffi::vmaFindMemoryTypeIndexForImageInfo( 168 | allocator.as_raw() as _, 169 | image_create_info as *const _, 170 | allocation_create_info as *const AllocationCreateInfo as *const _, 171 | &mut memory_type_index as *mut _ as *mut _ 172 | ))?; 173 | Ok(memory_type_index.assume_init()) 174 | } 175 | 176 | #[inline] 177 | pub unsafe fn create_pool(allocator: Allocator, create_info: &PoolCreateInfo) -> VkResult { 178 | let mut pool = MaybeUninit::uninit(); 179 | result_from_ffi(ffi::vmaCreatePool( 180 | allocator.as_raw() as _, 181 | create_info as *const PoolCreateInfo as *const _, 182 | &mut pool as *mut _ as *mut _ 183 | ))?; 184 | Ok(pool.assume_init()) 185 | } 186 | 187 | #[inline] 188 | pub unsafe fn destroy_pool(allocator: Allocator, pool: Pool) { 189 | ffi::vmaDestroyPool(allocator.as_raw() as _, pool.as_raw() as _); 190 | } 191 | 192 | #[inline] 193 | pub unsafe fn get_pool_statistics(allocator: Allocator, pool: Pool) -> Statistics { 194 | let mut statistics = MaybeUninit::uninit(); 195 | ffi::vmaGetPoolStatistics(allocator.as_raw() as _, pool.as_raw() as _, &mut statistics as *mut _ as *mut _); 196 | statistics.assume_init() 197 | } 198 | 199 | #[inline] 200 | pub unsafe fn calculate_pool_statistics(allocator: Allocator) -> DetailedStatistics { 201 | let mut statistics = MaybeUninit::uninit(); 202 | ffi::vmaCalculateStatistics(allocator.as_raw() as _, &mut statistics as *mut _ as *mut _); 203 | statistics.assume_init() 204 | } 205 | 206 | #[inline] 207 | pub unsafe fn check_pool_corruption(allocator: Allocator, pool: Pool) -> VkResult<()> { 208 | result_from_ffi(ffi::vmaCheckPoolCorruption(allocator.as_raw() as _, pool.as_raw() as _)) 209 | } 210 | 211 | #[inline] 212 | pub unsafe fn get_pool_name(allocator: Allocator, pool: Pool) -> *const c_char { 213 | let mut name = MaybeUninit::uninit(); 214 | ffi::vmaGetPoolName(allocator.as_raw() as _, pool.as_raw() as _, &mut name as *mut _ as *mut _); 215 | name.assume_init() 216 | } 217 | 218 | #[inline] 219 | pub unsafe fn set_pool_name(allocator: Allocator, pool: Pool, name: *const c_char) { 220 | ffi::vmaSetPoolName(allocator.as_raw() as _, pool.as_raw() as _, name); 221 | } 222 | 223 | #[inline] 224 | pub unsafe fn allocate_memory(allocator: Allocator, memory_requirements: &vk::MemoryRequirements, create_info: &AllocationCreateInfo) -> VkResult<(Allocation, AllocationInfo)> { 225 | let mut allocation = MaybeUninit::uninit(); 226 | let mut allocation_info = MaybeUninit::uninit(); 227 | result_from_ffi(ffi::vmaAllocateMemory( 228 | allocator.as_raw() as _, 229 | memory_requirements as *const _ as *const _, 230 | create_info as *const _ as *const _, 231 | &mut allocation as *mut _ as *mut _, 232 | &mut allocation_info as *mut _ as *mut _ 233 | ))?; 234 | Ok((allocation.assume_init(), allocation_info.assume_init())) 235 | } 236 | 237 | #[inline] 238 | pub unsafe fn allocate_memory_pages( 239 | allocator: Allocator, 240 | memory_requirements: &vk::MemoryRequirements, 241 | create_info: &AllocationCreateInfo, 242 | allocation_count: usize 243 | ) -> VkResult<(Allocation, AllocationInfo)> { 244 | let mut allocation = MaybeUninit::uninit(); 245 | let mut allocation_info = MaybeUninit::uninit(); 246 | result_from_ffi(ffi::vmaAllocateMemoryPages( 247 | allocator.as_raw() as _, 248 | memory_requirements as *const _ as *const _, 249 | create_info as *const _ as *const _, 250 | allocation_count, 251 | &mut allocation as *mut _ as *mut _, 252 | &mut allocation_info as *mut _ as *mut _ 253 | ))?; 254 | Ok((allocation.assume_init(), allocation_info.assume_init())) 255 | } 256 | 257 | #[inline] 258 | pub unsafe fn allocate_memory_for_buffer(allocator: Allocator, buffer: vk::Buffer, create_info: *const AllocationCreateInfo) -> VkResult<(Allocation, AllocationInfo)> { 259 | let mut allocation = MaybeUninit::uninit(); 260 | let mut allocation_info = MaybeUninit::uninit(); 261 | result_from_ffi(ffi::vmaAllocateMemoryForBuffer( 262 | allocator.as_raw() as _, 263 | buffer, 264 | create_info as *const _ as *const _, 265 | &mut allocation as *mut _ as *mut _, 266 | &mut allocation_info as *mut _ as *mut _ 267 | ))?; 268 | Ok((allocation.assume_init(), allocation_info.assume_init())) 269 | } 270 | 271 | #[inline] 272 | pub unsafe fn allocate_memory_for_image(allocator: Allocator, image: vk::Image, create_info: *const AllocationCreateInfo) -> VkResult<(Allocation, AllocationInfo)> { 273 | let mut allocation = MaybeUninit::uninit(); 274 | let mut allocation_info = MaybeUninit::uninit(); 275 | result_from_ffi(ffi::vmaAllocateMemoryForImage( 276 | allocator.as_raw() as _, 277 | image, 278 | create_info as *const _ as *const _, 279 | &mut allocation as *mut _ as *mut _, 280 | &mut allocation_info as *mut _ as *mut _ 281 | ))?; 282 | Ok((allocation.assume_init(), allocation_info.assume_init())) 283 | } 284 | 285 | #[inline] 286 | pub unsafe fn free_memory_pages(allocator: Allocator, allocation_count: usize, allocations: *mut Allocation) { 287 | ffi::vmaFreeMemoryPages(allocator.as_raw() as _, allocation_count, allocations.cast()); 288 | } 289 | 290 | #[inline] 291 | pub unsafe fn get_allocation_info(allocator: Allocator, allocation: Allocation) -> AllocationInfo { 292 | let mut allocation_info = MaybeUninit::uninit(); 293 | ffi::vmaGetAllocationInfo(allocator.as_raw() as _, allocation.as_raw() as _, &mut allocation_info as *mut _ as *mut _); 294 | allocation_info.assume_init() 295 | } 296 | 297 | #[inline] 298 | pub unsafe fn set_allocation_user_data(allocator: Allocator, allocation: Allocation, user_data: *mut c_void) { 299 | ffi::vmaSetAllocationUserData(allocator.as_raw() as _, allocation.as_raw() as _, user_data); 300 | } 301 | 302 | #[inline] 303 | pub unsafe fn set_allocation_name(allocator: Allocator, allocation: Allocation, name: *const c_char) { 304 | ffi::vmaSetAllocationName(allocator.as_raw() as _, allocation.as_raw() as _, name); 305 | } 306 | 307 | #[inline] 308 | pub unsafe fn get_allocation_memory_properties(allocator: Allocator, allocation: Allocation) -> vk::MemoryPropertyFlags { 309 | let mut memory_property_flags = MaybeUninit::uninit(); 310 | ffi::vmaGetAllocationMemoryProperties(allocator.as_raw() as _, allocation.as_raw() as _, &mut memory_property_flags as *mut _ as *mut _); 311 | memory_property_flags.assume_init() 312 | } 313 | 314 | #[inline] 315 | pub unsafe fn map_memory(allocator: Allocator, allocation: Allocation) -> VkResult<*mut c_void> { 316 | let mut data = MaybeUninit::uninit(); 317 | result_from_ffi(ffi::vmaMapMemory(allocator.as_raw() as _, allocation.as_raw() as _, &mut data as *mut _ as *mut _))?; 318 | Ok(data.assume_init()) 319 | } 320 | 321 | #[inline] 322 | pub unsafe fn unmap_memory(allocator: Allocator, allocation: Allocation) { 323 | ffi::vmaUnmapMemory(allocator.as_raw() as _, allocation.as_raw() as _); 324 | } 325 | 326 | #[inline] 327 | pub unsafe fn flush_allocation(allocator: Allocator, allocation: Allocation, offset: vk::DeviceSize, size: vk::DeviceSize) -> VkResult<()> { 328 | result_from_ffi(ffi::vmaFlushAllocation(allocator.as_raw() as _, allocation.as_raw() as _, offset, size)) 329 | } 330 | 331 | #[inline] 332 | pub unsafe fn invalidate_allocation(allocator: Allocator, allocation: Allocation, offset: vk::DeviceSize, size: vk::DeviceSize) -> VkResult<()> { 333 | result_from_ffi(ffi::vmaInvalidateAllocation(allocator.as_raw() as _, allocation.as_raw() as _, offset, size)) 334 | } 335 | 336 | #[inline] 337 | pub unsafe fn flush_allocations(allocator: Allocator, allocation_count: u32, allocations: *mut Allocation, offsets: *const vk::DeviceSize, sizes: *const vk::DeviceSize) -> VkResult<()> { 338 | result_from_ffi(ffi::vmaFlushAllocations(allocator.as_raw() as _, allocation_count, allocations.cast(), offsets, sizes)) 339 | } 340 | 341 | #[inline] 342 | pub unsafe fn invalidate_allocations( 343 | allocator: Allocator, 344 | allocation_count: u32, 345 | allocations: *mut Allocation, 346 | offsets: *const vk::DeviceSize, 347 | sizes: *const vk::DeviceSize 348 | ) -> VkResult<()> { 349 | result_from_ffi(ffi::vmaInvalidateAllocations(allocator.as_raw() as _, allocation_count, allocations.cast(), offsets, sizes)) 350 | } 351 | 352 | #[inline] 353 | pub unsafe fn check_corruption(allocator: Allocator, memory_type_bits: u32) -> VkResult<()> { 354 | result_from_ffi(ffi::vmaCheckCorruption(allocator.as_raw() as _, memory_type_bits)) 355 | } 356 | 357 | #[inline] 358 | pub unsafe fn begin_defragmentation(allocator: Allocator, info: &DefragmentationInfo) -> VkResult { 359 | let mut defragmentation_context = MaybeUninit::uninit(); 360 | result_from_ffi(ffi::vmaBeginDefragmentation( 361 | allocator.as_raw() as _, 362 | info as *const _ as *const _, 363 | &mut defragmentation_context as *mut _ as *mut _ 364 | ))?; 365 | Ok(defragmentation_context.assume_init()) 366 | } 367 | 368 | #[inline] 369 | pub unsafe fn end_defragmentation(allocator: Allocator, context: DefragmentationContext) -> DefragmentationStats { 370 | let mut defragmentation_stats = MaybeUninit::uninit(); 371 | ffi::vmaEndDefragmentation(allocator.as_raw() as _, context.as_raw() as _, &mut defragmentation_stats as *mut _ as *mut _); 372 | defragmentation_stats.assume_init() 373 | } 374 | 375 | #[inline] 376 | pub unsafe fn begin_defragmentation_pass(allocator: Allocator, context: DefragmentationContext) -> VkResult { 377 | let mut defragmentation_pass_move_info = MaybeUninit::uninit(); 378 | result_from_ffi(ffi::vmaBeginDefragmentationPass( 379 | allocator.as_raw() as _, 380 | context.as_raw() as _, 381 | &mut defragmentation_pass_move_info as *mut _ as *mut _ 382 | ))?; 383 | Ok(defragmentation_pass_move_info.assume_init()) 384 | } 385 | 386 | #[inline] 387 | pub unsafe fn end_defragmentation_pass(allocator: Allocator, context: DefragmentationContext) -> VkResult { 388 | let mut defragmentation_pass_move_info = MaybeUninit::uninit(); 389 | result_from_ffi(ffi::vmaEndDefragmentationPass( 390 | allocator.as_raw() as _, 391 | context.as_raw() as _, 392 | &mut defragmentation_pass_move_info as *mut _ as *mut _ 393 | ))?; 394 | Ok(defragmentation_pass_move_info.assume_init()) 395 | } 396 | 397 | #[inline] 398 | pub unsafe fn bind_buffer_memory(allocator: Allocator, allocation: Allocation, buffer: vk::Buffer) -> VkResult<()> { 399 | result_from_ffi(ffi::vmaBindBufferMemory(allocator.as_raw() as _, allocation.as_raw() as _, buffer)) 400 | } 401 | 402 | #[inline] 403 | pub unsafe fn bind_buffer_memory2(allocator: Allocator, allocation: Allocation, allocation_local_offset: vk::DeviceSize, buffer: vk::Buffer, next: *const c_void) -> VkResult<()> { 404 | result_from_ffi(ffi::vmaBindBufferMemory2( 405 | allocator.as_raw() as _, 406 | allocation.as_raw() as _, 407 | allocation_local_offset, 408 | buffer, 409 | next 410 | )) 411 | } 412 | 413 | #[inline] 414 | pub unsafe fn bind_image_memory(allocator: Allocator, allocation: Allocation, image: vk::Image) -> VkResult<()> { 415 | result_from_ffi(ffi::vmaBindImageMemory(allocator.as_raw() as _, allocation.as_raw() as _, image)) 416 | } 417 | 418 | #[inline] 419 | pub unsafe fn bind_image_memory2(allocator: Allocator, allocation: Allocation, allocation_local_offset: vk::DeviceSize, image: vk::Image, next: *const c_void) -> VkResult<()> { 420 | result_from_ffi(ffi::vmaBindImageMemory2(allocator.as_raw() as _, allocation.as_raw() as _, allocation_local_offset, image, next)) 421 | } 422 | 423 | #[inline] 424 | pub unsafe fn create_buffer( 425 | allocator: Allocator, 426 | buffer_create_info: &vk::BufferCreateInfo, 427 | allocation_create_info: &AllocationCreateInfo 428 | ) -> VkResult<(vk::Buffer, Allocation, AllocationInfo)> { 429 | let mut buffer = MaybeUninit::uninit(); 430 | let mut allocation = MaybeUninit::uninit(); 431 | let mut allocation_info = MaybeUninit::uninit(); 432 | result_from_ffi(ffi::vmaCreateBuffer( 433 | allocator.as_raw() as _, 434 | buffer_create_info as *const _, 435 | allocation_create_info as *const _ as *const _, 436 | &mut buffer as *mut _ as *mut _, 437 | &mut allocation as *mut _ as *mut _, 438 | &mut allocation_info as *mut _ as *mut _ 439 | ))?; 440 | Ok((buffer.assume_init(), allocation.assume_init(), allocation_info.assume_init())) 441 | } 442 | 443 | #[inline] 444 | pub unsafe fn create_buffer_with_alignment( 445 | allocator: Allocator, 446 | buffer_create_info: &vk::BufferCreateInfo, 447 | allocation_create_info: &AllocationCreateInfo, 448 | min_alignment: vk::DeviceSize 449 | ) -> VkResult<(vk::Buffer, Allocation, AllocationInfo)> { 450 | let mut buffer = MaybeUninit::uninit(); 451 | let mut allocation = MaybeUninit::uninit(); 452 | let mut allocation_info = MaybeUninit::uninit(); 453 | result_from_ffi(ffi::vmaCreateBufferWithAlignment( 454 | allocator.as_raw() as _, 455 | buffer_create_info as *const _, 456 | allocation_create_info as *const AllocationCreateInfo as *const _, 457 | min_alignment, 458 | &mut buffer as *mut _ as *mut _, 459 | &mut allocation as *mut _ as *mut _, 460 | &mut allocation_info as *mut _ as *mut _ 461 | ))?; 462 | Ok((buffer.assume_init(), allocation.assume_init(), allocation_info.assume_init())) 463 | } 464 | 465 | #[inline] 466 | pub unsafe fn create_aliasing_buffer(allocator: Allocator, allocation: Allocation, buffer_create_info: &vk::BufferCreateInfo) -> VkResult { 467 | let mut buffer = MaybeUninit::uninit(); 468 | result_from_ffi(ffi::vmaCreateAliasingBuffer( 469 | allocator.as_raw() as _, 470 | allocation.as_raw() as _, 471 | buffer_create_info as *const _, 472 | &mut buffer as *mut _ as *mut _ 473 | ))?; 474 | Ok(buffer.assume_init()) 475 | } 476 | 477 | #[inline] 478 | pub unsafe fn destroy_buffer(allocator: Allocator, buffer: vk::Buffer, allocation: Allocation) { 479 | ffi::vmaDestroyBuffer(allocator.as_raw() as _, buffer, allocation.as_raw() as _); 480 | } 481 | 482 | #[inline] 483 | pub unsafe fn create_image( 484 | allocator: Allocator, 485 | image_create_info: &vk::ImageCreateInfo, 486 | allocation_create_info: &AllocationCreateInfo 487 | ) -> VkResult<(vk::Image, Allocation, AllocationInfo)> { 488 | let mut image = MaybeUninit::uninit(); 489 | let mut allocation = MaybeUninit::uninit(); 490 | let mut allocation_info = MaybeUninit::uninit(); 491 | result_from_ffi(ffi::vmaCreateImage( 492 | allocator.as_raw() as _, 493 | image_create_info as *const _, 494 | allocation_create_info as *const AllocationCreateInfo as *const _, 495 | &mut image as *mut _ as *mut _, 496 | &mut allocation as *mut _ as *mut _, 497 | &mut allocation_info as *mut _ as *mut _ 498 | ))?; 499 | Ok((image.assume_init(), allocation.assume_init(), allocation_info.assume_init())) 500 | } 501 | 502 | #[inline] 503 | pub unsafe fn create_aliasing_image(allocator: Allocator, allocation: Allocation, image_create_info: &vk::ImageCreateInfo) -> VkResult { 504 | let mut image = MaybeUninit::uninit(); 505 | result_from_ffi(ffi::vmaCreateAliasingImage( 506 | allocator.as_raw() as _, 507 | allocation.as_raw() as _, 508 | image_create_info as *const _, 509 | &mut image as *mut _ as *mut _ 510 | ))?; 511 | Ok(image.assume_init()) 512 | } 513 | 514 | #[inline] 515 | pub unsafe fn destroy_image(allocator: Allocator, image: vk::Image, allocation: Allocation) { 516 | ffi::vmaDestroyImage(allocator.as_raw() as _, image, allocation.as_raw() as _); 517 | } 518 | 519 | #[inline] 520 | pub unsafe fn create_virtual_block(create_info: &VirtualBlockCreateInfo) -> VkResult { 521 | let mut virtual_block = MaybeUninit::uninit(); 522 | result_from_ffi(ffi::vmaCreateVirtualBlock(create_info as *const _ as *const _, &mut virtual_block as *mut _ as *mut _))?; 523 | Ok(virtual_block.assume_init()) 524 | } 525 | 526 | #[inline] 527 | pub unsafe fn destroy_virtual_block(virtual_block: VirtualBlock) { 528 | ffi::vmaDestroyVirtualBlock(virtual_block.as_raw() as _); 529 | } 530 | 531 | #[inline] 532 | pub unsafe fn is_virtual_block_empty(virtual_block: VirtualBlock) -> bool { 533 | ffi::vmaIsVirtualBlockEmpty(virtual_block.as_raw() as _) != 0 534 | } 535 | 536 | #[inline] 537 | pub unsafe fn get_virtual_allocation_info(virtual_block: VirtualBlock, allocation: VirtualAllocation) -> VirtualAllocationInfo { 538 | let mut virtual_alloc_info = MaybeUninit::uninit(); 539 | ffi::vmaGetVirtualAllocationInfo(virtual_block.as_raw() as _, allocation.as_raw() as _, &mut virtual_alloc_info as *mut _ as *mut _); 540 | virtual_alloc_info.assume_init() 541 | } 542 | 543 | #[inline] 544 | pub unsafe fn virtual_allocate(virtual_block: VirtualBlock, create_info: &VirtualAllocationCreateInfo) -> VkResult<(VirtualAllocation, vk::DeviceSize)> { 545 | let mut allocation = MaybeUninit::uninit(); 546 | let mut offset = 0; 547 | result_from_ffi(ffi::vmaVirtualAllocate( 548 | virtual_block.as_raw() as _, 549 | create_info as *const _ as *const _, 550 | &mut allocation as *mut _ as *mut _, 551 | &mut offset 552 | ))?; 553 | Ok((allocation.assume_init(), offset)) 554 | } 555 | 556 | #[inline] 557 | pub unsafe fn virtual_free(virtual_block: VirtualBlock, allocation: VirtualAllocation) { 558 | ffi::vmaVirtualFree(virtual_block.as_raw() as _, allocation.as_raw() as _); 559 | } 560 | 561 | #[inline] 562 | pub unsafe fn clear_virtual_block(virtual_block: VirtualBlock) { 563 | ffi::vmaClearVirtualBlock(virtual_block.as_raw() as _); 564 | } 565 | 566 | #[inline] 567 | pub unsafe fn set_virtual_allocation_user_data(virtual_block: VirtualBlock, allocation: VirtualAllocation, user_data: *mut c_void) { 568 | ffi::vmaSetVirtualAllocationUserData(virtual_block.as_raw() as _, allocation.as_raw() as _, user_data); 569 | } 570 | 571 | #[inline] 572 | pub unsafe fn get_virtual_block_statistics(virtual_block: VirtualBlock) -> Statistics { 573 | let mut statistics = MaybeUninit::uninit(); 574 | ffi::vmaGetVirtualBlockStatistics(virtual_block.as_raw() as _, &mut statistics as *mut _ as *mut _); 575 | statistics.assume_init() 576 | } 577 | 578 | #[inline] 579 | pub unsafe fn calculate_virtual_block_statistics(virtual_block: VirtualBlock) -> DetailedStatistics { 580 | let mut statistics = MaybeUninit::uninit(); 581 | ffi::vmaCalculateVirtualBlockStatistics(virtual_block.as_raw() as _, &mut statistics as *mut _ as *mut _); 582 | statistics.assume_init() 583 | } 584 | 585 | #[inline] 586 | pub unsafe fn build_virtual_block_stats_string(virtual_block: VirtualBlock, detailed_map: bool) -> *mut c_char { 587 | let mut stats_string = MaybeUninit::uninit(); 588 | ffi::vmaBuildVirtualBlockStatsString(virtual_block.as_raw() as _, &mut stats_string as *mut _ as *mut _, detailed_map as _); 589 | stats_string.assume_init() 590 | } 591 | 592 | #[inline] 593 | pub unsafe fn free_virtual_block_stats_string(virtual_block: VirtualBlock, stats_string: *mut c_char) { 594 | ffi::vmaFreeVirtualBlockStatsString(virtual_block.as_raw() as _, stats_string); 595 | } 596 | 597 | #[inline] 598 | pub unsafe fn build_stats_string(allocator: Allocator, detailed_map: bool) -> *mut c_char { 599 | let mut stats_string = MaybeUninit::uninit(); 600 | ffi::vmaBuildStatsString(allocator.as_raw() as _, &mut stats_string as *mut _ as *mut _, detailed_map as _); 601 | stats_string.assume_init() 602 | } 603 | 604 | #[inline] 605 | pub unsafe fn free_stats_string(allocator: Allocator, stats_string: *mut c_char) { 606 | ffi::vmaFreeStatsString(allocator.as_raw() as _, stats_string); 607 | } 608 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::missing_safety_doc)] 2 | 3 | mod ffi { 4 | pub(crate) use vk_mem_alloc_sys::*; 5 | } 6 | 7 | mod enums; 8 | mod functions; 9 | mod structs; 10 | mod types; 11 | mod utils; 12 | 13 | pub use enums::*; 14 | pub use functions::*; 15 | pub use structs::*; 16 | pub use types::*; 17 | -------------------------------------------------------------------------------- /src/structs.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | ffi::{c_char, c_void}, 3 | mem 4 | }; 5 | 6 | use ash::vk; 7 | 8 | use crate::{utils::assert_size_and_align, *}; 9 | 10 | #[repr(C)] 11 | #[derive(Copy, Clone, Debug)] 12 | pub struct DeviceMemoryCallbacks { 13 | pub pfn_allocate: PfnAllocateDeviceMemoryFunction, 14 | pub pfn_free: PfnFreeDeviceMemoryFunction, 15 | pub user_data: *mut c_void 16 | } 17 | 18 | assert_size_and_align!(DeviceMemoryCallbacks, ffi::VmaDeviceMemoryCallbacks); 19 | 20 | impl Default for DeviceMemoryCallbacks { 21 | #[inline] 22 | fn default() -> Self { 23 | unsafe { mem::zeroed() } 24 | } 25 | } 26 | 27 | #[repr(C)] 28 | #[derive(Copy, Clone)] 29 | pub struct VulkanFunctions { 30 | pub vk_get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr, 31 | pub vk_get_device_proc_addr: vk::PFN_vkGetDeviceProcAddr, 32 | pub vk_get_physical_device_properties: vk::PFN_vkGetPhysicalDeviceProperties, 33 | pub vk_get_physical_device_memory_properties: vk::PFN_vkGetPhysicalDeviceMemoryProperties, 34 | pub vk_allocate_memory: vk::PFN_vkAllocateMemory, 35 | pub vk_free_memory: vk::PFN_vkFreeMemory, 36 | pub vk_map_memory: vk::PFN_vkMapMemory, 37 | pub vk_unmap_memory: vk::PFN_vkUnmapMemory, 38 | pub vk_flush_mapped_memory_ranges: vk::PFN_vkFlushMappedMemoryRanges, 39 | pub vk_invalidate_mapped_memory_ranges: vk::PFN_vkInvalidateMappedMemoryRanges, 40 | pub vk_bind_buffer_memory: vk::PFN_vkBindBufferMemory, 41 | pub vk_bind_image_memory: vk::PFN_vkBindImageMemory, 42 | pub vk_get_buffer_memory_requirements: vk::PFN_vkGetBufferMemoryRequirements, 43 | pub vk_get_image_memory_requirements: vk::PFN_vkGetImageMemoryRequirements, 44 | pub vk_create_buffer: vk::PFN_vkCreateBuffer, 45 | pub vk_destroy_buffer: vk::PFN_vkDestroyBuffer, 46 | pub vk_create_image: vk::PFN_vkCreateImage, 47 | pub vk_destroy_image: vk::PFN_vkDestroyImage, 48 | pub vk_cmd_copy_buffer: vk::PFN_vkCmdCopyBuffer, 49 | pub vk_get_buffer_memory_requirements_2_khr: vk::PFN_vkGetBufferMemoryRequirements2, 50 | pub vk_get_image_memory_requirements_2_kr: vk::PFN_vkGetImageMemoryRequirements2, 51 | pub vk_bind_buffer_memory_2_khr: vk::PFN_vkBindBufferMemory2, 52 | pub vk_bind_image_memory_2_khr: vk::PFN_vkBindImageMemory2, 53 | pub vk_get_physical_device_memory_properties_2_khr: vk::PFN_vkGetPhysicalDeviceMemoryProperties2, 54 | pub vk_get_device_buffer_memory_requirements: vk::PFN_vkGetDeviceBufferMemoryRequirements, 55 | pub vk_get_device_image_memory_requirements: vk::PFN_vkGetDeviceImageMemoryRequirements 56 | } 57 | 58 | assert_size_and_align!(VulkanFunctions, ffi::VmaVulkanFunctions); 59 | 60 | #[repr(C)] 61 | #[derive(Copy, Clone)] 62 | pub struct AllocatorCreateInfo<'a> { 63 | pub flags: AllocatorCreateFlags, 64 | pub physical_device: vk::PhysicalDevice, 65 | pub device: vk::Device, 66 | pub preferred_large_heap_block_size: vk::DeviceSize, 67 | pub allocation_callbacks: *const vk::AllocationCallbacks<'a>, 68 | pub device_memory_callbacks: *const DeviceMemoryCallbacks, 69 | pub heap_size_limit: *const vk::DeviceSize, 70 | pub vulkan_functions: *const VulkanFunctions, 71 | pub instance: vk::Instance, 72 | pub vulkan_api_version: u32, 73 | pub type_external_memory_handle_types: *const vk::ExternalMemoryHandleTypeFlagsKHR 74 | } 75 | 76 | impl<'a> Default for AllocatorCreateInfo<'a> { 77 | #[inline] 78 | fn default() -> Self { 79 | unsafe { mem::zeroed() } 80 | } 81 | } 82 | 83 | assert_size_and_align!(AllocatorCreateInfo, ffi::VmaAllocatorCreateInfo); 84 | 85 | #[repr(C)] 86 | #[derive(Copy, Clone, Debug, Default)] 87 | pub struct AllocatorInfo { 88 | pub instance: vk::Instance, 89 | pub physical_device: vk::PhysicalDevice, 90 | pub device: vk::Device 91 | } 92 | 93 | assert_size_and_align!(AllocatorInfo, ffi::VmaAllocatorInfo); 94 | 95 | #[repr(C)] 96 | #[derive(Copy, Clone, Debug, Default)] 97 | pub struct Statistics { 98 | pub block_count: u32, 99 | pub allocation_count: u32, 100 | pub block_bytes: vk::DeviceSize, 101 | pub allocation_bytes: vk::DeviceSize 102 | } 103 | 104 | assert_size_and_align!(Statistics, ffi::VmaStatistics); 105 | 106 | #[repr(C)] 107 | #[derive(Copy, Clone, Debug, Default)] 108 | pub struct DetailedStatistics { 109 | pub statistics: Statistics, 110 | pub unused_range_count: u32, 111 | pub allocation_size_min: vk::DeviceSize, 112 | pub allocation_size_max: vk::DeviceSize, 113 | pub unused_range_size_min: vk::DeviceSize, 114 | pub unused_range_size_max: vk::DeviceSize 115 | } 116 | 117 | assert_size_and_align!(DetailedStatistics, ffi::VmaDetailedStatistics); 118 | 119 | #[repr(C)] 120 | #[derive(Copy, Clone, Debug, Default)] 121 | pub struct TotalStatistics { 122 | pub memory_type: [DetailedStatistics; vk::MAX_MEMORY_TYPES], 123 | pub memory_heap: [DetailedStatistics; vk::MAX_MEMORY_HEAPS], 124 | pub total: DetailedStatistics 125 | } 126 | 127 | assert_size_and_align!(TotalStatistics, ffi::VmaTotalStatistics); 128 | 129 | #[repr(C)] 130 | #[derive(Copy, Clone, Debug, Default)] 131 | pub struct Budget { 132 | pub statistics: Statistics, 133 | pub usage: vk::DeviceSize, 134 | pub budget: vk::DeviceSize 135 | } 136 | 137 | assert_size_and_align!(Budget, ffi::VmaBudget); 138 | 139 | #[repr(C)] 140 | #[derive(Copy, Clone, Debug)] 141 | pub struct AllocationCreateInfo { 142 | pub flags: AllocationCreateFlags, 143 | pub usage: MemoryUsage, 144 | pub required_flags: vk::MemoryPropertyFlags, 145 | pub preferred_flags: vk::MemoryPropertyFlags, 146 | pub memory_type_bits: u32, 147 | pub pool: Pool, 148 | pub user_data: *mut c_void, 149 | pub priority: f32 150 | } 151 | 152 | impl Default for AllocationCreateInfo { 153 | #[inline] 154 | fn default() -> Self { 155 | unsafe { mem::zeroed() } 156 | } 157 | } 158 | 159 | assert_size_and_align!(AllocationCreateInfo, ffi::VmaAllocationCreateInfo); 160 | 161 | #[repr(C)] 162 | #[derive(Copy, Clone, Debug)] 163 | pub struct PoolCreateInfo { 164 | pub memory_type_index: u32, 165 | pub flags: PoolCreateFlags, 166 | pub block_size: vk::DeviceSize, 167 | pub min_block_count: usize, 168 | pub max_block_count: usize, 169 | pub priority: f32, 170 | pub min_allocation_alignment: vk::DeviceSize, 171 | pub memory_allocate_next: *mut c_void 172 | } 173 | 174 | impl Default for PoolCreateInfo { 175 | #[inline] 176 | fn default() -> Self { 177 | unsafe { mem::zeroed() } 178 | } 179 | } 180 | 181 | assert_size_and_align!(PoolCreateInfo, ffi::VmaPoolCreateInfo); 182 | 183 | #[repr(C)] 184 | #[derive(Copy, Clone, Debug)] 185 | pub struct AllocationInfo { 186 | pub memory_type: u32, 187 | pub device_memory: vk::DeviceMemory, 188 | pub offset: vk::DeviceSize, 189 | pub size: vk::DeviceSize, 190 | pub mapped_data: *mut c_void, 191 | pub user_data: *mut c_void, 192 | pub name: *const c_char 193 | } 194 | 195 | impl Default for AllocationInfo { 196 | #[inline] 197 | fn default() -> Self { 198 | unsafe { mem::zeroed() } 199 | } 200 | } 201 | 202 | assert_size_and_align!(AllocationInfo, ffi::VmaAllocationInfo); 203 | 204 | #[repr(C)] 205 | #[derive(Copy, Clone, Debug)] 206 | pub struct DefragmentationInfo { 207 | pub flags: DefragmentationFlags, 208 | pub pool: Pool, 209 | pub max_bytes_per_pass: vk::DeviceSize, 210 | pub max_allocations_per_pass: u32, 211 | pub pfn_break_callback: PfnCheckDefragmentationBreakFunction, 212 | pub pfn_break_callback_userdata: *mut c_void 213 | } 214 | 215 | impl Default for DefragmentationInfo { 216 | fn default() -> Self { 217 | unsafe { mem::zeroed() } 218 | } 219 | } 220 | 221 | assert_size_and_align!(DefragmentationInfo, ffi::VmaDefragmentationInfo); 222 | 223 | #[repr(C)] 224 | #[derive(Copy, Clone, Debug)] 225 | pub struct DefragmentationMove { 226 | pub operation: DefragmentationMoveOperation, 227 | pub src_allocation: Allocation, 228 | pub dst_tmp_allocation: Allocation 229 | } 230 | 231 | impl Default for DefragmentationMove { 232 | #[inline] 233 | fn default() -> Self { 234 | unsafe { mem::zeroed() } 235 | } 236 | } 237 | 238 | assert_size_and_align!(DefragmentationMove, ffi::VmaDefragmentationMove); 239 | 240 | #[repr(C)] 241 | #[derive(Copy, Clone, Debug)] 242 | pub struct DefragmentationPassMoveInfo { 243 | pub move_count: u32, 244 | pub moves: *mut DefragmentationMove 245 | } 246 | 247 | impl Default for DefragmentationPassMoveInfo { 248 | #[inline] 249 | fn default() -> Self { 250 | unsafe { mem::zeroed::() } 251 | } 252 | } 253 | 254 | assert_size_and_align!(DefragmentationPassMoveInfo, ffi::VmaDefragmentationPassMoveInfo); 255 | 256 | #[repr(C)] 257 | #[derive(Copy, Clone, Debug, Default)] 258 | pub struct DefragmentationStats { 259 | pub bytes_moved: vk::DeviceSize, 260 | pub bytes_freed: vk::DeviceSize, 261 | pub allocations_moved: u32, 262 | pub device_memory_blocks_freed: u32 263 | } 264 | 265 | assert_size_and_align!(DefragmentationStats, ffi::VmaDefragmentationStats); 266 | 267 | #[repr(C)] 268 | #[derive(Copy, Clone, Debug)] 269 | pub struct VirtualBlockCreateInfo<'a> { 270 | pub size: vk::DeviceSize, 271 | pub flags: VirtualBlockCreateFlags, 272 | pub allocation_callbacks: *const vk::AllocationCallbacks<'a> 273 | } 274 | 275 | impl<'a> Default for VirtualBlockCreateInfo<'a> { 276 | #[inline] 277 | fn default() -> Self { 278 | unsafe { mem::zeroed() } 279 | } 280 | } 281 | 282 | assert_size_and_align!(VirtualBlockCreateInfo, ffi::VmaVirtualBlockCreateInfo); 283 | 284 | #[repr(C)] 285 | #[derive(Copy, Clone, Debug)] 286 | pub struct VirtualAllocationCreateInfo { 287 | pub size: vk::DeviceSize, 288 | pub alignment: vk::DeviceSize, 289 | pub flags: VirtualAllocationCreateFlags, 290 | pub user_data: *mut c_void 291 | } 292 | 293 | impl Default for VirtualAllocationCreateInfo { 294 | #[inline] 295 | fn default() -> Self { 296 | unsafe { mem::zeroed() } 297 | } 298 | } 299 | 300 | assert_size_and_align!(VirtualAllocationCreateInfo, ffi::VmaVirtualAllocationCreateInfo); 301 | 302 | #[repr(C)] 303 | #[derive(Copy, Clone, Debug)] 304 | pub struct VirtualAllocationInfo { 305 | pub offset: vk::DeviceSize, 306 | pub size: vk::DeviceSize, 307 | pub user_data: *mut c_void 308 | } 309 | 310 | impl Default for VirtualAllocationInfo { 311 | #[inline] 312 | fn default() -> Self { 313 | unsafe { mem::zeroed() } 314 | } 315 | } 316 | 317 | assert_size_and_align!(VirtualAllocationInfo, ffi::VmaVirtualAllocationInfo); 318 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::c_void; 2 | 3 | use ash::vk; 4 | 5 | use crate::utils::{define_handle, define_non_dispatchable_handle}; 6 | 7 | define_handle!(Allocator); 8 | define_handle!(Pool); 9 | define_handle!(Allocation); 10 | define_handle!(DefragmentationContext); 11 | define_non_dispatchable_handle!(VirtualAllocation); 12 | define_handle!(VirtualBlock); 13 | 14 | pub type PfnAllocateDeviceMemoryFunction = Option; 15 | pub type PfnFreeDeviceMemoryFunction = Option; 16 | 17 | pub type PfnCheckDefragmentationBreakFunction = Option vk::Bool32>; 18 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | macro_rules! define_handle { 2 | ($name: ident) => { 3 | #[repr(transparent)] 4 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] 5 | pub struct $name(*mut u8); 6 | 7 | impl Default for $name { 8 | #[inline] 9 | fn default() -> Self { 10 | Self::null() 11 | } 12 | } 13 | 14 | unsafe impl Send for $name {} 15 | unsafe impl Sync for $name {} 16 | 17 | impl $name { 18 | #[inline] 19 | pub fn as_raw(self) -> u64 { 20 | self.0 as u64 21 | } 22 | 23 | #[inline] 24 | pub fn from_raw(x: u64) -> Self { 25 | Self(x as _) 26 | } 27 | 28 | #[inline] 29 | pub const fn null() -> Self { 30 | Self(::std::ptr::null_mut()) 31 | } 32 | } 33 | 34 | impl ::std::fmt::Pointer for $name { 35 | #[inline] 36 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 37 | ::std::fmt::Pointer::fmt(&self.0, f) 38 | } 39 | } 40 | impl ::std::fmt::Debug for $name { 41 | #[inline] 42 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 43 | ::std::fmt::Debug::fmt(&self.0, f) 44 | } 45 | } 46 | }; 47 | } 48 | 49 | pub(crate) use define_handle; 50 | 51 | macro_rules! define_non_dispatchable_handle { 52 | ($name: ident) => { 53 | #[repr(transparent)] 54 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] 55 | pub struct $name(u64); 56 | 57 | impl Default for $name { 58 | #[inline] 59 | fn default() -> Self { 60 | Self::null() 61 | } 62 | } 63 | 64 | impl $name { 65 | #[inline] 66 | pub fn as_raw(self) -> u64 { 67 | self.0 68 | } 69 | 70 | #[inline] 71 | pub fn from_raw(x: u64) -> Self { 72 | Self(x) 73 | } 74 | 75 | #[inline] 76 | pub const fn null() -> Self { 77 | Self(0) 78 | } 79 | } 80 | 81 | impl ::std::fmt::Pointer for $name { 82 | #[inline] 83 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 84 | write!(f, "0x{:x}", self.0) 85 | } 86 | } 87 | impl ::std::fmt::Debug for $name { 88 | #[inline] 89 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 90 | write!(f, "0x{:x}", self.0) 91 | } 92 | } 93 | }; 94 | } 95 | 96 | pub(crate) use define_non_dispatchable_handle; 97 | 98 | macro_rules! assert_size_and_align { 99 | ($type_: ty, $ffi_type: ty) => { 100 | ::static_assertions::assert_eq_size!($type_, $ffi_type); 101 | ::static_assertions::assert_eq_align!($type_, $ffi_type); 102 | }; 103 | } 104 | 105 | pub(crate) use assert_size_and_align; 106 | -------------------------------------------------------------------------------- /vk-mem-alloc-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vk-mem-alloc-sys" 3 | version = "0.2.0" 4 | edition = "2021" 5 | 6 | authors = [ "Lorenz Klaus ", "Marlon Klaus " ] 7 | description = "A very lightweight wrapper around the Vulkan Memory Allocator" 8 | homepage = "https://github.com/projectkml/vk-mem-alloc-rs" 9 | repository = "https://github.com/projectkml/vk-mem-alloc-rs" 10 | documentation = "https://docs.rs/vk-mem-alloc" 11 | readme = "README.md" 12 | keywords = [ "vulkan", "vk", "ash", "memory", "allocator" ] 13 | categories = [ "api-bindings", "rendering", "rendering::engine", "rendering::graphics-api" ] 14 | license = "MIT/Apache-2.0" 15 | build = "build.rs" 16 | include = [ 17 | "src/*.rs", 18 | "build.rs", 19 | "Cargo.toml", 20 | "vendor/VulkanMemoryAllocator/include/vk_mem_alloc.h", 21 | "vendor/Vulkan-Headers/include/*", 22 | "wrapper/vk_mem_alloc.cpp" 23 | ] 24 | 25 | [dependencies] 26 | ash = "0.38.0+1.3.281" 27 | 28 | [build-dependencies] 29 | bindgen = "0.69.4" 30 | cc = "1.0.90" 31 | 32 | [features] 33 | recording = [] 34 | 35 | [profile.release] 36 | opt-level = 3 37 | codegen-units = 1 38 | 39 | lto = true -------------------------------------------------------------------------------- /vk-mem-alloc-sys/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | # `🌋 vk-mem-alloc-rs` 7 | 8 | **A very lightweight wrapper around the Vulkan Memory Allocator 🦀** 9 | 10 | [![crates][crates-badge]][crates-url] 11 | [![license][license-badge]][license-url] 12 | [![vma][vma-badge]][vma-url] 13 | [![dependency-status][dependency-badge]][dependency-url] 14 | 15 | [crates-badge]: https://img.shields.io/crates/v/vk-mem-alloc.svg 16 | [crates-url]: https://crates.io/crates/vk-mem-alloc 17 | 18 | [license-badge]: https://img.shields.io/badge/License-MIT/Apache_2.0-blue.svg 19 | [license-url]: LICENSE-MIT 20 | 21 | [vma-badge]: https://img.shields.io/badge/Vulkan%20Memory%20Allocator-3.0.1-orange 22 | [vma-url]: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator 23 | 24 | [dependency-badge]: https://deps.rs/repo/github/projectkml/vk-mem-alloc-rs/status.svg 25 | [dependency-url]: https://deps.rs/repo/github/projectkml/vk-mem-alloc-rs 26 | 27 |
28 | 29 | This is the `vk-mem-alloc-sys` crate. Its very likely that you want to use the `vk-mem-alloc` crate instead. -------------------------------------------------------------------------------- /vk-mem-alloc-sys/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, fs, path::Path}; 2 | 3 | use bindgen::Formatter; 4 | use bindgen::callbacks::ParseCallbacks; 5 | 6 | #[derive(Debug)] 7 | struct BindgenCallbacks; 8 | 9 | impl ParseCallbacks for BindgenCallbacks { 10 | fn item_name(&self, original_item_name: &str) -> Option { 11 | if original_item_name.starts_with("Vk") { 12 | Some(original_item_name.trim_start_matches("Vk").to_string()) 13 | } else if original_item_name.starts_with("PFN_vk") && original_item_name.ends_with("KHR") { 14 | Some(original_item_name.trim_end_matches("KHR").to_string()) 15 | } else { 16 | None 17 | } 18 | } 19 | } 20 | 21 | fn generate_bindings() { 22 | let bindings = bindgen::Builder::default() 23 | .clang_arg("I./wrapper") 24 | .clang_arg("-I./vendor/Vulkan-Headers/include") 25 | .header("vendor/VulkanMemoryAllocator/include/vk_mem_alloc.h") 26 | .formatter(Formatter::Rustfmt) 27 | .size_t_is_usize(true) 28 | .allowlist_function("vma.*") 29 | .allowlist_function("PFN_vma.*") 30 | .allowlist_type("Vma.*") 31 | .parse_callbacks(Box::new(BindgenCallbacks)) 32 | .blocklist_type("Vk.*") 33 | .blocklist_type("PFN_vk.*") 34 | .raw_line("use ash::vk::*;") 35 | .layout_tests(false) 36 | .generate() 37 | .expect("Failed to generate bindings"); 38 | 39 | let bindings_str = bindings 40 | .to_string() 41 | .replace(" AllocationCallbacks", " AllocationCallbacks<'a>") 42 | .replace(" VmaAllocatorCreateInfo", " VmaAllocatorCreateInfo<'a>") 43 | .replace(" VmaVirtualBlockCreateInfo", " VmaVirtualBlockCreateInfo<'a>") 44 | .replace("vmaCreateAllocator", "vmaCreateAllocator<'a>") 45 | .replace("vmaCreateVirtualBlock", "vmaCreateVirtualBlock<'a>"); 46 | 47 | fs::create_dir_all("gen").unwrap(); 48 | fs::write(Path::new("gen/bindings.rs"), bindings_str).expect("Failed to write bindings to file"); 49 | } 50 | 51 | fn main() { 52 | let mut build = cc::Build::new(); 53 | 54 | build.define("VMA_STATIC_VULKAN_FUNCTIONS", "0").define("VMA_DYNAMIC_VULKAN_FUNCTIONS", "0"); 55 | 56 | #[cfg(feature = "recording")] 57 | build.define("VMA_RECORDING_ENABLED", "1"); 58 | 59 | let target = env::var("TARGET").unwrap(); 60 | 61 | if target.contains("gnu") || target.contains("darwin") { 62 | build 63 | .flag("-std=c++17") 64 | .flag("-Wno-missing-field-initializers") 65 | .flag("-Wno-nullability-completeness") 66 | .flag("-Wno-unused-parameter") 67 | .flag("-Wno-unused-variable") 68 | .flag("-Wno-parentheses") 69 | .flag("-Wno-implicit-fallthrough"); 70 | } 71 | 72 | build 73 | .cpp(true) 74 | .include("vendor/Vulkan-Headers/include") 75 | .include("vendor/VulkanMemoryAllocator/include") 76 | .file("wrapper/vk_mem_alloc.cpp") 77 | .compile("vk_mem_alloc_sys_cc"); 78 | 79 | generate_bindings(); 80 | } 81 | -------------------------------------------------------------------------------- /vk-mem-alloc-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_snake_case)] 4 | #![cfg_attr(feature = "cargo-clippy", allow(clippy::unreadable_literal))] 5 | 6 | include!("../gen/bindings.rs"); 7 | -------------------------------------------------------------------------------- /vk-mem-alloc-sys/wrapper/vk_mem_alloc.cpp: -------------------------------------------------------------------------------- 1 | #define VMA_IMPLEMENTATION 2 | #include --------------------------------------------------------------------------------