From d685b50c85df76b275f8a504b93078a4fd9aabb8 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Tue, 10 May 2022 22:31:09 -0700 Subject: [PATCH 01/23] fix bindgen issue on msvc --- Cargo.toml | 6 +- build.rs | 9 +- gen/bindings.rs | 1871 -------------------------------------------- src/definitions.rs | 38 +- src/ffi.rs | 1863 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 1885 insertions(+), 1902 deletions(-) delete mode 100644 gen/bindings.rs diff --git a/Cargo.toml b/Cargo.toml index 74fa545..eb172a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,14 +29,14 @@ travis-ci = { repository = "gwihlidal/vk-mem-rs" } maintenance = { status = "actively-developed" } [dependencies] -ash = ">= 0.35" +ash = "0.37" bitflags = "1.2.1" [build-dependencies] -cc = "1.0.50" +cc = "1.0" [build-dependencies.bindgen] -version = "0.59.1" +version = "0.59" optional = true [profile.release] diff --git a/build.rs b/build.rs index c5ca942..cba6e3b 100644 --- a/build.rs +++ b/build.rs @@ -8,7 +8,7 @@ fn main() { let mut build = cc::Build::new(); build.include("vendor/VulkanMemoryAllocator/include"); - build.include("vendor/Vulkan-Headers/include/vulkan"); + build.include("vendor/Vulkan-Headers/include"); build.include("wrapper"); // Disable VMA_ASSERT when rust assertions are disabled @@ -102,10 +102,10 @@ fn main() { .cpp(true); } - build.compile("vma_cpp"); + build.compile("vma"); link_vulkan(); - generate_bindings("gen/bindings.rs"); + generate_bindings("src/ffi.rs"); } #[cfg(feature = "link_vulkan")] @@ -166,9 +166,12 @@ fn generate_bindings(output_file: &str) { .parse_callbacks(Box::new(FixAshTypes)) .blocklist_type("Vk.*") .blocklist_type("PFN_vk.*") + .raw_line("#![allow(non_camel_case_types)]") + .raw_line("#![allow(non_snake_case)]") .raw_line("use ash::vk::*;") .trust_clang_mangling(false) .layout_tests(false) + .rustified_enum("Vma.*") .generate() .expect("Unable to generate bindings!"); diff --git a/gen/bindings.rs b/gen/bindings.rs deleted file mode 100644 index ac5af5c..0000000 --- a/gen/bindings.rs +++ /dev/null @@ -1,1871 +0,0 @@ -/* automatically generated by rust-bindgen 0.59.2 */ - -use ash::vk::*; - -pub type __uint8_t = ::std::os::raw::c_uchar; -pub type __int32_t = ::std::os::raw::c_int; -pub type __uint32_t = ::std::os::raw::c_uint; -pub type __uint64_t = ::std::os::raw::c_ulong; -#[doc = " \\brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you."] -#[doc = ""] -#[doc = "Using this flag may increase performance because internal mutexes are not used."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT: - VmaAllocatorCreateFlagBits = 1; -#[doc = " \\brief Enables usage of VK_KHR_dedicated_allocation extension."] -#[doc = ""] -#[doc = "The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`."] -#[doc = "When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1."] -#[doc = ""] -#[doc = "Using this extension will automatically allocate dedicated blocks of memory for"] -#[doc = "some buffers and images instead of suballocating place for them out of bigger"] -#[doc = "memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT"] -#[doc = "flag) when it is recommended by the driver. It may improve performance on some"] -#[doc = "GPUs."] -#[doc = ""] -#[doc = "You may set this flag only if you found out that following device extensions are"] -#[doc = "supported, you enabled them while creating Vulkan device passed as"] -#[doc = "VmaAllocatorCreateInfo::device, and you want them to be used internally by this"] -#[doc = "library:"] -#[doc = ""] -#[doc = "- VK_KHR_get_memory_requirements2 (device extension)"] -#[doc = "- VK_KHR_dedicated_allocation (device extension)"] -#[doc = ""] -#[doc = "When this flag is set, you can experience following warnings reported by Vulkan"] -#[doc = "validation layer. You can ignore them."] -#[doc = ""] -#[doc = "> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT: - VmaAllocatorCreateFlagBits = 2; -#[doc = "Enables usage of VK_KHR_bind_memory2 extension."] -#[doc = ""] -#[doc = "The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`."] -#[doc = "When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1."] -#[doc = ""] -#[doc = "You may set this flag only if you found out that this device extension is supported,"] -#[doc = "you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,"] -#[doc = "and you want it to be used internally by this library."] -#[doc = ""] -#[doc = "The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,"] -#[doc = "which allow to pass a chain of `pNext` structures while binding."] -#[doc = "This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2()."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT: - VmaAllocatorCreateFlagBits = 4; -#[doc = "Enables usage of VK_EXT_memory_budget extension."] -#[doc = ""] -#[doc = "You may set this flag only if you found out that this device extension is supported,"] -#[doc = "you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,"] -#[doc = "and you want it to be used internally by this library, along with another instance extension"] -#[doc = "VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted)."] -#[doc = ""] -#[doc = "The extension provides query for current memory usage and budget, which will probably"] -#[doc = "be more accurate than an estimation used by the library otherwise."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT: - VmaAllocatorCreateFlagBits = 8; -#[doc = "Enables usage of VK_AMD_device_coherent_memory extension."] -#[doc = ""] -#[doc = "You may set this flag only if you:"] -#[doc = ""] -#[doc = "- found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,"] -#[doc = "- checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device,"] -#[doc = "- want it to be used internally by this library."] -#[doc = ""] -#[doc = "The extension and accompanying device feature provide access to memory types with"] -#[doc = "`VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags."] -#[doc = "They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR."] -#[doc = ""] -#[doc = "When the extension is not enabled, such memory types are still enumerated, but their usage is illegal."] -#[doc = "To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type,"] -#[doc = "returning `VK_ERROR_FEATURE_NOT_PRESENT`."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT: - VmaAllocatorCreateFlagBits = 16; -#[doc = "Enables usage of \"buffer device address\" feature, which allows you to use function"] -#[doc = "`vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader."] -#[doc = ""] -#[doc = "You may set this flag only if you:"] -#[doc = ""] -#[doc = "1. (For Vulkan version < 1.2) Found as available and enabled device extension"] -#[doc = "VK_KHR_buffer_device_address."] -#[doc = "This extension is promoted to core Vulkan 1.2."] -#[doc = "2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`."] -#[doc = ""] -#[doc = "When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA."] -#[doc = "The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to"] -#[doc = "allocated memory blocks wherever it might be needed."] -#[doc = ""] -#[doc = "For more information, see documentation chapter \\ref enabling_buffer_device_address."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT: - VmaAllocatorCreateFlagBits = 32; -#[doc = "Enables usage of VK_EXT_memory_priority extension in the library."] -#[doc = ""] -#[doc = "You may set this flag only if you found available and enabled this device extension,"] -#[doc = "along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,"] -#[doc = "while creating Vulkan device passed as VmaAllocatorCreateInfo::device."] -#[doc = ""] -#[doc = "When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority"] -#[doc = "are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored."] -#[doc = ""] -#[doc = "A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations."] -#[doc = "Larger values are higher priority. The granularity of the priorities is implementation-dependent."] -#[doc = "It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`."] -#[doc = "The value to be used for default priority is 0.5."] -#[doc = "For more details, see the documentation of the VK_EXT_memory_priority extension."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT: - VmaAllocatorCreateFlagBits = 64; -#[doc = "Enables usage of VK_EXT_memory_priority extension in the library."] -#[doc = ""] -#[doc = "You may set this flag only if you found available and enabled this device extension,"] -#[doc = "along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,"] -#[doc = "while creating Vulkan device passed as VmaAllocatorCreateInfo::device."] -#[doc = ""] -#[doc = "When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority"] -#[doc = "are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored."] -#[doc = ""] -#[doc = "A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations."] -#[doc = "Larger values are higher priority. The granularity of the priorities is implementation-dependent."] -#[doc = "It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`."] -#[doc = "The value to be used for default priority is 0.5."] -#[doc = "For more details, see the documentation of the VK_EXT_memory_priority extension."] -pub const VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM: - VmaAllocatorCreateFlagBits = 2147483647; -#[doc = " Flags for created #VmaAllocator."] -pub type VmaAllocatorCreateFlagBits = ::std::os::raw::c_uint; -pub type VmaAllocatorCreateFlags = Flags; -#[doc = " No intended memory usage specified."] -#[doc = "Use other members of VmaAllocationCreateInfo to specify your requirements."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_UNKNOWN: VmaMemoryUsage = 0; -#[doc = " Memory will be used on device only, so fast access from the device is preferred."] -#[doc = "It usually means device-local GPU (video) memory."] -#[doc = "No need to be mappable on host."] -#[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`."] -#[doc = ""] -#[doc = "Usage:"] -#[doc = ""] -#[doc = "- Resources written and read by device, e.g. images used as attachments."] -#[doc = "- Resources transferred from host once (immutable) or infrequently and read by"] -#[doc = "device multiple times, e.g. textures to be sampled, vertex buffers, uniform"] -#[doc = "(constant) buffers, and majority of other types of resources used on GPU."] -#[doc = ""] -#[doc = "Allocation may still end up in `HOST_VISIBLE` memory on some implementations."] -#[doc = "In such case, you are free to map it."] -#[doc = "You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_ONLY: VmaMemoryUsage = 1; -#[doc = " Memory will be mappable on host."] -#[doc = "It usually means CPU (system) memory."] -#[doc = "Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`."] -#[doc = "CPU access is typically uncached. Writes may be write-combined."] -#[doc = "Resources created in this pool may still be accessible to the device, but access to them can be slow."] -#[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`."] -#[doc = ""] -#[doc = "Usage: Staging copy of resources used as transfer source."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_ONLY: VmaMemoryUsage = 2; -#[doc = "Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU."] -#[doc = "CPU access is typically uncached. Writes may be write-combined."] -#[doc = ""] -#[doc = "Usage: Resources written frequently by host (dynamic), read by device. E.g. textures (with LINEAR layout), vertex buffers, uniform buffers updated every frame or every draw call."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_TO_GPU: VmaMemoryUsage = 3; -#[doc = " Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached."] -#[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`."] -#[doc = ""] -#[doc = "Usage:"] -#[doc = ""] -#[doc = "- Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping."] -#[doc = "- Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_TO_CPU: VmaMemoryUsage = 4; -#[doc = " CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`."] -#[doc = ""] -#[doc = "Usage: Staging copy of resources moved from GPU memory to CPU memory as part"] -#[doc = "of custom paging/residency mechanism, to be moved back to GPU memory when needed."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_COPY: VmaMemoryUsage = 5; -#[doc = " Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] -#[doc = "Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation."] -#[doc = ""] -#[doc = "Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`."] -#[doc = ""] -#[doc = "Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED: VmaMemoryUsage = 6; -#[doc = " Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] -#[doc = "Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation."] -#[doc = ""] -#[doc = "Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`."] -#[doc = ""] -#[doc = "Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] -pub const VmaMemoryUsage_VMA_MEMORY_USAGE_MAX_ENUM: VmaMemoryUsage = 2147483647; -#[doc = " \\brief Intended usage of the allocated memory."] -pub type VmaMemoryUsage = ::std::os::raw::c_uint; -#[doc = " \\brief Set this flag if the allocation should have its own memory block."] -#[doc = ""] -#[doc = "Use it for special, big resources, like fullscreen images used as attachments."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT: - VmaAllocationCreateFlagBits = 1; -#[doc = " \\brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block."] -#[doc = ""] -#[doc = "If new allocation cannot be placed in any of the existing blocks, allocation"] -#[doc = "fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error."] -#[doc = ""] -#[doc = "You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and"] -#[doc = "#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense."] -#[doc = ""] -#[doc = "If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT: - VmaAllocationCreateFlagBits = 2; -#[doc = " \\brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it."] -#[doc = ""] -#[doc = "Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData."] -#[doc = ""] -#[doc = "It is valid to use this flag for allocation made from memory type that is not"] -#[doc = "`HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is"] -#[doc = "useful if you need an allocation that is efficient to use on GPU"] -#[doc = "(`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that"] -#[doc = "support it (e.g. Intel GPU)."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_MAPPED_BIT: - VmaAllocationCreateFlagBits = 4; -#[doc = " \\deprecated Removed. Do not use."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_RESERVED_1_BIT: - VmaAllocationCreateFlagBits = 8; -#[doc = " \\deprecated Removed. Do not use."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_RESERVED_2_BIT: - VmaAllocationCreateFlagBits = 16; -#[doc = " Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a"] -#[doc = "null-terminated string. Instead of copying pointer value, a local copy of the"] -#[doc = "string is made and stored in allocation's `pUserData`. The string is automatically"] -#[doc = "freed together with the allocation. It is also used in vmaBuildStatsString()."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT: - VmaAllocationCreateFlagBits = 32; -#[doc = " Allocation will be created from upper stack in a double stack pool."] -#[doc = ""] -#[doc = "This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT: - VmaAllocationCreateFlagBits = 64; -#[doc = " Create both buffer/image and allocation, but don't bind them together."] -#[doc = "It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions."] -#[doc = "The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage()."] -#[doc = "Otherwise it is ignored."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_DONT_BIND_BIT: - VmaAllocationCreateFlagBits = 128; -#[doc = " Create allocation only if additional device memory required for it, if any, won't exceed"] -#[doc = "memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT: - VmaAllocationCreateFlagBits = 256; -#[doc = " \\brief Set this flag if the allocated memory will have aliasing resources."] -#[doc = ""] -#[doc = "Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified."] -#[doc = "Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT: - VmaAllocationCreateFlagBits = 512; -#[doc = " Allocation strategy that chooses smallest possible free range for the allocation"] -#[doc = "to minimize memory usage and fragmentation, possibly at the expense of allocation time."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT: - VmaAllocationCreateFlagBits = 65536; -#[doc = " Allocation strategy that chooses first suitable free range for the allocation -"] -#[doc = "not necessarily in terms of the smallest offset but the one that is easiest and fastest to find"] -#[doc = "to minimize allocation time, possibly at the expense of allocation quality."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT: - VmaAllocationCreateFlagBits = 131072; -#[doc = " Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT: - VmaAllocationCreateFlagBits = 65536; -#[doc = " Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT: - VmaAllocationCreateFlagBits = 131072; -#[doc = " A bit mask to extract only `STRATEGY` bits from entire set of flags."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_STRATEGY_MASK: - VmaAllocationCreateFlagBits = 196608; -#[doc = " A bit mask to extract only `STRATEGY` bits from entire set of flags."] -pub const VmaAllocationCreateFlagBits_VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM: - VmaAllocationCreateFlagBits = 2147483647; -#[doc = " Flags to be passed as VmaAllocationCreateInfo::flags."] -pub type VmaAllocationCreateFlagBits = ::std::os::raw::c_uint; -pub type VmaAllocationCreateFlags = Flags; -#[doc = " \\brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored."] -#[doc = ""] -#[doc = "This is an optional optimization flag."] -#[doc = ""] -#[doc = "If you always allocate using vmaCreateBuffer(), vmaCreateImage(),"] -#[doc = "vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator"] -#[doc = "knows exact type of your allocations so it can handle Buffer-Image Granularity"] -#[doc = "in the optimal way."] -#[doc = ""] -#[doc = "If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),"] -#[doc = "exact type of such allocations is not known, so allocator must be conservative"] -#[doc = "in handling Buffer-Image Granularity, which can lead to suboptimal allocation"] -#[doc = "(wasted memory). In that case, if you can make sure you always allocate only"] -#[doc = "buffers and linear images or only optimal images out of this pool, use this flag"] -#[doc = "to make allocator disregard Buffer-Image Granularity and so make allocations"] -#[doc = "faster and more optimal."] -pub const VmaPoolCreateFlagBits_VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT: - VmaPoolCreateFlagBits = 2; -#[doc = " \\brief Enables alternative, linear allocation algorithm in this pool."] -#[doc = ""] -#[doc = "Specify this flag to enable linear allocation algorithm, which always creates"] -#[doc = "new allocations after last one and doesn't reuse space from allocations freed in"] -#[doc = "between. It trades memory consumption for simplified algorithm and data"] -#[doc = "structure, which has better performance and uses less memory for metadata."] -#[doc = ""] -#[doc = "By using this flag, you can achieve behavior of free-at-once, stack,"] -#[doc = "ring buffer, and double stack."] -#[doc = "For details, see documentation chapter \\ref linear_algorithm."] -pub const VmaPoolCreateFlagBits_VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT: VmaPoolCreateFlagBits = 4; -#[doc = " \\brief Enables alternative, buddy allocation algorithm in this pool."] -#[doc = ""] -#[doc = "It operates on a tree of blocks, each having size that is a power of two and"] -#[doc = "a half of its parent's size. Comparing to default algorithm, this one provides"] -#[doc = "faster allocation and deallocation and decreased external fragmentation,"] -#[doc = "at the expense of more memory wasted (internal fragmentation)."] -#[doc = "For details, see documentation chapter \\ref buddy_algorithm."] -pub const VmaPoolCreateFlagBits_VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT: VmaPoolCreateFlagBits = 8; -#[doc = " \\brief Enables alternative, Two-Level Segregated Fit (TLSF) allocation algorithm in this pool."] -#[doc = ""] -#[doc = "This algorithm is based on 2-level lists dividing address space into smaller"] -#[doc = "chunks. The first level is aligned to power of two which serves as buckets for requested"] -#[doc = "memory to fall into, and the second level is lineary subdivided into lists of free memory."] -#[doc = "This algorithm aims to achieve bounded response time even in the worst case scenario."] -#[doc = "Allocation time can be sometimes slightly longer than compared to other algorithms"] -#[doc = "but in return the application can avoid stalls in case of fragmentation, giving"] -#[doc = "predictable results, suitable for real-time use cases."] -pub const VmaPoolCreateFlagBits_VMA_POOL_CREATE_TLSF_ALGORITHM_BIT: VmaPoolCreateFlagBits = 16; -#[doc = " Bit mask to extract only `ALGORITHM` bits from entire set of flags."] -pub const VmaPoolCreateFlagBits_VMA_POOL_CREATE_ALGORITHM_MASK: VmaPoolCreateFlagBits = 28; -#[doc = " Bit mask to extract only `ALGORITHM` bits from entire set of flags."] -pub const VmaPoolCreateFlagBits_VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM: VmaPoolCreateFlagBits = - 2147483647; -#[doc = " Flags to be passed as VmaPoolCreateInfo::flags."] -pub type VmaPoolCreateFlagBits = ::std::os::raw::c_uint; -#[doc = " Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits."] -pub type VmaPoolCreateFlags = Flags; -pub const VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_INCREMENTAL: - VmaDefragmentationFlagBits = 1; -pub const VmaDefragmentationFlagBits_VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM: - VmaDefragmentationFlagBits = 2147483647; -#[doc = " Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use."] -pub type VmaDefragmentationFlagBits = ::std::os::raw::c_uint; -pub type VmaDefragmentationFlags = Flags; -#[doc = " \\brief Enables alternative, linear allocation algorithm in this virtual block."] -#[doc = ""] -#[doc = "Specify this flag to enable linear allocation algorithm, which always creates"] -#[doc = "new allocations after last one and doesn't reuse space from allocations freed in"] -#[doc = "between. It trades memory consumption for simplified algorithm and data"] -#[doc = "structure, which has better performance and uses less memory for metadata."] -#[doc = ""] -#[doc = "By using this flag, you can achieve behavior of free-at-once, stack,"] -#[doc = "ring buffer, and double stack."] -#[doc = "For details, see documentation chapter \\ref linear_algorithm."] -pub const VmaVirtualBlockCreateFlagBits_VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT: - VmaVirtualBlockCreateFlagBits = 1; -#[doc = " \\brief Enables alternative, buddy allocation algorithm in this virtual block."] -#[doc = ""] -#[doc = "It operates on a tree of blocks, each having size that is a power of two and"] -#[doc = "a half of its parent's size. Comparing to default algorithm, this one provides"] -#[doc = "faster allocation and deallocation and decreased external fragmentation,"] -#[doc = "at the expense of more memory wasted (internal fragmentation)."] -#[doc = "For details, see documentation chapter \\ref buddy_algorithm."] -pub const VmaVirtualBlockCreateFlagBits_VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT: - VmaVirtualBlockCreateFlagBits = 2; -#[doc = " \\brief Enables alternative, TLSF allocation algorithm in virtual block."] -#[doc = ""] -#[doc = "This algorithm is based on 2-level lists dividing address space into smaller"] -#[doc = "chunks. The first level is aligned to power of two which serves as buckets for requested"] -#[doc = "memory to fall into, and the second level is lineary subdivided into lists of free memory."] -#[doc = "This algorithm aims to achieve bounded response time even in the worst case scenario."] -#[doc = "Allocation time can be sometimes slightly longer than compared to other algorithms"] -#[doc = "but in return the application can avoid stalls in case of fragmentation, giving"] -#[doc = "predictable results, suitable for real-time use cases."] -pub const VmaVirtualBlockCreateFlagBits_VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT: - VmaVirtualBlockCreateFlagBits = 4; -#[doc = " \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags."] -pub const VmaVirtualBlockCreateFlagBits_VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK: - VmaVirtualBlockCreateFlagBits = 7; -#[doc = " \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags."] -pub const VmaVirtualBlockCreateFlagBits_VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM: - VmaVirtualBlockCreateFlagBits = 2147483647; -#[doc = " Flags to be passed as VmaVirtualBlockCreateInfo::flags."] -pub type VmaVirtualBlockCreateFlagBits = ::std::os::raw::c_uint; -#[doc = " Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits."] -pub type VmaVirtualBlockCreateFlags = Flags; -#[doc = " \\brief Allocation will be created from upper stack in a double stack pool."] -#[doc = ""] -#[doc = "This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag."] -pub const VmaVirtualAllocationCreateFlagBits_VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT: - VmaVirtualAllocationCreateFlagBits = 64; -#[doc = " \\brief Allocation strategy that tries to minimize memory usage."] -pub const VmaVirtualAllocationCreateFlagBits_VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT : VmaVirtualAllocationCreateFlagBits = 65536 ; -#[doc = " \\brief Allocation strategy that tries to minimize allocation time."] -pub const VmaVirtualAllocationCreateFlagBits_VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT: - VmaVirtualAllocationCreateFlagBits = 131072; -#[doc = " \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags."] -#[doc = ""] -#[doc = "These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits."] -pub const VmaVirtualAllocationCreateFlagBits_VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK: - VmaVirtualAllocationCreateFlagBits = 196608; -#[doc = " \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags."] -#[doc = ""] -#[doc = "These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits."] -pub const VmaVirtualAllocationCreateFlagBits_VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM: - VmaVirtualAllocationCreateFlagBits = 2147483647; -#[doc = " Flags to be passed as VmaVirtualAllocationCreateInfo::flags."] -pub type VmaVirtualAllocationCreateFlagBits = ::std::os::raw::c_uint; -#[doc = " Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits."] -pub type VmaVirtualAllocationCreateFlags = Flags; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaAllocator_T { - _unused: [u8; 0], -} -pub type VmaAllocator = *mut VmaAllocator_T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaPool_T { - _unused: [u8; 0], -} -pub type VmaPool = *mut VmaPool_T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaAllocation_T { - _unused: [u8; 0], -} -pub type VmaAllocation = *mut VmaAllocation_T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaDefragmentationContext_T { - _unused: [u8; 0], -} -pub type VmaDefragmentationContext = *mut VmaDefragmentationContext_T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaVirtualAllocation_T { - _unused: [u8; 0], -} -pub type VmaVirtualAllocation = *mut VmaVirtualAllocation_T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaVirtualBlock_T { - _unused: [u8; 0], -} -pub type VmaVirtualBlock = *mut VmaVirtualBlock_T; -#[doc = " Callback function called after successful vkAllocateMemory."] -pub type PFN_vmaAllocateDeviceMemoryFunction = ::std::option::Option< - unsafe extern "C" fn( - allocator: VmaAllocator, - memoryType: u32, - memory: DeviceMemory, - size: DeviceSize, - pUserData: *mut ::std::os::raw::c_void, - ), ->; -#[doc = " Callback function called before vkFreeMemory."] -pub type PFN_vmaFreeDeviceMemoryFunction = ::std::option::Option< - unsafe extern "C" fn( - allocator: VmaAllocator, - memoryType: u32, - memory: DeviceMemory, - size: DeviceSize, - pUserData: *mut ::std::os::raw::c_void, - ), ->; -#[doc = " \\brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`."] -#[doc = ""] -#[doc = "Provided for informative purpose, e.g. to gather statistics about number of"] -#[doc = "allocations or total amount of memory allocated in Vulkan."] -#[doc = ""] -#[doc = "Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaDeviceMemoryCallbacks { - #[doc = " Optional, can be null."] - pub pfnAllocate: PFN_vmaAllocateDeviceMemoryFunction, - #[doc = " Optional, can be null."] - pub pfnFree: PFN_vmaFreeDeviceMemoryFunction, - #[doc = " Optional, can be null."] - pub pUserData: *mut ::std::os::raw::c_void, -} -#[doc = " \\brief Pointers to some Vulkan functions - a subset used by the library."] -#[doc = ""] -#[doc = "Used in VmaAllocatorCreateInfo::pVulkanFunctions."] -#[repr(C)] -pub struct VmaVulkanFunctions { - #[doc = " Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS."] - pub vkGetInstanceProcAddr: PFN_vkGetInstanceProcAddr, - #[doc = " Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS."] - pub vkGetDeviceProcAddr: PFN_vkGetDeviceProcAddr, - pub vkGetPhysicalDeviceProperties: PFN_vkGetPhysicalDeviceProperties, - pub vkGetPhysicalDeviceMemoryProperties: PFN_vkGetPhysicalDeviceMemoryProperties, - pub vkAllocateMemory: PFN_vkAllocateMemory, - pub vkFreeMemory: PFN_vkFreeMemory, - pub vkMapMemory: PFN_vkMapMemory, - pub vkUnmapMemory: PFN_vkUnmapMemory, - pub vkFlushMappedMemoryRanges: PFN_vkFlushMappedMemoryRanges, - pub vkInvalidateMappedMemoryRanges: PFN_vkInvalidateMappedMemoryRanges, - pub vkBindBufferMemory: PFN_vkBindBufferMemory, - pub vkBindImageMemory: PFN_vkBindImageMemory, - pub vkGetBufferMemoryRequirements: PFN_vkGetBufferMemoryRequirements, - pub vkGetImageMemoryRequirements: PFN_vkGetImageMemoryRequirements, - pub vkCreateBuffer: PFN_vkCreateBuffer, - pub vkDestroyBuffer: PFN_vkDestroyBuffer, - pub vkCreateImage: PFN_vkCreateImage, - pub vkDestroyImage: PFN_vkDestroyImage, - pub vkCmdCopyBuffer: PFN_vkCmdCopyBuffer, - #[doc = " Fetch \"vkGetBufferMemoryRequirements2\" on Vulkan >= 1.1, fetch \"vkGetBufferMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] - pub vkGetBufferMemoryRequirements2KHR: PFN_vkGetBufferMemoryRequirements2, - #[doc = " Fetch \"vkGetImageMemoryRequirements 2\" on Vulkan >= 1.1, fetch \"vkGetImageMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] - pub vkGetImageMemoryRequirements2KHR: PFN_vkGetImageMemoryRequirements2, - #[doc = " Fetch \"vkBindBufferMemory2\" on Vulkan >= 1.1, fetch \"vkBindBufferMemory2KHR\" when using VK_KHR_bind_memory2 extension."] - pub vkBindBufferMemory2KHR: PFN_vkBindBufferMemory2, - #[doc = " Fetch \"vkBindImageMemory2\" on Vulkan >= 1.1, fetch \"vkBindImageMemory2KHR\" when using VK_KHR_bind_memory2 extension."] - pub vkBindImageMemory2KHR: PFN_vkBindImageMemory2, - pub vkGetPhysicalDeviceMemoryProperties2KHR: PFN_vkGetPhysicalDeviceMemoryProperties2, -} -#[doc = " Description of a Allocator to be created."] -#[repr(C)] -pub struct VmaAllocatorCreateInfo { - #[doc = " Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum."] - pub flags: VmaAllocatorCreateFlags, - #[doc = " Vulkan physical device."] - #[doc = "** It must be valid throughout whole lifetime of created allocator. */"] - pub physicalDevice: PhysicalDevice, - #[doc = " Vulkan device."] - #[doc = "** It must be valid throughout whole lifetime of created allocator. */"] - pub device: Device, - #[doc = " Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional."] - #[doc = "** Set to 0 to use default, which is currently 256 MiB. */"] - pub preferredLargeHeapBlockSize: DeviceSize, - #[doc = " Custom CPU memory allocation callbacks. Optional."] - #[doc = "** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */"] - pub pAllocationCallbacks: *const AllocationCallbacks, - #[doc = " Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional."] - #[doc = "** Optional, can be null. */"] - pub pDeviceMemoryCallbacks: *const VmaDeviceMemoryCallbacks, - #[doc = " \\brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap."] - #[doc = ""] - #[doc = "If not NULL, it must be a pointer to an array of"] - #[doc = "`VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on"] - #[doc = "maximum number of bytes that can be allocated out of particular Vulkan memory"] - #[doc = "heap."] - #[doc = ""] - #[doc = "Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that"] - #[doc = "heap. This is also the default in case of `pHeapSizeLimit` = NULL."] - #[doc = ""] - #[doc = "If there is a limit defined for a heap:"] - #[doc = ""] - #[doc = "- If user tries to allocate more memory from that heap using this allocator,"] - #[doc = "the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`."] - #[doc = "- If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the"] - #[doc = "value of this limit will be reported instead when using vmaGetMemoryProperties()."] - #[doc = ""] - #[doc = "Warning! Using this feature may not be equivalent to installing a GPU with"] - #[doc = "smaller amount of memory, because graphics driver doesn't necessary fail new"] - #[doc = "allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is"] - #[doc = "exceeded. It may return success and just silently migrate some device memory"] - #[doc = "blocks to system RAM. This driver behavior can also be controlled using"] - #[doc = "VK_AMD_memory_overallocation_behavior extension."] - pub pHeapSizeLimit: *const DeviceSize, - #[doc = " \\brief Pointers to Vulkan functions. Can be null."] - #[doc = ""] - #[doc = "For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions)."] - pub pVulkanFunctions: *const VmaVulkanFunctions, - #[doc = " \\brief Handle to Vulkan instance object."] - #[doc = ""] - #[doc = "Starting from version 3.0.0 this member is no longer optional, it must be set!"] - pub instance: Instance, - #[doc = " \\brief Optional. The highest version of Vulkan that the application is designed to use."] - #[doc = ""] - #[doc = "It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`."] - #[doc = "The patch version number specified is ignored. Only the major and minor versions are considered."] - #[doc = "It must be less or equal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`."] - #[doc = "Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation."] - #[doc = "Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`."] - pub vulkanApiVersion: u32, - #[doc = " \\brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type."] - #[doc = ""] - #[doc = "If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount`"] - #[doc = "elements, defining external memory handle types of particular Vulkan memory type,"] - #[doc = "to be passed using `VkExportMemoryAllocateInfoKHR`."] - #[doc = ""] - #[doc = "Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type."] - #[doc = "This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL."] - pub pTypeExternalMemoryHandleTypes: *const ExternalMemoryHandleTypeFlagsKHR, -} -#[doc = " Information about existing #VmaAllocator object."] -#[repr(C)] -pub struct VmaAllocatorInfo { - #[doc = " \\brief Handle to Vulkan instance object."] - #[doc = ""] - #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::instance."] - pub instance: Instance, - #[doc = " \\brief Handle to Vulkan physical device object."] - #[doc = ""] - #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice."] - pub physicalDevice: PhysicalDevice, - #[doc = " \\brief Handle to Vulkan device object."] - #[doc = ""] - #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::device."] - pub device: Device, -} -#[doc = " Calculated statistics of memory usage in entire allocator."] -#[repr(C)] -pub struct VmaStatInfo { - #[doc = " Number of `VkDeviceMemory` Vulkan memory blocks allocated."] - pub blockCount: u32, - #[doc = " Number of #VmaAllocation allocation objects allocated."] - pub allocationCount: u32, - #[doc = " Number of free ranges of memory between allocations."] - pub unusedRangeCount: u32, - #[doc = " Total number of bytes occupied by all allocations."] - pub usedBytes: DeviceSize, - #[doc = " Total number of bytes occupied by unused ranges."] - pub unusedBytes: DeviceSize, - pub allocationSizeMin: DeviceSize, - pub allocationSizeAvg: DeviceSize, - pub allocationSizeMax: DeviceSize, - pub unusedRangeSizeMin: DeviceSize, - pub unusedRangeSizeAvg: DeviceSize, - pub unusedRangeSizeMax: DeviceSize, -} -#[doc = " General statistics from current state of Allocator."] -#[repr(C)] -pub struct VmaStats { - pub memoryType: [VmaStatInfo; 32usize], - pub memoryHeap: [VmaStatInfo; 16usize], - pub total: VmaStatInfo, -} -#[doc = " Statistics of current memory usage and available budget, in bytes, for specific memory heap."] -#[repr(C)] -pub struct VmaBudget { - #[doc = " \\brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes."] - pub blockBytes: DeviceSize, - #[doc = " \\brief Sum size of all allocations created in particular heap, in bytes."] - #[doc = ""] - #[doc = "Usually less or equal than `blockBytes`."] - #[doc = "Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused -"] - #[doc = "available for new allocations or wasted due to fragmentation."] - pub allocationBytes: DeviceSize, - #[doc = " \\brief Estimated current memory usage of the program, in bytes."] - #[doc = ""] - #[doc = "Fetched from system using `VK_EXT_memory_budget` extension if enabled."] - #[doc = ""] - #[doc = "It might be different than `blockBytes` (usually higher) due to additional implicit objects"] - #[doc = "also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or"] - #[doc = "`VkDeviceMemory` blocks allocated outside of this library, if any."] - pub usage: DeviceSize, - #[doc = " \\brief Estimated amount of memory available to the program, in bytes."] - #[doc = ""] - #[doc = "Fetched from system using `VK_EXT_memory_budget` extension if enabled."] - #[doc = ""] - #[doc = "It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors"] - #[doc = "external to the program, like other programs also consuming system resources."] - #[doc = "Difference `budget - usage` is the amount of additional memory that can probably"] - #[doc = "be allocated without problems. Exceeding the budget may result in various problems."] - pub budget: DeviceSize, -} -#[doc = "\\addtogroup group_alloc"] -#[doc = "@{"] -#[repr(C)] -pub struct VmaAllocationCreateInfo { - #[doc = " Use #VmaAllocationCreateFlagBits enum."] - pub flags: VmaAllocationCreateFlags, - #[doc = " \\brief Intended usage of memory."] - #[doc = ""] - #[doc = "You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \\n"] - #[doc = "If `pool` is not null, this member is ignored."] - pub usage: VmaMemoryUsage, - #[doc = " \\brief Flags that must be set in a Memory Type chosen for an allocation."] - #[doc = ""] - #[doc = "Leave 0 if you specify memory requirements in other way. \\n"] - #[doc = "If `pool` is not null, this member is ignored."] - pub requiredFlags: MemoryPropertyFlags, - #[doc = " \\brief Flags that preferably should be set in a memory type chosen for an allocation."] - #[doc = ""] - #[doc = "Set to 0 if no additional flags are preferred. \\n"] - #[doc = "If `pool` is not null, this member is ignored."] - pub preferredFlags: MemoryPropertyFlags, - #[doc = " \\brief Bitmask containing one bit set for every memory type acceptable for this allocation."] - #[doc = ""] - #[doc = "Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if"] - #[doc = "it meets other requirements specified by this structure, with no further"] - #[doc = "restrictions on memory type index. \\n"] - #[doc = "If `pool` is not null, this member is ignored."] - pub memoryTypeBits: u32, - #[doc = " \\brief Pool that this allocation should be created in."] - #[doc = ""] - #[doc = "Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:"] - #[doc = "`usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored."] - pub pool: VmaPool, - #[doc = " \\brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData()."] - #[doc = ""] - #[doc = "If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either"] - #[doc = "null or pointer to a null-terminated string. The string will be then copied to"] - #[doc = "internal buffer, so it doesn't need to be valid after allocation call."] - pub pUserData: *mut ::std::os::raw::c_void, - #[doc = " \\brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations."] - #[doc = ""] - #[doc = "It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object"] - #[doc = "and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] - #[doc = "Otherwise, it has the priority of a memory block where it is placed and this variable is ignored."] - pub priority: f32, -} -#[doc = " Describes parameter of created #VmaPool."] -#[repr(C)] -pub struct VmaPoolCreateInfo { - #[doc = " \\brief Vulkan memory type index to allocate this pool from."] - pub memoryTypeIndex: u32, - #[doc = " \\brief Use combination of #VmaPoolCreateFlagBits."] - pub flags: VmaPoolCreateFlags, - #[doc = " \\brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional."] - #[doc = ""] - #[doc = "Specify nonzero to set explicit, constant size of memory blocks used by this"] - #[doc = "pool."] - #[doc = ""] - #[doc = "Leave 0 to use default and let the library manage block sizes automatically."] - #[doc = "Sizes of particular blocks may vary."] - #[doc = "In this case, the pool will also support dedicated allocations."] - pub blockSize: DeviceSize, - #[doc = " \\brief Minimum number of blocks to be always allocated in this pool, even if they stay empty."] - #[doc = ""] - #[doc = "Set to 0 to have no preallocated blocks and allow the pool be completely empty."] - pub minBlockCount: usize, - #[doc = " \\brief Maximum number of blocks that can be allocated in this pool. Optional."] - #[doc = ""] - #[doc = "Set to 0 to use default, which is `SIZE_MAX`, which means no limit."] - #[doc = ""] - #[doc = "Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated"] - #[doc = "throughout whole lifetime of this pool."] - pub maxBlockCount: usize, - #[doc = " \\brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations."] - #[doc = ""] - #[doc = "It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object."] - #[doc = "Otherwise, this variable is ignored."] - pub priority: f32, - #[doc = " \\brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0."] - #[doc = ""] - #[doc = "Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two."] - #[doc = "It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,"] - #[doc = "e.g. when doing interop with OpenGL."] - pub minAllocationAlignment: DeviceSize, - #[doc = " \\brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional."] - #[doc = ""] - #[doc = "Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`."] - #[doc = "It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`."] - #[doc = "Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool."] - #[doc = ""] - #[doc = "Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`,"] - #[doc = "can be attached automatically by this library when using other, more convenient of its features."] - pub pMemoryAllocateNext: *mut ::std::os::raw::c_void, -} -#[doc = " Describes parameter of existing #VmaPool."] -#[repr(C)] -pub struct VmaPoolStats { - #[doc = " \\brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes."] - pub size: DeviceSize, - #[doc = " \\brief Total number of bytes in the pool not used by any #VmaAllocation."] - pub unusedSize: DeviceSize, - #[doc = " \\brief Number of #VmaAllocation objects created from this pool that were not destroyed."] - pub allocationCount: usize, - #[doc = " \\brief Number of continuous memory ranges in the pool not used by any #VmaAllocation."] - pub unusedRangeCount: usize, - #[doc = " \\brief Number of `VkDeviceMemory` blocks allocated for this pool."] - pub blockCount: usize, -} -#[doc = " Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo()."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaAllocationInfo { - #[doc = " \\brief Memory type index that this allocation was allocated from."] - #[doc = ""] - #[doc = "It never changes."] - pub memoryType: u32, - #[doc = " \\brief Handle to Vulkan memory object."] - #[doc = ""] - #[doc = "Same memory object can be shared by multiple allocations."] - #[doc = ""] - #[doc = "It can change after call to vmaDefragment() if this allocation is passed to the function."] - pub deviceMemory: DeviceMemory, - #[doc = " \\brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation."] - #[doc = ""] - #[doc = "You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function"] - #[doc = "vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,"] - #[doc = "not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation"] - #[doc = "and apply this offset automatically."] - #[doc = ""] - #[doc = "It can change after call to vmaDefragment() if this allocation is passed to the function."] - pub offset: DeviceSize, - #[doc = " \\brief Size of this allocation, in bytes."] - #[doc = ""] - #[doc = "It never changes."] - #[doc = ""] - #[doc = "\\note Allocation size returned in this variable may be greater than the size"] - #[doc = "requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the"] - #[doc = "allocation is accessible for operations on memory e.g. using a pointer after"] - #[doc = "mapping with vmaMapMemory(), but operations on the resource e.g. using"] - #[doc = "`vkCmdCopyBuffer` must be limited to the size of the resource."] - pub size: DeviceSize, - #[doc = " \\brief Pointer to the beginning of this allocation as mapped data."] - #[doc = ""] - #[doc = "If the allocation hasn't been mapped using vmaMapMemory() and hasn't been"] - #[doc = "created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null."] - #[doc = ""] - #[doc = "It can change after call to vmaMapMemory(), vmaUnmapMemory()."] - #[doc = "It can also change after call to vmaDefragment() if this allocation is passed to the function."] - pub pMappedData: *mut ::std::os::raw::c_void, - #[doc = " \\brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData()."] - #[doc = ""] - #[doc = "It can change after call to vmaSetAllocationUserData() for this allocation."] - pub pUserData: *mut ::std::os::raw::c_void, -} -#[doc = " \\brief Parameters for defragmentation."] -#[doc = ""] -#[doc = "To be used with function vmaDefragmentationBegin()."] -#[repr(C)] -pub struct VmaDefragmentationInfo2 { - #[doc = " \\brief Reserved for future use. Should be 0."] - pub flags: VmaDefragmentationFlags, - #[doc = " \\brief Number of allocations in `pAllocations` array."] - pub allocationCount: u32, - #[doc = " \\brief Pointer to array of allocations that can be defragmented."] - #[doc = ""] - #[doc = "The array should have `allocationCount` elements."] - #[doc = "The array should not contain nulls."] - #[doc = "Elements in the array should be unique - same allocation cannot occur twice."] - #[doc = "All allocations not present in this array are considered non-moveable during this defragmentation."] - pub pAllocations: *mut VmaAllocation, - #[doc = " \\brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation."] - #[doc = ""] - #[doc = "The array should have `allocationCount` elements."] - #[doc = "You can pass null if you are not interested in this information."] - pub pAllocationsChanged: *mut Bool32, - #[doc = " \\brief Numer of pools in `pPools` array."] - pub poolCount: u32, - #[doc = " \\brief Either null or pointer to array of pools to be defragmented."] - #[doc = ""] - #[doc = "All the allocations in the specified pools can be moved during defragmentation"] - #[doc = "and there is no way to check if they were really moved as in `pAllocationsChanged`,"] - #[doc = "so you must query all the allocations in all these pools for new `VkDeviceMemory`"] - #[doc = "and offset using vmaGetAllocationInfo() if you might need to recreate buffers"] - #[doc = "and images bound to them."] - #[doc = ""] - #[doc = "The array should have `poolCount` elements."] - #[doc = "The array should not contain nulls."] - #[doc = "Elements in the array should be unique - same pool cannot occur twice."] - #[doc = ""] - #[doc = "Using this array is equivalent to specifying all allocations from the pools in `pAllocations`."] - #[doc = "It might be more efficient."] - pub pPools: *mut VmaPool, - #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`."] - #[doc = ""] - #[doc = "`VK_WHOLE_SIZE` means no limit."] - pub maxCpuBytesToMove: DeviceSize, - #[doc = " \\brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`."] - #[doc = ""] - #[doc = "`UINT32_MAX` means no limit."] - pub maxCpuAllocationsToMove: u32, - #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`."] - #[doc = ""] - #[doc = "`VK_WHOLE_SIZE` means no limit."] - pub maxGpuBytesToMove: DeviceSize, - #[doc = " \\brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`."] - #[doc = ""] - #[doc = "`UINT32_MAX` means no limit."] - pub maxGpuAllocationsToMove: u32, - #[doc = " \\brief Optional. Command buffer where GPU copy commands will be posted."] - #[doc = ""] - #[doc = "If not null, it must be a valid command buffer handle that supports Transfer queue type."] - #[doc = "It must be in the recording state and outside of a render pass instance."] - #[doc = "You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd()."] - #[doc = ""] - #[doc = "Passing null means that only CPU defragmentation will be performed."] - pub commandBuffer: CommandBuffer, -} -#[repr(C)] -pub struct VmaDefragmentationPassMoveInfo { - pub allocation: VmaAllocation, - pub memory: DeviceMemory, - pub offset: DeviceSize, -} -#[doc = " \\brief Parameters for incremental defragmentation steps."] -#[doc = ""] -#[doc = "To be used with function vmaBeginDefragmentationPass()."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaDefragmentationPassInfo { - pub moveCount: u32, - pub pMoves: *mut VmaDefragmentationPassMoveInfo, -} -#[doc = " \\brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment()."] -#[doc = ""] -#[doc = "\\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead."] -#[repr(C)] -pub struct VmaDefragmentationInfo { - #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places."] - #[doc = ""] - #[doc = "Default is `VK_WHOLE_SIZE`, which means no limit."] - pub maxBytesToMove: DeviceSize, - #[doc = " \\brief Maximum number of allocations that can be moved to different place."] - #[doc = ""] - #[doc = "Default is `UINT32_MAX`, which means no limit."] - pub maxAllocationsToMove: u32, -} -#[doc = " Statistics returned by function vmaDefragment()."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VmaDefragmentationStats { - #[doc = " Total number of bytes that have been copied while moving allocations to different places."] - pub bytesMoved: DeviceSize, - #[doc = " Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects."] - pub bytesFreed: DeviceSize, - #[doc = " Number of allocations that have been moved to different places."] - pub allocationsMoved: u32, - #[doc = " Number of empty `VkDeviceMemory` objects that have been released to the system."] - pub deviceMemoryBlocksFreed: u32, -} -#[doc = " Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock()."] -#[repr(C)] -pub struct VmaVirtualBlockCreateInfo { - #[doc = " \\brief Total size of the virtual block."] - #[doc = ""] - #[doc = "Sizes can be expressed in bytes or any units you want as long as you are consistent in using them."] - #[doc = "For example, if you allocate from some array of structures, 1 can mean single instance of entire structure."] - pub size: DeviceSize, - #[doc = " \\brief Use combination of #VmaVirtualBlockCreateFlagBits."] - pub flags: VmaVirtualBlockCreateFlags, - #[doc = " \\brief Custom CPU memory allocation callbacks. Optional."] - #[doc = ""] - #[doc = "Optional, can be null. When specified, they will be used for all CPU-side memory allocations."] - pub pAllocationCallbacks: *const AllocationCallbacks, -} -#[doc = " Parameters of created virtual allocation to be passed to vmaVirtualAllocate()."] -#[repr(C)] -pub struct VmaVirtualAllocationCreateInfo { - #[doc = " \\brief Size of the allocation."] - #[doc = ""] - #[doc = "Cannot be zero."] - pub size: DeviceSize, - #[doc = " \\brief Required alignment of the allocation. Optional."] - #[doc = ""] - #[doc = "Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset."] - pub alignment: DeviceSize, - #[doc = " \\brief Use combination of #VmaVirtualAllocationCreateFlagBits."] - pub flags: VmaVirtualAllocationCreateFlags, - #[doc = " \\brief Custom pointer to be associated with the allocation. Optional."] - #[doc = ""] - #[doc = "It can be any value and can be used for user-defined purposes. It can be fetched or changed later."] - pub pUserData: *mut ::std::os::raw::c_void, -} -#[doc = " Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo()."] -#[repr(C)] -pub struct VmaVirtualAllocationInfo { - #[doc = " \\brief Offset of the allocation."] - #[doc = ""] - #[doc = "Offset at which the allocation was made."] - pub offset: DeviceSize, - #[doc = " \\brief Size of the allocation."] - #[doc = ""] - #[doc = "Same value as passed in VmaVirtualAllocationCreateInfo::size."] - pub size: DeviceSize, - #[doc = " \\brief Custom pointer associated with the allocation."] - #[doc = ""] - #[doc = "Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData()."] - pub pUserData: *mut ::std::os::raw::c_void, -} -extern "C" { - #[doc = " Creates #VmaAllocator object."] - pub fn vmaCreateAllocator( - pCreateInfo: *const VmaAllocatorCreateInfo, - pAllocator: *mut VmaAllocator, - ) -> Result; -} -extern "C" { - #[doc = " Destroys allocator object."] - pub fn vmaDestroyAllocator(allocator: VmaAllocator); -} -extern "C" { - #[doc = " \\brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc."] - #[doc = ""] - #[doc = "It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to"] - #[doc = "`VkPhysicalDevice`, `VkDevice` etc. every time using this function."] - pub fn vmaGetAllocatorInfo(allocator: VmaAllocator, pAllocatorInfo: *mut VmaAllocatorInfo); -} -extern "C" { - #[doc = "PhysicalDeviceProperties are fetched from physicalDevice by the allocator."] - #[doc = "You can access it here, without fetching it again on your own."] - pub fn vmaGetPhysicalDeviceProperties( - allocator: VmaAllocator, - ppPhysicalDeviceProperties: *mut *const PhysicalDeviceProperties, - ); -} -extern "C" { - #[doc = "PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator."] - #[doc = "You can access it here, without fetching it again on your own."] - pub fn vmaGetMemoryProperties( - allocator: VmaAllocator, - ppPhysicalDeviceMemoryProperties: *mut *const PhysicalDeviceMemoryProperties, - ); -} -extern "C" { - #[doc = "\\brief Given Memory Type Index, returns Property Flags of this memory type."] - #[doc = ""] - #[doc = "This is just a convenience function. Same information can be obtained using"] - #[doc = "vmaGetMemoryProperties()."] - pub fn vmaGetMemoryTypeProperties( - allocator: VmaAllocator, - memoryTypeIndex: u32, - pFlags: *mut MemoryPropertyFlags, - ); -} -extern "C" { - #[doc = " \\brief Sets index of the current frame."] - pub fn vmaSetCurrentFrameIndex(allocator: VmaAllocator, frameIndex: u32); -} -extern "C" { - #[doc = " \\brief Retrieves statistics from current state of the Allocator."] - #[doc = ""] - #[doc = "This function is called \"calculate\" not \"get\" because it has to traverse all"] - #[doc = "internal data structures, so it may be quite slow. For faster but more brief statistics"] - #[doc = "suitable to be called every frame or every allocation, use vmaGetHeapBudgets()."] - #[doc = ""] - #[doc = "Note that when using allocator from multiple threads, returned information may immediately"] - #[doc = "become outdated."] - pub fn vmaCalculateStats(allocator: VmaAllocator, pStats: *mut VmaStats); -} -extern "C" { - #[doc = " \\brief Retrieves information about current memory budget for all memory heaps."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used."] - #[doc = ""] - #[doc = "This function is called \"get\" not \"calculate\" because it is very fast, suitable to be called"] - #[doc = "every frame or every allocation. For more detailed statistics use vmaCalculateStats()."] - #[doc = ""] - #[doc = "Note that when using allocator from multiple threads, returned information may immediately"] - #[doc = "become outdated."] - pub fn vmaGetHeapBudgets(allocator: VmaAllocator, pBudgets: *mut VmaBudget); -} -extern "C" { - #[doc = "\\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo."] - #[doc = ""] - #[doc = "This algorithm tries to find a memory type that:"] - #[doc = ""] - #[doc = "- Is allowed by memoryTypeBits."] - #[doc = "- Contains all the flags from pAllocationCreateInfo->requiredFlags."] - #[doc = "- Matches intended usage."] - #[doc = "- Has as many flags from pAllocationCreateInfo->preferredFlags as possible."] - #[doc = ""] - #[doc = "\\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result"] - #[doc = "from this function or any other allocating function probably means that your"] - #[doc = "device doesn't support any memory type with requested features for the specific"] - #[doc = "type of resource you want to use it for. Please check parameters of your"] - #[doc = "resource, like image layout (OPTIMAL versus LINEAR) or mip level count."] - pub fn vmaFindMemoryTypeIndex( - allocator: VmaAllocator, - memoryTypeBits: u32, - pAllocationCreateInfo: *const VmaAllocationCreateInfo, - pMemoryTypeIndex: *mut u32, - ) -> Result; -} -extern "C" { - #[doc = "\\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo."] - #[doc = ""] - #[doc = "It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex."] - #[doc = "It internally creates a temporary, dummy buffer that never has memory bound."] - #[doc = "It is just a convenience function, equivalent to calling:"] - #[doc = ""] - #[doc = "- `vkCreateBuffer`"] - #[doc = "- `vkGetBufferMemoryRequirements`"] - #[doc = "- `vmaFindMemoryTypeIndex`"] - #[doc = "- `vkDestroyBuffer`"] - pub fn vmaFindMemoryTypeIndexForBufferInfo( - allocator: VmaAllocator, - pBufferCreateInfo: *const BufferCreateInfo, - pAllocationCreateInfo: *const VmaAllocationCreateInfo, - pMemoryTypeIndex: *mut u32, - ) -> Result; -} -extern "C" { - #[doc = "\\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo."] - #[doc = ""] - #[doc = "It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex."] - #[doc = "It internally creates a temporary, dummy image that never has memory bound."] - #[doc = "It is just a convenience function, equivalent to calling:"] - #[doc = ""] - #[doc = "- `vkCreateImage`"] - #[doc = "- `vkGetImageMemoryRequirements`"] - #[doc = "- `vmaFindMemoryTypeIndex`"] - #[doc = "- `vkDestroyImage`"] - pub fn vmaFindMemoryTypeIndexForImageInfo( - allocator: VmaAllocator, - pImageCreateInfo: *const ImageCreateInfo, - pAllocationCreateInfo: *const VmaAllocationCreateInfo, - pMemoryTypeIndex: *mut u32, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Allocates Vulkan device memory and creates #VmaPool object."] - #[doc = ""] - #[doc = "\\param allocator Allocator object."] - #[doc = "\\param pCreateInfo Parameters of pool to create."] - #[doc = "\\param[out] pPool Handle to created pool."] - pub fn vmaCreatePool( - allocator: VmaAllocator, - pCreateInfo: *const VmaPoolCreateInfo, - pPool: *mut VmaPool, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Destroys #VmaPool object and frees Vulkan device memory."] - pub fn vmaDestroyPool(allocator: VmaAllocator, pool: VmaPool); -} -extern "C" { - #[doc = " \\brief Retrieves statistics of existing #VmaPool object."] - #[doc = ""] - #[doc = "\\param allocator Allocator object."] - #[doc = "\\param pool Pool object."] - #[doc = "\\param[out] pPoolStats Statistics of specified pool."] - pub fn vmaGetPoolStats(allocator: VmaAllocator, pool: VmaPool, pPoolStats: *mut VmaPoolStats); -} -extern "C" { - #[doc = " \\brief Checks magic number in margins around all allocations in given memory pool in search for corruptions."] - #[doc = ""] - #[doc = "Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,"] - #[doc = "`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is"] - #[doc = "`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection)."] - #[doc = ""] - #[doc = "Possible return values:"] - #[doc = ""] - #[doc = "- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool."] - #[doc = "- `VK_SUCCESS` - corruption detection has been performed and succeeded."] - #[doc = "- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations."] - #[doc = "`VMA_ASSERT` is also fired in that case."] - #[doc = "- Other value: Error returned by Vulkan, e.g. memory mapping failure."] - pub fn vmaCheckPoolCorruption(allocator: VmaAllocator, pool: VmaPool) -> Result; -} -extern "C" { - #[doc = " \\brief Retrieves name of a custom pool."] - #[doc = ""] - #[doc = "After the call `ppName` is either null or points to an internally-owned null-terminated string"] - #[doc = "containing name of the pool that was previously set. The pointer becomes invalid when the pool is"] - #[doc = "destroyed or its name is changed using vmaSetPoolName()."] - pub fn vmaGetPoolName( - allocator: VmaAllocator, - pool: VmaPool, - ppName: *mut *const ::std::os::raw::c_char, - ); -} -extern "C" { - #[doc = " \\brief Sets name of a custom pool."] - #[doc = ""] - #[doc = "`pName` can be either null or pointer to a null-terminated string with new name for the pool."] - #[doc = "Function makes internal copy of the string, so it can be changed or freed immediately after this call."] - pub fn vmaSetPoolName( - allocator: VmaAllocator, - pool: VmaPool, - pName: *const ::std::os::raw::c_char, - ); -} -extern "C" { - #[doc = " \\brief General purpose memory allocation."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param pVkMemoryRequirements"] - #[doc = "\\param pCreateInfo"] - #[doc = "\\param[out] pAllocation Handle to allocated memory."] - #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] - #[doc = ""] - #[doc = "You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages()."] - #[doc = ""] - #[doc = "It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(),"] - #[doc = "vmaCreateBuffer(), vmaCreateImage() instead whenever possible."] - pub fn vmaAllocateMemory( - allocator: VmaAllocator, - pVkMemoryRequirements: *const MemoryRequirements, - pCreateInfo: *const VmaAllocationCreateInfo, - pAllocation: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = " \\brief General purpose memory allocation for multiple allocation objects at once."] - #[doc = ""] - #[doc = "\\param allocator Allocator object."] - #[doc = "\\param pVkMemoryRequirements Memory requirements for each allocation."] - #[doc = "\\param pCreateInfo Creation parameters for each allocation."] - #[doc = "\\param allocationCount Number of allocations to make."] - #[doc = "\\param[out] pAllocations Pointer to array that will be filled with handles to created allocations."] - #[doc = "\\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations."] - #[doc = ""] - #[doc = "You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages()."] - #[doc = ""] - #[doc = "Word \"pages\" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding."] - #[doc = "It is just a general purpose allocation function able to make multiple allocations at once."] - #[doc = "It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times."] - #[doc = ""] - #[doc = "All allocations are made using same parameters. All of them are created out of the same memory pool and type."] - #[doc = "If any allocation fails, all allocations already made within this function call are also freed, so that when"] - #[doc = "returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`."] - pub fn vmaAllocateMemoryPages( - allocator: VmaAllocator, - pVkMemoryRequirements: *const MemoryRequirements, - pCreateInfo: *const VmaAllocationCreateInfo, - allocationCount: usize, - pAllocations: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = "\\param allocator"] - #[doc = "\\param buffer"] - #[doc = "\\param pCreateInfo"] - #[doc = "\\param[out] pAllocation Handle to allocated memory."] - #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] - #[doc = ""] - #[doc = "You should free the memory using vmaFreeMemory()."] - pub fn vmaAllocateMemoryForBuffer( - allocator: VmaAllocator, - buffer: Buffer, - pCreateInfo: *const VmaAllocationCreateInfo, - pAllocation: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = " Function similar to vmaAllocateMemoryForBuffer()."] - pub fn vmaAllocateMemoryForImage( - allocator: VmaAllocator, - image: Image, - pCreateInfo: *const VmaAllocationCreateInfo, - pAllocation: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage()."] - #[doc = ""] - #[doc = "Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped."] - pub fn vmaFreeMemory(allocator: VmaAllocator, allocation: VmaAllocation); -} -extern "C" { - #[doc = " \\brief Frees memory and destroys multiple allocations."] - #[doc = ""] - #[doc = "Word \"pages\" is just a suggestion to use this function to free pieces of memory used for sparse binding."] - #[doc = "It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(),"] - #[doc = "vmaAllocateMemoryPages() and other functions."] - #[doc = "It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times."] - #[doc = ""] - #[doc = "Allocations in `pAllocations` array can come from any memory pools and types."] - #[doc = "Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped."] - pub fn vmaFreeMemoryPages( - allocator: VmaAllocator, - allocationCount: usize, - pAllocations: *mut VmaAllocation, - ); -} -extern "C" { - #[doc = " \\brief Returns current information about specified allocation."] - #[doc = ""] - #[doc = "Current paramteres of given allocation are returned in `pAllocationInfo`."] - #[doc = ""] - #[doc = "Although this function doesn't lock any mutex, so it should be quite efficient,"] - #[doc = "you should avoid calling it too often."] - #[doc = "You can retrieve same VmaAllocationInfo structure while creating your resource, from function"] - #[doc = "vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change"] - #[doc = "(e.g. due to defragmentation)."] - pub fn vmaGetAllocationInfo( - allocator: VmaAllocator, - allocation: VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ); -} -extern "C" { - #[doc = " \\brief Sets pUserData in given allocation to new value."] - #[doc = ""] - #[doc = "If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,"] - #[doc = "pUserData must be either null, or pointer to a null-terminated string. The function"] - #[doc = "makes local copy of the string and sets it as allocation's `pUserData`. String"] - #[doc = "passed as pUserData doesn't need to be valid for whole lifetime of the allocation -"] - #[doc = "you can free it after this call. String previously pointed by allocation's"] - #[doc = "pUserData is freed from memory."] - #[doc = ""] - #[doc = "If the flag was not used, the value of pointer `pUserData` is just copied to"] - #[doc = "allocation's `pUserData`. It is opaque, so you can use it however you want - e.g."] - #[doc = "as a pointer, ordinal number or some handle to you own data."] - pub fn vmaSetAllocationUserData( - allocator: VmaAllocator, - allocation: VmaAllocation, - pUserData: *mut ::std::os::raw::c_void, - ); -} -extern "C" { - #[doc = "\\brief Given an allocation, returns Property Flags of its memory type."] - #[doc = ""] - #[doc = "This is just a convenience function. Same information can be obtained using"] - #[doc = "vmaGetAllocationInfo() + vmaGetMemoryProperties()."] - pub fn vmaGetAllocationMemoryProperties( - allocator: VmaAllocator, - allocation: VmaAllocation, - pFlags: *mut MemoryPropertyFlags, - ); -} -extern "C" { - #[doc = " \\brief Maps memory represented by given allocation and returns pointer to it."] - #[doc = ""] - #[doc = "Maps memory represented by given allocation to make it accessible to CPU code."] - #[doc = "When succeeded, `*ppData` contains pointer to first byte of this memory."] - #[doc = ""] - #[doc = "\\warning"] - #[doc = "If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is"] - #[doc = "correctly offsetted to the beginning of region assigned to this particular allocation."] - #[doc = "Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block."] - #[doc = "You should not add VmaAllocationInfo::offset to it!"] - #[doc = ""] - #[doc = "Mapping is internally reference-counted and synchronized, so despite raw Vulkan"] - #[doc = "function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`"] - #[doc = "multiple times simultaneously, it is safe to call this function on allocations"] - #[doc = "assigned to the same memory block. Actual Vulkan memory will be mapped on first"] - #[doc = "mapping and unmapped on last unmapping."] - #[doc = ""] - #[doc = "If the function succeeded, you must call vmaUnmapMemory() to unmap the"] - #[doc = "allocation when mapping is no longer needed or before freeing the allocation, at"] - #[doc = "the latest."] - #[doc = ""] - #[doc = "It also safe to call this function multiple times on the same allocation. You"] - #[doc = "must call vmaUnmapMemory() same number of times as you called vmaMapMemory()."] - #[doc = ""] - #[doc = "It is also safe to call this function on allocation created with"] - #[doc = "#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time."] - #[doc = "You must still call vmaUnmapMemory() same number of times as you called"] - #[doc = "vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the"] - #[doc = "\"0-th\" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag."] - #[doc = ""] - #[doc = "This function fails when used on allocation made in memory type that is not"] - #[doc = "`HOST_VISIBLE`."] - #[doc = ""] - #[doc = "This function doesn't automatically flush or invalidate caches."] - #[doc = "If the allocation is made from a memory types that is not `HOST_COHERENT`,"] - #[doc = "you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification."] - pub fn vmaMapMemory( - allocator: VmaAllocator, - allocation: VmaAllocation, - ppData: *mut *mut ::std::os::raw::c_void, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory()."] - #[doc = ""] - #[doc = "For details, see description of vmaMapMemory()."] - #[doc = ""] - #[doc = "This function doesn't automatically flush or invalidate caches."] - #[doc = "If the allocation is made from a memory types that is not `HOST_COHERENT`,"] - #[doc = "you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification."] - pub fn vmaUnmapMemory(allocator: VmaAllocator, allocation: VmaAllocation); -} -extern "C" { - #[doc = " \\brief Flushes memory of given allocation."] - #[doc = ""] - #[doc = "Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation."] - #[doc = "It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`."] - #[doc = "Unmap operation doesn't do that automatically."] - #[doc = ""] - #[doc = "- `offset` must be relative to the beginning of allocation."] - #[doc = "- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation."] - #[doc = "- `offset` and `size` don't have to be aligned."] - #[doc = "They are internally rounded down/up to multiply of `nonCoherentAtomSize`."] - #[doc = "- If `size` is 0, this call is ignored."] - #[doc = "- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,"] - #[doc = "this call is ignored."] - #[doc = ""] - #[doc = "Warning! `offset` and `size` are relative to the contents of given `allocation`."] - #[doc = "If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively."] - #[doc = "Do not pass allocation's offset as `offset`!!!"] - #[doc = ""] - #[doc = "This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is"] - #[doc = "called, otherwise `VK_SUCCESS`."] - pub fn vmaFlushAllocation( - allocator: VmaAllocator, - allocation: VmaAllocation, - offset: DeviceSize, - size: DeviceSize, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Invalidates memory of given allocation."] - #[doc = ""] - #[doc = "Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation."] - #[doc = "It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`."] - #[doc = "Map operation doesn't do that automatically."] - #[doc = ""] - #[doc = "- `offset` must be relative to the beginning of allocation."] - #[doc = "- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation."] - #[doc = "- `offset` and `size` don't have to be aligned."] - #[doc = "They are internally rounded down/up to multiply of `nonCoherentAtomSize`."] - #[doc = "- If `size` is 0, this call is ignored."] - #[doc = "- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,"] - #[doc = "this call is ignored."] - #[doc = ""] - #[doc = "Warning! `offset` and `size` are relative to the contents of given `allocation`."] - #[doc = "If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively."] - #[doc = "Do not pass allocation's offset as `offset`!!!"] - #[doc = ""] - #[doc = "This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if"] - #[doc = "it is called, otherwise `VK_SUCCESS`."] - pub fn vmaInvalidateAllocation( - allocator: VmaAllocator, - allocation: VmaAllocation, - offset: DeviceSize, - size: DeviceSize, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Flushes memory of given set of allocations."] - #[doc = ""] - #[doc = "Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations."] - #[doc = "For more information, see documentation of vmaFlushAllocation()."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param allocationCount"] - #[doc = "\\param allocations"] - #[doc = "\\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero."] - #[doc = "\\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations."] - #[doc = ""] - #[doc = "This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is"] - #[doc = "called, otherwise `VK_SUCCESS`."] - pub fn vmaFlushAllocations( - allocator: VmaAllocator, - allocationCount: u32, - allocations: *mut VmaAllocation, - offsets: *const DeviceSize, - sizes: *const DeviceSize, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Invalidates memory of given set of allocations."] - #[doc = ""] - #[doc = "Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations."] - #[doc = "For more information, see documentation of vmaInvalidateAllocation()."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param allocationCount"] - #[doc = "\\param allocations"] - #[doc = "\\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero."] - #[doc = "\\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations."] - #[doc = ""] - #[doc = "This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is"] - #[doc = "called, otherwise `VK_SUCCESS`."] - pub fn vmaInvalidateAllocations( - allocator: VmaAllocator, - allocationCount: u32, - allocations: *mut VmaAllocation, - offsets: *const DeviceSize, - sizes: *const DeviceSize, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked."] - #[doc = ""] - #[doc = "Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,"] - #[doc = "`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are"] - #[doc = "`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection)."] - #[doc = ""] - #[doc = "Possible return values:"] - #[doc = ""] - #[doc = "- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types."] - #[doc = "- `VK_SUCCESS` - corruption detection has been performed and succeeded."] - #[doc = "- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations."] - #[doc = "`VMA_ASSERT` is also fired in that case."] - #[doc = "- Other value: Error returned by Vulkan, e.g. memory mapping failure."] - pub fn vmaCheckCorruption(allocator: VmaAllocator, memoryTypeBits: u32) -> Result; -} -extern "C" { - #[doc = " \\brief Begins defragmentation process."] - #[doc = ""] - #[doc = "\\param allocator Allocator object."] - #[doc = "\\param pInfo Structure filled with parameters of defragmentation."] - #[doc = "\\param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information."] - #[doc = "\\param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation."] - #[doc = "\\return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error."] - #[doc = ""] - #[doc = "Use this function instead of old, deprecated vmaDefragment()."] - #[doc = ""] - #[doc = "Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():"] - #[doc = ""] - #[doc = "- You should not use any of allocations passed as `pInfo->pAllocations` or"] - #[doc = "any allocations that belong to pools passed as `pInfo->pPools`,"] - #[doc = "including calling vmaGetAllocationInfo(), or access"] - #[doc = "their data."] - #[doc = "- Some mutexes protecting internal data structures may be locked, so trying to"] - #[doc = "make or free any allocations, bind buffers or images, map memory, or launch"] - #[doc = "another simultaneous defragmentation in between may cause stall (when done on"] - #[doc = "another thread) or deadlock (when done on the same thread), unless you are"] - #[doc = "100% sure that defragmented allocations are in different pools."] - #[doc = "- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined."] - #[doc = "They become valid after call to vmaDefragmentationEnd()."] - #[doc = "- If `pInfo->commandBuffer` is not null, you must submit that command buffer"] - #[doc = "and make sure it finished execution before calling vmaDefragmentationEnd()."] - #[doc = ""] - #[doc = "For more information and important limitations regarding defragmentation, see documentation chapter:"] - #[doc = "[Defragmentation](@ref defragmentation)."] - pub fn vmaDefragmentationBegin( - allocator: VmaAllocator, - pInfo: *const VmaDefragmentationInfo2, - pStats: *mut VmaDefragmentationStats, - pContext: *mut VmaDefragmentationContext, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Ends defragmentation process."] - #[doc = ""] - #[doc = "Use this function to finish defragmentation started by vmaDefragmentationBegin()."] - #[doc = "It is safe to pass `context == null`. The function then does nothing."] - pub fn vmaDefragmentationEnd( - allocator: VmaAllocator, - context: VmaDefragmentationContext, - ) -> Result; -} -extern "C" { - pub fn vmaBeginDefragmentationPass( - allocator: VmaAllocator, - context: VmaDefragmentationContext, - pInfo: *mut VmaDefragmentationPassInfo, - ) -> Result; -} -extern "C" { - pub fn vmaEndDefragmentationPass( - allocator: VmaAllocator, - context: VmaDefragmentationContext, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Deprecated. Compacts memory by moving allocations."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param pAllocations Array of allocations that can be moved during this compation."] - #[doc = "\\param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays."] - #[doc = "\\param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information."] - #[doc = "\\param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values."] - #[doc = "\\param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information."] - #[doc = "\\return `VK_SUCCESS` if completed, negative error code in case of error."] - #[doc = ""] - #[doc = "\\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead."] - #[doc = ""] - #[doc = "This function works by moving allocations to different places (different"] - #[doc = "`VkDeviceMemory` objects and/or different offsets) in order to optimize memory"] - #[doc = "usage. Only allocations that are in `pAllocations` array can be moved. All other"] - #[doc = "allocations are considered nonmovable in this call. Basic rules:"] - #[doc = ""] - #[doc = "- Only allocations made in memory types that have"] - #[doc = "`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`"] - #[doc = "flags can be compacted. You may pass other allocations but it makes no sense -"] - #[doc = "these will never be moved."] - #[doc = "- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or"] - #[doc = "#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations"] - #[doc = "passed to this function that come from such pools are ignored."] - #[doc = "- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or"] - #[doc = "created as dedicated allocations for any other reason are also ignored."] - #[doc = "- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT"] - #[doc = "flag can be compacted. If not persistently mapped, memory will be mapped"] - #[doc = "temporarily inside this function if needed."] - #[doc = "- You must not pass same #VmaAllocation object multiple times in `pAllocations` array."] - #[doc = ""] - #[doc = "The function also frees empty `VkDeviceMemory` blocks."] - #[doc = ""] - #[doc = "Warning: This function may be time-consuming, so you shouldn't call it too often"] - #[doc = "(like after every resource creation/destruction)."] - #[doc = "You can call it on special occasions (like when reloading a game level or"] - #[doc = "when you just destroyed a lot of objects). Calling it every frame may be OK, but"] - #[doc = "you should measure that on your platform."] - #[doc = ""] - #[doc = "For more information, see [Defragmentation](@ref defragmentation) chapter."] - pub fn vmaDefragment( - allocator: VmaAllocator, - pAllocations: *mut VmaAllocation, - allocationCount: usize, - pAllocationsChanged: *mut Bool32, - pDefragmentationInfo: *const VmaDefragmentationInfo, - pDefragmentationStats: *mut VmaDefragmentationStats, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Binds buffer to allocation."] - #[doc = ""] - #[doc = "Binds specified buffer to region of memory represented by specified allocation."] - #[doc = "Gets `VkDeviceMemory` handle and offset from the allocation."] - #[doc = "If you want to create a buffer, allocate memory for it and bind them together separately,"] - #[doc = "you should use this function for binding instead of standard `vkBindBufferMemory()`,"] - #[doc = "because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple"] - #[doc = "allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously"] - #[doc = "(which is illegal in Vulkan)."] - #[doc = ""] - #[doc = "It is recommended to use function vmaCreateBuffer() instead of this one."] - pub fn vmaBindBufferMemory( - allocator: VmaAllocator, - allocation: VmaAllocation, - buffer: Buffer, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Binds buffer to allocation with additional parameters."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param allocation"] - #[doc = "\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0."] - #[doc = "\\param buffer"] - #[doc = "\\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null."] - #[doc = ""] - #[doc = "This function is similar to vmaBindBufferMemory(), but it provides additional parameters."] - #[doc = ""] - #[doc = "If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag"] - #[doc = "or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails."] - pub fn vmaBindBufferMemory2( - allocator: VmaAllocator, - allocation: VmaAllocation, - allocationLocalOffset: DeviceSize, - buffer: Buffer, - pNext: *const ::std::os::raw::c_void, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Binds image to allocation."] - #[doc = ""] - #[doc = "Binds specified image to region of memory represented by specified allocation."] - #[doc = "Gets `VkDeviceMemory` handle and offset from the allocation."] - #[doc = "If you want to create an image, allocate memory for it and bind them together separately,"] - #[doc = "you should use this function for binding instead of standard `vkBindImageMemory()`,"] - #[doc = "because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple"] - #[doc = "allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously"] - #[doc = "(which is illegal in Vulkan)."] - #[doc = ""] - #[doc = "It is recommended to use function vmaCreateImage() instead of this one."] - pub fn vmaBindImageMemory( - allocator: VmaAllocator, - allocation: VmaAllocation, - image: Image, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Binds image to allocation with additional parameters."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param allocation"] - #[doc = "\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0."] - #[doc = "\\param image"] - #[doc = "\\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null."] - #[doc = ""] - #[doc = "This function is similar to vmaBindImageMemory(), but it provides additional parameters."] - #[doc = ""] - #[doc = "If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag"] - #[doc = "or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails."] - pub fn vmaBindImageMemory2( - allocator: VmaAllocator, - allocation: VmaAllocation, - allocationLocalOffset: DeviceSize, - image: Image, - pNext: *const ::std::os::raw::c_void, - ) -> Result; -} -extern "C" { - #[doc = "\\param allocator"] - #[doc = "\\param pBufferCreateInfo"] - #[doc = "\\param pAllocationCreateInfo"] - #[doc = "\\param[out] pBuffer Buffer that was created."] - #[doc = "\\param[out] pAllocation Allocation that was created."] - #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] - #[doc = ""] - #[doc = "This function automatically:"] - #[doc = ""] - #[doc = "-# Creates buffer."] - #[doc = "-# Allocates appropriate memory for it."] - #[doc = "-# Binds the buffer with the memory."] - #[doc = ""] - #[doc = "If any of these operations fail, buffer and allocation are not created,"] - #[doc = "returned value is negative error code, *pBuffer and *pAllocation are null."] - #[doc = ""] - #[doc = "If the function succeeded, you must destroy both buffer and allocation when you"] - #[doc = "no longer need them using either convenience function vmaDestroyBuffer() or"] - #[doc = "separately, using `vkDestroyBuffer()` and vmaFreeMemory()."] - #[doc = ""] - #[doc = "If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,"] - #[doc = "VK_KHR_dedicated_allocation extension is used internally to query driver whether"] - #[doc = "it requires or prefers the new buffer to have dedicated allocation. If yes,"] - #[doc = "and if dedicated allocation is possible"] - #[doc = "(#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated"] - #[doc = "allocation for this buffer, just like when using"] - #[doc = "#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] - #[doc = ""] - #[doc = "\\note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer,"] - #[doc = "although recommended as a good practice, is out of scope of this library and could be implemented"] - #[doc = "by the user as a higher-level logic on top of VMA."] - pub fn vmaCreateBuffer( - allocator: VmaAllocator, - pBufferCreateInfo: *const BufferCreateInfo, - pAllocationCreateInfo: *const VmaAllocationCreateInfo, - pBuffer: *mut Buffer, - pAllocation: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Creates a buffer with additional minimum alignment."] - #[doc = ""] - #[doc = "Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom,"] - #[doc = "minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g."] - #[doc = "for interop with OpenGL."] - pub fn vmaCreateBufferWithAlignment( - allocator: VmaAllocator, - pBufferCreateInfo: *const BufferCreateInfo, - pAllocationCreateInfo: *const VmaAllocationCreateInfo, - minAlignment: DeviceSize, - pBuffer: *mut Buffer, - pAllocation: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Destroys Vulkan buffer and frees allocated memory."] - #[doc = ""] - #[doc = "This is just a convenience function equivalent to:"] - #[doc = ""] - #[doc = "\\code"] - #[doc = "vkDestroyBuffer(device, buffer, allocationCallbacks);"] - #[doc = "vmaFreeMemory(allocator, allocation);"] - #[doc = "\\endcode"] - #[doc = ""] - #[doc = "It it safe to pass null as buffer and/or allocation."] - pub fn vmaDestroyBuffer(allocator: VmaAllocator, buffer: Buffer, allocation: VmaAllocation); -} -extern "C" { - #[doc = " Function similar to vmaCreateBuffer()."] - pub fn vmaCreateImage( - allocator: VmaAllocator, - pImageCreateInfo: *const ImageCreateInfo, - pAllocationCreateInfo: *const VmaAllocationCreateInfo, - pImage: *mut Image, - pAllocation: *mut VmaAllocation, - pAllocationInfo: *mut VmaAllocationInfo, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Destroys Vulkan image and frees allocated memory."] - #[doc = ""] - #[doc = "This is just a convenience function equivalent to:"] - #[doc = ""] - #[doc = "\\code"] - #[doc = "vkDestroyImage(device, image, allocationCallbacks);"] - #[doc = "vmaFreeMemory(allocator, allocation);"] - #[doc = "\\endcode"] - #[doc = ""] - #[doc = "It it safe to pass null as image and/or allocation."] - pub fn vmaDestroyImage(allocator: VmaAllocator, image: Image, allocation: VmaAllocation); -} -extern "C" { - #[doc = " \\brief Creates new #VmaVirtualBlock object."] - #[doc = ""] - #[doc = "\\param pCreateInfo Parameters for creation."] - #[doc = "\\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed."] - pub fn vmaCreateVirtualBlock( - pCreateInfo: *const VmaVirtualBlockCreateInfo, - pVirtualBlock: *mut VmaVirtualBlock, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Destroys #VmaVirtualBlock object."] - #[doc = ""] - #[doc = "Please note that you should consciously handle virtual allocations that could remain unfreed in the block."] - #[doc = "You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock()"] - #[doc = "if you are sure this is what you want. If you do neither, an assert is called."] - #[doc = ""] - #[doc = "If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`,"] - #[doc = "don't forget to free them."] - pub fn vmaDestroyVirtualBlock(virtualBlock: VmaVirtualBlock); -} -extern "C" { - #[doc = " \\brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations."] - pub fn vmaIsVirtualBlockEmpty(virtualBlock: VmaVirtualBlock) -> Bool32; -} -extern "C" { - #[doc = " \\brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer."] - pub fn vmaGetVirtualAllocationInfo( - virtualBlock: VmaVirtualBlock, - allocation: VmaVirtualAllocation, - pVirtualAllocInfo: *mut VmaVirtualAllocationInfo, - ); -} -extern "C" { - #[doc = " \\brief Allocates new virtual allocation inside given #VmaVirtualBlock."] - #[doc = ""] - #[doc = "If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned"] - #[doc = "(despite the function doesn't ever allocate actual GPU memory)."] - #[doc = "`pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`."] - #[doc = ""] - #[doc = "\\param virtualBlock Virtual block"] - #[doc = "\\param pCreateInfo Parameters for the allocation"] - #[doc = "\\param[out] pAllocation Returned handle of the new allocation"] - #[doc = "\\param[out] pOffset Returned offset of the new allocation. Optional, can be null."] - pub fn vmaVirtualAllocate( - virtualBlock: VmaVirtualBlock, - pCreateInfo: *const VmaVirtualAllocationCreateInfo, - pAllocation: *mut VmaVirtualAllocation, - pOffset: *mut DeviceSize, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Frees virtual allocation inside given #VmaVirtualBlock."] - #[doc = ""] - #[doc = "It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing."] - pub fn vmaVirtualFree(virtualBlock: VmaVirtualBlock, allocation: VmaVirtualAllocation); -} -extern "C" { - #[doc = " \\brief Frees all virtual allocations inside given #VmaVirtualBlock."] - #[doc = ""] - #[doc = "You must either call this function or free each virtual allocation individually with vmaVirtualFree()"] - #[doc = "before destroying a virtual block. Otherwise, an assert is called."] - #[doc = ""] - #[doc = "If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`,"] - #[doc = "don't forget to free it as well."] - pub fn vmaClearVirtualBlock(virtualBlock: VmaVirtualBlock); -} -extern "C" { - #[doc = " \\brief Changes custom pointer associated with given virtual allocation."] - pub fn vmaSetVirtualAllocationUserData( - virtualBlock: VmaVirtualBlock, - allocation: VmaVirtualAllocation, - pUserData: *mut ::std::os::raw::c_void, - ); -} -extern "C" { - #[doc = " \\brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock."] - pub fn vmaCalculateVirtualBlockStats( - virtualBlock: VmaVirtualBlock, - pStatInfo: *mut VmaStatInfo, - ); -} -extern "C" { - #[doc = " \\brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock."] - #[doc = "\\param virtualBlock Virtual block."] - #[doc = "\\param[out] ppStatsString Returned string."] - #[doc = "\\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStats(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces."] - #[doc = ""] - #[doc = "Returned string must be freed using vmaFreeVirtualBlockStatsString()."] - pub fn vmaBuildVirtualBlockStatsString( - virtualBlock: VmaVirtualBlock, - ppStatsString: *mut *mut ::std::os::raw::c_char, - detailedMap: Bool32, - ); -} -extern "C" { - #[doc = " Frees a string returned by vmaBuildVirtualBlockStatsString()."] - pub fn vmaFreeVirtualBlockStatsString( - virtualBlock: VmaVirtualBlock, - pStatsString: *mut ::std::os::raw::c_char, - ); -} -extern "C" { - #[doc = " \\brief Builds and returns statistics as a null-terminated string in JSON format."] - #[doc = "\\param allocator"] - #[doc = "\\param[out] ppStatsString Must be freed using vmaFreeStatsString() function."] - #[doc = "\\param detailedMap"] - pub fn vmaBuildStatsString( - allocator: VmaAllocator, - ppStatsString: *mut *mut ::std::os::raw::c_char, - detailedMap: Bool32, - ); -} -extern "C" { - pub fn vmaFreeStatsString(allocator: VmaAllocator, pStatsString: *mut ::std::os::raw::c_char); -} diff --git a/src/definitions.rs b/src/definitions.rs index 0e69fcc..e5d1220 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -74,7 +74,7 @@ bitflags! { /// so you must guarantee they are used from only one thread at a time or synchronized /// externally by you. Using this flag may increase performance because internal /// mutexes are not used. - const EXTERNALLY_SYNCHRONIZED = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT; + const EXTERNALLY_SYNCHRONIZED = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT as u32; /// Enables usage of `VK_KHR_dedicated_allocation` extension. /// @@ -94,7 +94,7 @@ bitflags! { /// When this flag is set, you can experience following warnings reported by Vulkan /// validation layer. You can ignore them. /// `> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.` - const KHR_DEDICATED_ALLOCATION = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + const KHR_DEDICATED_ALLOCATION = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT as u32; /// Enables usage of VK_KHR_bind_memory2 extension. /// @@ -108,7 +108,7 @@ bitflags! { /// The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`, /// which allow to pass a chain of `pNext` structures while binding. /// This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2(). - const KHR_BIND_MEMORY2 = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT; + const KHR_BIND_MEMORY2 = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT as u32; /// Enables usage of VK_EXT_memory_budget extension. /// @@ -119,7 +119,7 @@ bitflags! { /// /// The extension provides query for current memory usage and budget, which will probably /// be more accurate than an estimation used by the library otherwise. - const EXT_MEMORY_BUDGET = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; + const EXT_MEMORY_BUDGET = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT as u32; /// Enables usage of VK_AMD_device_coherent_memory extension. /// @@ -136,7 +136,7 @@ bitflags! { /// When the extension is not enabled, such memory types are still enumerated, but their usage is illegal. /// To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type, /// returning `VK_ERROR_FEATURE_NOT_PRESENT`. - const AMD_DEVICE_COHERENT_MEMORY = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT; + const AMD_DEVICE_COHERENT_MEMORY = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT as u32; /// You may set this flag only if you: /// @@ -150,7 +150,7 @@ bitflags! { /// allocated memory blocks wherever it might be needed. /// /// For more information, see documentation chapter \ref enabling_buffer_device_address. - const BUFFER_DEVICE_ADDRESS = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + const BUFFER_DEVICE_ADDRESS = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT as u32; /// Enables usage of VK_EXT_memory_priority extension in the library. /// @@ -166,7 +166,7 @@ bitflags! { /// It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`. /// The value to be used for default priority is 0.5. /// For more details, see the documentation of the VK_EXT_memory_priority extension. - const EXT_MEMORY_PRIORITY = ffi::VmaAllocatorCreateFlagBits_VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT; + const EXT_MEMORY_PRIORITY = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT as u32; } } @@ -288,7 +288,7 @@ bitflags! { /// buffers and linear images or only optimal images out of this pool, use this flag /// to make allocator disregard buffer-image granularity and so make allocations /// faster and more optimal. - const IGNORE_BUFFER_IMAGE_GRANULARITY = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT; + const IGNORE_BUFFER_IMAGE_GRANULARITY = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT as u32; /// Enables alternative, linear allocation algorithm in this pool. /// @@ -301,7 +301,7 @@ bitflags! { /// ring buffer, and double stack. /// /// When using this flag, you must specify PoolCreateInfo::max_block_count == 1 (or 0 for default). - const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT; + const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT as u32; /// Enables alternative, buddy allocation algorithm in this pool. /// @@ -309,7 +309,7 @@ bitflags! { /// a half of its parent's size. Comparing to default algorithm, this one provides /// faster allocation and deallocation and decreased external fragmentation, /// at the expense of more memory wasted (internal fragmentation). - const BUDDY_ALGORITHM = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT; + const BUDDY_ALGORITHM = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT as u32; /// \brief Enables alternative, Two-Level Segregated Fit (TLSF) allocation algorithm in this pool. /// @@ -320,10 +320,10 @@ bitflags! { /// Allocation time can be sometimes slightly longer than compared to other algorithms /// but in return the application can avoid stalls in case of fragmentation, giving /// predictable results, suitable for real-time use cases. - const TLSF_ALGORITHM_BIT = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_TLSF_ALGORITHM_BIT; + const TLSF_ALGORITHM_BIT = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_TLSF_ALGORITHM_BIT as u32; /// Bit mask to extract only `*_ALGORITHM` bits from entire set of flags. - const ALGORITHM_MASK = ffi::VmaPoolCreateFlagBits_VMA_POOL_CREATE_ALGORITHM_MASK; + const ALGORITHM_MASK = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_ALGORITHM_MASK as u32; } } @@ -485,7 +485,7 @@ impl<'a> AllocationCreateInfo<'a> { AllocationCreateInfo { inner: VmaAllocationCreateInfo { flags: 0, - usage: 0, + usage: ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN, requiredFlags: Default::default(), preferredFlags: Default::default(), memoryTypeBits: 0, @@ -504,12 +504,12 @@ impl<'a> AllocationCreateInfo<'a> { pub fn usage(mut self, usage: MemoryUsage) -> Self { self.inner.usage = match usage { - MemoryUsage::Unknown => ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_UNKNOWN, - MemoryUsage::GpuOnly => ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_ONLY, - MemoryUsage::CpuOnly => ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_ONLY, - MemoryUsage::CpuToGpu => ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_CPU_TO_GPU, - MemoryUsage::GpuToCpu => ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_TO_CPU, - MemoryUsage::GpuLazy => ffi::VmaMemoryUsage_VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED, + MemoryUsage::Unknown => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN, + MemoryUsage::GpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_ONLY, + MemoryUsage::CpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_ONLY, + MemoryUsage::CpuToGpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU, + MemoryUsage::GpuToCpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_TO_CPU, + MemoryUsage::GpuLazy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED, }; self } diff --git a/src/ffi.rs b/src/ffi.rs index 8221e8c..0e28be4 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -1,6 +1,1857 @@ -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![cfg_attr(feature = "cargo-clippy", allow(clippy::unreadable_literal))] - -include!("../gen/bindings.rs"); +/* automatically generated by rust-bindgen 0.59.2 */ + +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use ash::vk::*; + +#[repr(i32)] +#[doc = " Flags for created #VmaAllocator."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaAllocatorCreateFlagBits { + #[doc = " \\brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you."] + #[doc = ""] + #[doc = "Using this flag may increase performance because internal mutexes are not used."] + VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 1, + #[doc = " \\brief Enables usage of VK_KHR_dedicated_allocation extension."] + #[doc = ""] + #[doc = "The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`."] + #[doc = "When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1."] + #[doc = ""] + #[doc = "Using this extension will automatically allocate dedicated blocks of memory for"] + #[doc = "some buffers and images instead of suballocating place for them out of bigger"] + #[doc = "memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT"] + #[doc = "flag) when it is recommended by the driver. It may improve performance on some"] + #[doc = "GPUs."] + #[doc = ""] + #[doc = "You may set this flag only if you found out that following device extensions are"] + #[doc = "supported, you enabled them while creating Vulkan device passed as"] + #[doc = "VmaAllocatorCreateInfo::device, and you want them to be used internally by this"] + #[doc = "library:"] + #[doc = ""] + #[doc = "- VK_KHR_get_memory_requirements2 (device extension)"] + #[doc = "- VK_KHR_dedicated_allocation (device extension)"] + #[doc = ""] + #[doc = "When this flag is set, you can experience following warnings reported by Vulkan"] + #[doc = "validation layer. You can ignore them."] + #[doc = ""] + #[doc = "> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer."] + VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 2, + #[doc = "Enables usage of VK_KHR_bind_memory2 extension."] + #[doc = ""] + #[doc = "The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`."] + #[doc = "When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1."] + #[doc = ""] + #[doc = "You may set this flag only if you found out that this device extension is supported,"] + #[doc = "you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,"] + #[doc = "and you want it to be used internally by this library."] + #[doc = ""] + #[doc = "The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,"] + #[doc = "which allow to pass a chain of `pNext` structures while binding."] + #[doc = "This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2()."] + VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 4, + #[doc = "Enables usage of VK_EXT_memory_budget extension."] + #[doc = ""] + #[doc = "You may set this flag only if you found out that this device extension is supported,"] + #[doc = "you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,"] + #[doc = "and you want it to be used internally by this library, along with another instance extension"] + #[doc = "VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted)."] + #[doc = ""] + #[doc = "The extension provides query for current memory usage and budget, which will probably"] + #[doc = "be more accurate than an estimation used by the library otherwise."] + VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 8, + #[doc = "Enables usage of VK_AMD_device_coherent_memory extension."] + #[doc = ""] + #[doc = "You may set this flag only if you:"] + #[doc = ""] + #[doc = "- found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,"] + #[doc = "- checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device,"] + #[doc = "- want it to be used internally by this library."] + #[doc = ""] + #[doc = "The extension and accompanying device feature provide access to memory types with"] + #[doc = "`VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags."] + #[doc = "They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR."] + #[doc = ""] + #[doc = "When the extension is not enabled, such memory types are still enumerated, but their usage is illegal."] + #[doc = "To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type,"] + #[doc = "returning `VK_ERROR_FEATURE_NOT_PRESENT`."] + VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 16, + #[doc = "Enables usage of \"buffer device address\" feature, which allows you to use function"] + #[doc = "`vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader."] + #[doc = ""] + #[doc = "You may set this flag only if you:"] + #[doc = ""] + #[doc = "1. (For Vulkan version < 1.2) Found as available and enabled device extension"] + #[doc = "VK_KHR_buffer_device_address."] + #[doc = "This extension is promoted to core Vulkan 1.2."] + #[doc = "2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`."] + #[doc = ""] + #[doc = "When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA."] + #[doc = "The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to"] + #[doc = "allocated memory blocks wherever it might be needed."] + #[doc = ""] + #[doc = "For more information, see documentation chapter \\ref enabling_buffer_device_address."] + VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 32, + #[doc = "Enables usage of VK_EXT_memory_priority extension in the library."] + #[doc = ""] + #[doc = "You may set this flag only if you found available and enabled this device extension,"] + #[doc = "along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,"] + #[doc = "while creating Vulkan device passed as VmaAllocatorCreateInfo::device."] + #[doc = ""] + #[doc = "When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority"] + #[doc = "are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored."] + #[doc = ""] + #[doc = "A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations."] + #[doc = "Larger values are higher priority. The granularity of the priorities is implementation-dependent."] + #[doc = "It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`."] + #[doc = "The value to be used for default priority is 0.5."] + #[doc = "For more details, see the documentation of the VK_EXT_memory_priority extension."] + VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT = 64, + #[doc = "Enables usage of VK_EXT_memory_priority extension in the library."] + #[doc = ""] + #[doc = "You may set this flag only if you found available and enabled this device extension,"] + #[doc = "along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,"] + #[doc = "while creating Vulkan device passed as VmaAllocatorCreateInfo::device."] + #[doc = ""] + #[doc = "When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority"] + #[doc = "are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored."] + #[doc = ""] + #[doc = "A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations."] + #[doc = "Larger values are higher priority. The granularity of the priorities is implementation-dependent."] + #[doc = "It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`."] + #[doc = "The value to be used for default priority is 0.5."] + #[doc = "For more details, see the documentation of the VK_EXT_memory_priority extension."] + VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, +} +pub type VmaAllocatorCreateFlags = Flags; +#[repr(i32)] +#[doc = " \\brief Intended usage of the allocated memory."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaMemoryUsage { + #[doc = " No intended memory usage specified."] + #[doc = "Use other members of VmaAllocationCreateInfo to specify your requirements."] + VMA_MEMORY_USAGE_UNKNOWN = 0, + #[doc = " Memory will be used on device only, so fast access from the device is preferred."] + #[doc = "It usually means device-local GPU (video) memory."] + #[doc = "No need to be mappable on host."] + #[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`."] + #[doc = ""] + #[doc = "Usage:"] + #[doc = ""] + #[doc = "- Resources written and read by device, e.g. images used as attachments."] + #[doc = "- Resources transferred from host once (immutable) or infrequently and read by"] + #[doc = "device multiple times, e.g. textures to be sampled, vertex buffers, uniform"] + #[doc = "(constant) buffers, and majority of other types of resources used on GPU."] + #[doc = ""] + #[doc = "Allocation may still end up in `HOST_VISIBLE` memory on some implementations."] + #[doc = "In such case, you are free to map it."] + #[doc = "You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type."] + VMA_MEMORY_USAGE_GPU_ONLY = 1, + #[doc = " Memory will be mappable on host."] + #[doc = "It usually means CPU (system) memory."] + #[doc = "Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`."] + #[doc = "CPU access is typically uncached. Writes may be write-combined."] + #[doc = "Resources created in this pool may still be accessible to the device, but access to them can be slow."] + #[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`."] + #[doc = ""] + #[doc = "Usage: Staging copy of resources used as transfer source."] + VMA_MEMORY_USAGE_CPU_ONLY = 2, + #[doc = "Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU."] + #[doc = "CPU access is typically uncached. Writes may be write-combined."] + #[doc = ""] + #[doc = "Usage: Resources written frequently by host (dynamic), read by device. E.g. textures (with LINEAR layout), vertex buffers, uniform buffers updated every frame or every draw call."] + VMA_MEMORY_USAGE_CPU_TO_GPU = 3, + #[doc = " Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached."] + #[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`."] + #[doc = ""] + #[doc = "Usage:"] + #[doc = ""] + #[doc = "- Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping."] + #[doc = "- Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection."] + VMA_MEMORY_USAGE_GPU_TO_CPU = 4, + #[doc = " CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`."] + #[doc = ""] + #[doc = "Usage: Staging copy of resources moved from GPU memory to CPU memory as part"] + #[doc = "of custom paging/residency mechanism, to be moved back to GPU memory when needed."] + VMA_MEMORY_USAGE_CPU_COPY = 5, + #[doc = " Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] + #[doc = "Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation."] + #[doc = ""] + #[doc = "Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`."] + #[doc = ""] + #[doc = "Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] + VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, + #[doc = " Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] + #[doc = "Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation."] + #[doc = ""] + #[doc = "Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`."] + #[doc = ""] + #[doc = "Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] + VMA_MEMORY_USAGE_MAX_ENUM = 2147483647, +} +impl VmaAllocationCreateFlagBits { + pub const VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT: VmaAllocationCreateFlagBits = + VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT; +} +impl VmaAllocationCreateFlagBits { + pub const VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT: VmaAllocationCreateFlagBits = + VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT; +} +#[repr(i32)] +#[doc = " Flags to be passed as VmaAllocationCreateInfo::flags."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaAllocationCreateFlagBits { + #[doc = " \\brief Set this flag if the allocation should have its own memory block."] + #[doc = ""] + #[doc = "Use it for special, big resources, like fullscreen images used as attachments."] + VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 1, + #[doc = " \\brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block."] + #[doc = ""] + #[doc = "If new allocation cannot be placed in any of the existing blocks, allocation"] + #[doc = "fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error."] + #[doc = ""] + #[doc = "You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and"] + #[doc = "#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense."] + #[doc = ""] + #[doc = "If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored."] + VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 2, + #[doc = " \\brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it."] + #[doc = ""] + #[doc = "Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData."] + #[doc = ""] + #[doc = "It is valid to use this flag for allocation made from memory type that is not"] + #[doc = "`HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is"] + #[doc = "useful if you need an allocation that is efficient to use on GPU"] + #[doc = "(`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that"] + #[doc = "support it (e.g. Intel GPU)."] + VMA_ALLOCATION_CREATE_MAPPED_BIT = 4, + #[doc = " \\deprecated Removed. Do not use."] + VMA_ALLOCATION_CREATE_RESERVED_1_BIT = 8, + #[doc = " \\deprecated Removed. Do not use."] + VMA_ALLOCATION_CREATE_RESERVED_2_BIT = 16, + #[doc = " Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a"] + #[doc = "null-terminated string. Instead of copying pointer value, a local copy of the"] + #[doc = "string is made and stored in allocation's `pUserData`. The string is automatically"] + #[doc = "freed together with the allocation. It is also used in vmaBuildStatsString()."] + VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 32, + #[doc = " Allocation will be created from upper stack in a double stack pool."] + #[doc = ""] + #[doc = "This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag."] + VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 64, + #[doc = " Create both buffer/image and allocation, but don't bind them together."] + #[doc = "It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions."] + #[doc = "The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage()."] + #[doc = "Otherwise it is ignored."] + VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 128, + #[doc = " Create allocation only if additional device memory required for it, if any, won't exceed"] + #[doc = "memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`."] + VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 256, + #[doc = " \\brief Set this flag if the allocated memory will have aliasing resources."] + #[doc = ""] + #[doc = "Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified."] + #[doc = "Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors."] + VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 512, + #[doc = " Allocation strategy that chooses smallest possible free range for the allocation"] + #[doc = "to minimize memory usage and fragmentation, possibly at the expense of allocation time."] + VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 65536, + #[doc = " Allocation strategy that chooses first suitable free range for the allocation -"] + #[doc = "not necessarily in terms of the smallest offset but the one that is easiest and fastest to find"] + #[doc = "to minimize allocation time, possibly at the expense of allocation quality."] + VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 131072, + #[doc = " A bit mask to extract only `STRATEGY` bits from entire set of flags."] + VMA_ALLOCATION_CREATE_STRATEGY_MASK = 196608, + #[doc = " A bit mask to extract only `STRATEGY` bits from entire set of flags."] + VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, +} +pub type VmaAllocationCreateFlags = Flags; +#[repr(i32)] +#[doc = " Flags to be passed as VmaPoolCreateInfo::flags."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaPoolCreateFlagBits { + #[doc = " \\brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored."] + #[doc = ""] + #[doc = "This is an optional optimization flag."] + #[doc = ""] + #[doc = "If you always allocate using vmaCreateBuffer(), vmaCreateImage(),"] + #[doc = "vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator"] + #[doc = "knows exact type of your allocations so it can handle Buffer-Image Granularity"] + #[doc = "in the optimal way."] + #[doc = ""] + #[doc = "If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),"] + #[doc = "exact type of such allocations is not known, so allocator must be conservative"] + #[doc = "in handling Buffer-Image Granularity, which can lead to suboptimal allocation"] + #[doc = "(wasted memory). In that case, if you can make sure you always allocate only"] + #[doc = "buffers and linear images or only optimal images out of this pool, use this flag"] + #[doc = "to make allocator disregard Buffer-Image Granularity and so make allocations"] + #[doc = "faster and more optimal."] + VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 2, + #[doc = " \\brief Enables alternative, linear allocation algorithm in this pool."] + #[doc = ""] + #[doc = "Specify this flag to enable linear allocation algorithm, which always creates"] + #[doc = "new allocations after last one and doesn't reuse space from allocations freed in"] + #[doc = "between. It trades memory consumption for simplified algorithm and data"] + #[doc = "structure, which has better performance and uses less memory for metadata."] + #[doc = ""] + #[doc = "By using this flag, you can achieve behavior of free-at-once, stack,"] + #[doc = "ring buffer, and double stack."] + #[doc = "For details, see documentation chapter \\ref linear_algorithm."] + VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 4, + #[doc = " \\brief Enables alternative, buddy allocation algorithm in this pool."] + #[doc = ""] + #[doc = "It operates on a tree of blocks, each having size that is a power of two and"] + #[doc = "a half of its parent's size. Comparing to default algorithm, this one provides"] + #[doc = "faster allocation and deallocation and decreased external fragmentation,"] + #[doc = "at the expense of more memory wasted (internal fragmentation)."] + #[doc = "For details, see documentation chapter \\ref buddy_algorithm."] + VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 8, + #[doc = " \\brief Enables alternative, Two-Level Segregated Fit (TLSF) allocation algorithm in this pool."] + #[doc = ""] + #[doc = "This algorithm is based on 2-level lists dividing address space into smaller"] + #[doc = "chunks. The first level is aligned to power of two which serves as buckets for requested"] + #[doc = "memory to fall into, and the second level is lineary subdivided into lists of free memory."] + #[doc = "This algorithm aims to achieve bounded response time even in the worst case scenario."] + #[doc = "Allocation time can be sometimes slightly longer than compared to other algorithms"] + #[doc = "but in return the application can avoid stalls in case of fragmentation, giving"] + #[doc = "predictable results, suitable for real-time use cases."] + VMA_POOL_CREATE_TLSF_ALGORITHM_BIT = 16, + #[doc = " Bit mask to extract only `ALGORITHM` bits from entire set of flags."] + VMA_POOL_CREATE_ALGORITHM_MASK = 28, + #[doc = " Bit mask to extract only `ALGORITHM` bits from entire set of flags."] + VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, +} +#[doc = " Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits."] +pub type VmaPoolCreateFlags = Flags; +#[repr(i32)] +#[doc = " Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaDefragmentationFlagBits { + VMA_DEFRAGMENTATION_FLAG_INCREMENTAL = 1, + VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 2147483647, +} +pub type VmaDefragmentationFlags = Flags; +#[repr(i32)] +#[doc = " Flags to be passed as VmaVirtualBlockCreateInfo::flags."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaVirtualBlockCreateFlagBits { + #[doc = " \\brief Enables alternative, linear allocation algorithm in this virtual block."] + #[doc = ""] + #[doc = "Specify this flag to enable linear allocation algorithm, which always creates"] + #[doc = "new allocations after last one and doesn't reuse space from allocations freed in"] + #[doc = "between. It trades memory consumption for simplified algorithm and data"] + #[doc = "structure, which has better performance and uses less memory for metadata."] + #[doc = ""] + #[doc = "By using this flag, you can achieve behavior of free-at-once, stack,"] + #[doc = "ring buffer, and double stack."] + #[doc = "For details, see documentation chapter \\ref linear_algorithm."] + VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 1, + #[doc = " \\brief Enables alternative, buddy allocation algorithm in this virtual block."] + #[doc = ""] + #[doc = "It operates on a tree of blocks, each having size that is a power of two and"] + #[doc = "a half of its parent's size. Comparing to default algorithm, this one provides"] + #[doc = "faster allocation and deallocation and decreased external fragmentation,"] + #[doc = "at the expense of more memory wasted (internal fragmentation)."] + #[doc = "For details, see documentation chapter \\ref buddy_algorithm."] + VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT = 2, + #[doc = " \\brief Enables alternative, TLSF allocation algorithm in virtual block."] + #[doc = ""] + #[doc = "This algorithm is based on 2-level lists dividing address space into smaller"] + #[doc = "chunks. The first level is aligned to power of two which serves as buckets for requested"] + #[doc = "memory to fall into, and the second level is lineary subdivided into lists of free memory."] + #[doc = "This algorithm aims to achieve bounded response time even in the worst case scenario."] + #[doc = "Allocation time can be sometimes slightly longer than compared to other algorithms"] + #[doc = "but in return the application can avoid stalls in case of fragmentation, giving"] + #[doc = "predictable results, suitable for real-time use cases."] + VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT = 4, + #[doc = " \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags."] + VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK = 7, + #[doc = " \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags."] + VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, +} +#[doc = " Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits."] +pub type VmaVirtualBlockCreateFlags = Flags; +#[repr(i32)] +#[doc = " Flags to be passed as VmaVirtualAllocationCreateInfo::flags."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaVirtualAllocationCreateFlagBits { + #[doc = " \\brief Allocation will be created from upper stack in a double stack pool."] + #[doc = ""] + #[doc = "This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag."] + VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 64, + #[doc = " \\brief Allocation strategy that tries to minimize memory usage."] + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 65536, + #[doc = " \\brief Allocation strategy that tries to minimize allocation time."] + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 131072, + #[doc = " \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags."] + #[doc = ""] + #[doc = "These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits."] + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = 196608, + #[doc = " \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags."] + #[doc = ""] + #[doc = "These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits."] + VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, +} +#[doc = " Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits."] +pub type VmaVirtualAllocationCreateFlags = Flags; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaAllocator_T { + _unused: [u8; 0], +} +pub type VmaAllocator = *mut VmaAllocator_T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaPool_T { + _unused: [u8; 0], +} +pub type VmaPool = *mut VmaPool_T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaAllocation_T { + _unused: [u8; 0], +} +pub type VmaAllocation = *mut VmaAllocation_T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaDefragmentationContext_T { + _unused: [u8; 0], +} +pub type VmaDefragmentationContext = *mut VmaDefragmentationContext_T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaVirtualAllocation_T { + _unused: [u8; 0], +} +pub type VmaVirtualAllocation = *mut VmaVirtualAllocation_T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaVirtualBlock_T { + _unused: [u8; 0], +} +pub type VmaVirtualBlock = *mut VmaVirtualBlock_T; +#[doc = " Callback function called after successful vkAllocateMemory."] +pub type PFN_vmaAllocateDeviceMemoryFunction = ::std::option::Option< + unsafe extern "C" fn( + allocator: VmaAllocator, + memoryType: u32, + memory: DeviceMemory, + size: DeviceSize, + pUserData: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " Callback function called before vkFreeMemory."] +pub type PFN_vmaFreeDeviceMemoryFunction = ::std::option::Option< + unsafe extern "C" fn( + allocator: VmaAllocator, + memoryType: u32, + memory: DeviceMemory, + size: DeviceSize, + pUserData: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " \\brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`."] +#[doc = ""] +#[doc = "Provided for informative purpose, e.g. to gather statistics about number of"] +#[doc = "allocations or total amount of memory allocated in Vulkan."] +#[doc = ""] +#[doc = "Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaDeviceMemoryCallbacks { + #[doc = " Optional, can be null."] + pub pfnAllocate: PFN_vmaAllocateDeviceMemoryFunction, + #[doc = " Optional, can be null."] + pub pfnFree: PFN_vmaFreeDeviceMemoryFunction, + #[doc = " Optional, can be null."] + pub pUserData: *mut ::std::os::raw::c_void, +} +#[doc = " \\brief Pointers to some Vulkan functions - a subset used by the library."] +#[doc = ""] +#[doc = "Used in VmaAllocatorCreateInfo::pVulkanFunctions."] +#[repr(C)] +pub struct VmaVulkanFunctions { + #[doc = " Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS."] + pub vkGetInstanceProcAddr: PFN_vkGetInstanceProcAddr, + #[doc = " Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS."] + pub vkGetDeviceProcAddr: PFN_vkGetDeviceProcAddr, + pub vkGetPhysicalDeviceProperties: PFN_vkGetPhysicalDeviceProperties, + pub vkGetPhysicalDeviceMemoryProperties: PFN_vkGetPhysicalDeviceMemoryProperties, + pub vkAllocateMemory: PFN_vkAllocateMemory, + pub vkFreeMemory: PFN_vkFreeMemory, + pub vkMapMemory: PFN_vkMapMemory, + pub vkUnmapMemory: PFN_vkUnmapMemory, + pub vkFlushMappedMemoryRanges: PFN_vkFlushMappedMemoryRanges, + pub vkInvalidateMappedMemoryRanges: PFN_vkInvalidateMappedMemoryRanges, + pub vkBindBufferMemory: PFN_vkBindBufferMemory, + pub vkBindImageMemory: PFN_vkBindImageMemory, + pub vkGetBufferMemoryRequirements: PFN_vkGetBufferMemoryRequirements, + pub vkGetImageMemoryRequirements: PFN_vkGetImageMemoryRequirements, + pub vkCreateBuffer: PFN_vkCreateBuffer, + pub vkDestroyBuffer: PFN_vkDestroyBuffer, + pub vkCreateImage: PFN_vkCreateImage, + pub vkDestroyImage: PFN_vkDestroyImage, + pub vkCmdCopyBuffer: PFN_vkCmdCopyBuffer, + #[doc = " Fetch \"vkGetBufferMemoryRequirements2\" on Vulkan >= 1.1, fetch \"vkGetBufferMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] + pub vkGetBufferMemoryRequirements2KHR: PFN_vkGetBufferMemoryRequirements2, + #[doc = " Fetch \"vkGetImageMemoryRequirements 2\" on Vulkan >= 1.1, fetch \"vkGetImageMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] + pub vkGetImageMemoryRequirements2KHR: PFN_vkGetImageMemoryRequirements2, + #[doc = " Fetch \"vkBindBufferMemory2\" on Vulkan >= 1.1, fetch \"vkBindBufferMemory2KHR\" when using VK_KHR_bind_memory2 extension."] + pub vkBindBufferMemory2KHR: PFN_vkBindBufferMemory2, + #[doc = " Fetch \"vkBindImageMemory2\" on Vulkan >= 1.1, fetch \"vkBindImageMemory2KHR\" when using VK_KHR_bind_memory2 extension."] + pub vkBindImageMemory2KHR: PFN_vkBindImageMemory2, + pub vkGetPhysicalDeviceMemoryProperties2KHR: PFN_vkGetPhysicalDeviceMemoryProperties2, +} +#[doc = " Description of a Allocator to be created."] +#[repr(C)] +pub struct VmaAllocatorCreateInfo { + #[doc = " Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum."] + pub flags: VmaAllocatorCreateFlags, + #[doc = " Vulkan physical device."] + #[doc = "** It must be valid throughout whole lifetime of created allocator. */"] + pub physicalDevice: PhysicalDevice, + #[doc = " Vulkan device."] + #[doc = "** It must be valid throughout whole lifetime of created allocator. */"] + pub device: Device, + #[doc = " Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional."] + #[doc = "** Set to 0 to use default, which is currently 256 MiB. */"] + pub preferredLargeHeapBlockSize: DeviceSize, + #[doc = " Custom CPU memory allocation callbacks. Optional."] + #[doc = "** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */"] + pub pAllocationCallbacks: *const AllocationCallbacks, + #[doc = " Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional."] + #[doc = "** Optional, can be null. */"] + pub pDeviceMemoryCallbacks: *const VmaDeviceMemoryCallbacks, + #[doc = " \\brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap."] + #[doc = ""] + #[doc = "If not NULL, it must be a pointer to an array of"] + #[doc = "`VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on"] + #[doc = "maximum number of bytes that can be allocated out of particular Vulkan memory"] + #[doc = "heap."] + #[doc = ""] + #[doc = "Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that"] + #[doc = "heap. This is also the default in case of `pHeapSizeLimit` = NULL."] + #[doc = ""] + #[doc = "If there is a limit defined for a heap:"] + #[doc = ""] + #[doc = "- If user tries to allocate more memory from that heap using this allocator,"] + #[doc = "the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`."] + #[doc = "- If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the"] + #[doc = "value of this limit will be reported instead when using vmaGetMemoryProperties()."] + #[doc = ""] + #[doc = "Warning! Using this feature may not be equivalent to installing a GPU with"] + #[doc = "smaller amount of memory, because graphics driver doesn't necessary fail new"] + #[doc = "allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is"] + #[doc = "exceeded. It may return success and just silently migrate some device memory"] + #[doc = "blocks to system RAM. This driver behavior can also be controlled using"] + #[doc = "VK_AMD_memory_overallocation_behavior extension."] + pub pHeapSizeLimit: *const DeviceSize, + #[doc = " \\brief Pointers to Vulkan functions. Can be null."] + #[doc = ""] + #[doc = "For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions)."] + pub pVulkanFunctions: *const VmaVulkanFunctions, + #[doc = " \\brief Handle to Vulkan instance object."] + #[doc = ""] + #[doc = "Starting from version 3.0.0 this member is no longer optional, it must be set!"] + pub instance: Instance, + #[doc = " \\brief Optional. The highest version of Vulkan that the application is designed to use."] + #[doc = ""] + #[doc = "It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`."] + #[doc = "The patch version number specified is ignored. Only the major and minor versions are considered."] + #[doc = "It must be less or equal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`."] + #[doc = "Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation."] + #[doc = "Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`."] + pub vulkanApiVersion: u32, + #[doc = " \\brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type."] + #[doc = ""] + #[doc = "If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount`"] + #[doc = "elements, defining external memory handle types of particular Vulkan memory type,"] + #[doc = "to be passed using `VkExportMemoryAllocateInfoKHR`."] + #[doc = ""] + #[doc = "Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type."] + #[doc = "This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL."] + pub pTypeExternalMemoryHandleTypes: *const ExternalMemoryHandleTypeFlagsKHR, +} +#[doc = " Information about existing #VmaAllocator object."] +#[repr(C)] +pub struct VmaAllocatorInfo { + #[doc = " \\brief Handle to Vulkan instance object."] + #[doc = ""] + #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::instance."] + pub instance: Instance, + #[doc = " \\brief Handle to Vulkan physical device object."] + #[doc = ""] + #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice."] + pub physicalDevice: PhysicalDevice, + #[doc = " \\brief Handle to Vulkan device object."] + #[doc = ""] + #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::device."] + pub device: Device, +} +#[doc = " Calculated statistics of memory usage in entire allocator."] +#[repr(C)] +pub struct VmaStatInfo { + #[doc = " Number of `VkDeviceMemory` Vulkan memory blocks allocated."] + pub blockCount: u32, + #[doc = " Number of #VmaAllocation allocation objects allocated."] + pub allocationCount: u32, + #[doc = " Number of free ranges of memory between allocations."] + pub unusedRangeCount: u32, + #[doc = " Total number of bytes occupied by all allocations."] + pub usedBytes: DeviceSize, + #[doc = " Total number of bytes occupied by unused ranges."] + pub unusedBytes: DeviceSize, + pub allocationSizeMin: DeviceSize, + pub allocationSizeAvg: DeviceSize, + pub allocationSizeMax: DeviceSize, + pub unusedRangeSizeMin: DeviceSize, + pub unusedRangeSizeAvg: DeviceSize, + pub unusedRangeSizeMax: DeviceSize, +} +#[doc = " General statistics from current state of Allocator."] +#[repr(C)] +pub struct VmaStats { + pub memoryType: [VmaStatInfo; 32usize], + pub memoryHeap: [VmaStatInfo; 16usize], + pub total: VmaStatInfo, +} +#[doc = " Statistics of current memory usage and available budget, in bytes, for specific memory heap."] +#[repr(C)] +pub struct VmaBudget { + #[doc = " \\brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes."] + pub blockBytes: DeviceSize, + #[doc = " \\brief Sum size of all allocations created in particular heap, in bytes."] + #[doc = ""] + #[doc = "Usually less or equal than `blockBytes`."] + #[doc = "Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused -"] + #[doc = "available for new allocations or wasted due to fragmentation."] + pub allocationBytes: DeviceSize, + #[doc = " \\brief Estimated current memory usage of the program, in bytes."] + #[doc = ""] + #[doc = "Fetched from system using `VK_EXT_memory_budget` extension if enabled."] + #[doc = ""] + #[doc = "It might be different than `blockBytes` (usually higher) due to additional implicit objects"] + #[doc = "also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or"] + #[doc = "`VkDeviceMemory` blocks allocated outside of this library, if any."] + pub usage: DeviceSize, + #[doc = " \\brief Estimated amount of memory available to the program, in bytes."] + #[doc = ""] + #[doc = "Fetched from system using `VK_EXT_memory_budget` extension if enabled."] + #[doc = ""] + #[doc = "It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors"] + #[doc = "external to the program, like other programs also consuming system resources."] + #[doc = "Difference `budget - usage` is the amount of additional memory that can probably"] + #[doc = "be allocated without problems. Exceeding the budget may result in various problems."] + pub budget: DeviceSize, +} +#[doc = "\\addtogroup group_alloc"] +#[doc = "@{"] +#[repr(C)] +pub struct VmaAllocationCreateInfo { + #[doc = " Use #VmaAllocationCreateFlagBits enum."] + pub flags: VmaAllocationCreateFlags, + #[doc = " \\brief Intended usage of memory."] + #[doc = ""] + #[doc = "You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \\n"] + #[doc = "If `pool` is not null, this member is ignored."] + pub usage: VmaMemoryUsage, + #[doc = " \\brief Flags that must be set in a Memory Type chosen for an allocation."] + #[doc = ""] + #[doc = "Leave 0 if you specify memory requirements in other way. \\n"] + #[doc = "If `pool` is not null, this member is ignored."] + pub requiredFlags: MemoryPropertyFlags, + #[doc = " \\brief Flags that preferably should be set in a memory type chosen for an allocation."] + #[doc = ""] + #[doc = "Set to 0 if no additional flags are preferred. \\n"] + #[doc = "If `pool` is not null, this member is ignored."] + pub preferredFlags: MemoryPropertyFlags, + #[doc = " \\brief Bitmask containing one bit set for every memory type acceptable for this allocation."] + #[doc = ""] + #[doc = "Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if"] + #[doc = "it meets other requirements specified by this structure, with no further"] + #[doc = "restrictions on memory type index. \\n"] + #[doc = "If `pool` is not null, this member is ignored."] + pub memoryTypeBits: u32, + #[doc = " \\brief Pool that this allocation should be created in."] + #[doc = ""] + #[doc = "Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:"] + #[doc = "`usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored."] + pub pool: VmaPool, + #[doc = " \\brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData()."] + #[doc = ""] + #[doc = "If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either"] + #[doc = "null or pointer to a null-terminated string. The string will be then copied to"] + #[doc = "internal buffer, so it doesn't need to be valid after allocation call."] + pub pUserData: *mut ::std::os::raw::c_void, + #[doc = " \\brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations."] + #[doc = ""] + #[doc = "It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object"] + #[doc = "and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] + #[doc = "Otherwise, it has the priority of a memory block where it is placed and this variable is ignored."] + pub priority: f32, +} +#[doc = " Describes parameter of created #VmaPool."] +#[repr(C)] +pub struct VmaPoolCreateInfo { + #[doc = " \\brief Vulkan memory type index to allocate this pool from."] + pub memoryTypeIndex: u32, + #[doc = " \\brief Use combination of #VmaPoolCreateFlagBits."] + pub flags: VmaPoolCreateFlags, + #[doc = " \\brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional."] + #[doc = ""] + #[doc = "Specify nonzero to set explicit, constant size of memory blocks used by this"] + #[doc = "pool."] + #[doc = ""] + #[doc = "Leave 0 to use default and let the library manage block sizes automatically."] + #[doc = "Sizes of particular blocks may vary."] + #[doc = "In this case, the pool will also support dedicated allocations."] + pub blockSize: DeviceSize, + #[doc = " \\brief Minimum number of blocks to be always allocated in this pool, even if they stay empty."] + #[doc = ""] + #[doc = "Set to 0 to have no preallocated blocks and allow the pool be completely empty."] + pub minBlockCount: usize, + #[doc = " \\brief Maximum number of blocks that can be allocated in this pool. Optional."] + #[doc = ""] + #[doc = "Set to 0 to use default, which is `SIZE_MAX`, which means no limit."] + #[doc = ""] + #[doc = "Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated"] + #[doc = "throughout whole lifetime of this pool."] + pub maxBlockCount: usize, + #[doc = " \\brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations."] + #[doc = ""] + #[doc = "It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object."] + #[doc = "Otherwise, this variable is ignored."] + pub priority: f32, + #[doc = " \\brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0."] + #[doc = ""] + #[doc = "Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two."] + #[doc = "It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,"] + #[doc = "e.g. when doing interop with OpenGL."] + pub minAllocationAlignment: DeviceSize, + #[doc = " \\brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional."] + #[doc = ""] + #[doc = "Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`."] + #[doc = "It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`."] + #[doc = "Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool."] + #[doc = ""] + #[doc = "Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`,"] + #[doc = "can be attached automatically by this library when using other, more convenient of its features."] + pub pMemoryAllocateNext: *mut ::std::os::raw::c_void, +} +#[doc = " Describes parameter of existing #VmaPool."] +#[repr(C)] +pub struct VmaPoolStats { + #[doc = " \\brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes."] + pub size: DeviceSize, + #[doc = " \\brief Total number of bytes in the pool not used by any #VmaAllocation."] + pub unusedSize: DeviceSize, + #[doc = " \\brief Number of #VmaAllocation objects created from this pool that were not destroyed."] + pub allocationCount: usize, + #[doc = " \\brief Number of continuous memory ranges in the pool not used by any #VmaAllocation."] + pub unusedRangeCount: usize, + #[doc = " \\brief Number of `VkDeviceMemory` blocks allocated for this pool."] + pub blockCount: usize, +} +#[doc = " Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo()."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaAllocationInfo { + #[doc = " \\brief Memory type index that this allocation was allocated from."] + #[doc = ""] + #[doc = "It never changes."] + pub memoryType: u32, + #[doc = " \\brief Handle to Vulkan memory object."] + #[doc = ""] + #[doc = "Same memory object can be shared by multiple allocations."] + #[doc = ""] + #[doc = "It can change after call to vmaDefragment() if this allocation is passed to the function."] + pub deviceMemory: DeviceMemory, + #[doc = " \\brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation."] + #[doc = ""] + #[doc = "You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function"] + #[doc = "vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,"] + #[doc = "not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation"] + #[doc = "and apply this offset automatically."] + #[doc = ""] + #[doc = "It can change after call to vmaDefragment() if this allocation is passed to the function."] + pub offset: DeviceSize, + #[doc = " \\brief Size of this allocation, in bytes."] + #[doc = ""] + #[doc = "It never changes."] + #[doc = ""] + #[doc = "\\note Allocation size returned in this variable may be greater than the size"] + #[doc = "requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the"] + #[doc = "allocation is accessible for operations on memory e.g. using a pointer after"] + #[doc = "mapping with vmaMapMemory(), but operations on the resource e.g. using"] + #[doc = "`vkCmdCopyBuffer` must be limited to the size of the resource."] + pub size: DeviceSize, + #[doc = " \\brief Pointer to the beginning of this allocation as mapped data."] + #[doc = ""] + #[doc = "If the allocation hasn't been mapped using vmaMapMemory() and hasn't been"] + #[doc = "created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null."] + #[doc = ""] + #[doc = "It can change after call to vmaMapMemory(), vmaUnmapMemory()."] + #[doc = "It can also change after call to vmaDefragment() if this allocation is passed to the function."] + pub pMappedData: *mut ::std::os::raw::c_void, + #[doc = " \\brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData()."] + #[doc = ""] + #[doc = "It can change after call to vmaSetAllocationUserData() for this allocation."] + pub pUserData: *mut ::std::os::raw::c_void, +} +#[doc = " \\brief Parameters for defragmentation."] +#[doc = ""] +#[doc = "To be used with function vmaDefragmentationBegin()."] +#[repr(C)] +pub struct VmaDefragmentationInfo2 { + #[doc = " \\brief Reserved for future use. Should be 0."] + pub flags: VmaDefragmentationFlags, + #[doc = " \\brief Number of allocations in `pAllocations` array."] + pub allocationCount: u32, + #[doc = " \\brief Pointer to array of allocations that can be defragmented."] + #[doc = ""] + #[doc = "The array should have `allocationCount` elements."] + #[doc = "The array should not contain nulls."] + #[doc = "Elements in the array should be unique - same allocation cannot occur twice."] + #[doc = "All allocations not present in this array are considered non-moveable during this defragmentation."] + pub pAllocations: *mut VmaAllocation, + #[doc = " \\brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation."] + #[doc = ""] + #[doc = "The array should have `allocationCount` elements."] + #[doc = "You can pass null if you are not interested in this information."] + pub pAllocationsChanged: *mut Bool32, + #[doc = " \\brief Numer of pools in `pPools` array."] + pub poolCount: u32, + #[doc = " \\brief Either null or pointer to array of pools to be defragmented."] + #[doc = ""] + #[doc = "All the allocations in the specified pools can be moved during defragmentation"] + #[doc = "and there is no way to check if they were really moved as in `pAllocationsChanged`,"] + #[doc = "so you must query all the allocations in all these pools for new `VkDeviceMemory`"] + #[doc = "and offset using vmaGetAllocationInfo() if you might need to recreate buffers"] + #[doc = "and images bound to them."] + #[doc = ""] + #[doc = "The array should have `poolCount` elements."] + #[doc = "The array should not contain nulls."] + #[doc = "Elements in the array should be unique - same pool cannot occur twice."] + #[doc = ""] + #[doc = "Using this array is equivalent to specifying all allocations from the pools in `pAllocations`."] + #[doc = "It might be more efficient."] + pub pPools: *mut VmaPool, + #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`."] + #[doc = ""] + #[doc = "`VK_WHOLE_SIZE` means no limit."] + pub maxCpuBytesToMove: DeviceSize, + #[doc = " \\brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`."] + #[doc = ""] + #[doc = "`UINT32_MAX` means no limit."] + pub maxCpuAllocationsToMove: u32, + #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`."] + #[doc = ""] + #[doc = "`VK_WHOLE_SIZE` means no limit."] + pub maxGpuBytesToMove: DeviceSize, + #[doc = " \\brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`."] + #[doc = ""] + #[doc = "`UINT32_MAX` means no limit."] + pub maxGpuAllocationsToMove: u32, + #[doc = " \\brief Optional. Command buffer where GPU copy commands will be posted."] + #[doc = ""] + #[doc = "If not null, it must be a valid command buffer handle that supports Transfer queue type."] + #[doc = "It must be in the recording state and outside of a render pass instance."] + #[doc = "You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd()."] + #[doc = ""] + #[doc = "Passing null means that only CPU defragmentation will be performed."] + pub commandBuffer: CommandBuffer, +} +#[repr(C)] +pub struct VmaDefragmentationPassMoveInfo { + pub allocation: VmaAllocation, + pub memory: DeviceMemory, + pub offset: DeviceSize, +} +#[doc = " \\brief Parameters for incremental defragmentation steps."] +#[doc = ""] +#[doc = "To be used with function vmaBeginDefragmentationPass()."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaDefragmentationPassInfo { + pub moveCount: u32, + pub pMoves: *mut VmaDefragmentationPassMoveInfo, +} +#[doc = " \\brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment()."] +#[doc = ""] +#[doc = "\\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead."] +#[repr(C)] +pub struct VmaDefragmentationInfo { + #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places."] + #[doc = ""] + #[doc = "Default is `VK_WHOLE_SIZE`, which means no limit."] + pub maxBytesToMove: DeviceSize, + #[doc = " \\brief Maximum number of allocations that can be moved to different place."] + #[doc = ""] + #[doc = "Default is `UINT32_MAX`, which means no limit."] + pub maxAllocationsToMove: u32, +} +#[doc = " Statistics returned by function vmaDefragment()."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VmaDefragmentationStats { + #[doc = " Total number of bytes that have been copied while moving allocations to different places."] + pub bytesMoved: DeviceSize, + #[doc = " Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects."] + pub bytesFreed: DeviceSize, + #[doc = " Number of allocations that have been moved to different places."] + pub allocationsMoved: u32, + #[doc = " Number of empty `VkDeviceMemory` objects that have been released to the system."] + pub deviceMemoryBlocksFreed: u32, +} +#[doc = " Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock()."] +#[repr(C)] +pub struct VmaVirtualBlockCreateInfo { + #[doc = " \\brief Total size of the virtual block."] + #[doc = ""] + #[doc = "Sizes can be expressed in bytes or any units you want as long as you are consistent in using them."] + #[doc = "For example, if you allocate from some array of structures, 1 can mean single instance of entire structure."] + pub size: DeviceSize, + #[doc = " \\brief Use combination of #VmaVirtualBlockCreateFlagBits."] + pub flags: VmaVirtualBlockCreateFlags, + #[doc = " \\brief Custom CPU memory allocation callbacks. Optional."] + #[doc = ""] + #[doc = "Optional, can be null. When specified, they will be used for all CPU-side memory allocations."] + pub pAllocationCallbacks: *const AllocationCallbacks, +} +#[doc = " Parameters of created virtual allocation to be passed to vmaVirtualAllocate()."] +#[repr(C)] +pub struct VmaVirtualAllocationCreateInfo { + #[doc = " \\brief Size of the allocation."] + #[doc = ""] + #[doc = "Cannot be zero."] + pub size: DeviceSize, + #[doc = " \\brief Required alignment of the allocation. Optional."] + #[doc = ""] + #[doc = "Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset."] + pub alignment: DeviceSize, + #[doc = " \\brief Use combination of #VmaVirtualAllocationCreateFlagBits."] + pub flags: VmaVirtualAllocationCreateFlags, + #[doc = " \\brief Custom pointer to be associated with the allocation. Optional."] + #[doc = ""] + #[doc = "It can be any value and can be used for user-defined purposes. It can be fetched or changed later."] + pub pUserData: *mut ::std::os::raw::c_void, +} +#[doc = " Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo()."] +#[repr(C)] +pub struct VmaVirtualAllocationInfo { + #[doc = " \\brief Offset of the allocation."] + #[doc = ""] + #[doc = "Offset at which the allocation was made."] + pub offset: DeviceSize, + #[doc = " \\brief Size of the allocation."] + #[doc = ""] + #[doc = "Same value as passed in VmaVirtualAllocationCreateInfo::size."] + pub size: DeviceSize, + #[doc = " \\brief Custom pointer associated with the allocation."] + #[doc = ""] + #[doc = "Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData()."] + pub pUserData: *mut ::std::os::raw::c_void, +} +extern "C" { + #[doc = " Creates #VmaAllocator object."] + pub fn vmaCreateAllocator( + pCreateInfo: *const VmaAllocatorCreateInfo, + pAllocator: *mut VmaAllocator, + ) -> Result; +} +extern "C" { + #[doc = " Destroys allocator object."] + pub fn vmaDestroyAllocator(allocator: VmaAllocator); +} +extern "C" { + #[doc = " \\brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc."] + #[doc = ""] + #[doc = "It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to"] + #[doc = "`VkPhysicalDevice`, `VkDevice` etc. every time using this function."] + pub fn vmaGetAllocatorInfo(allocator: VmaAllocator, pAllocatorInfo: *mut VmaAllocatorInfo); +} +extern "C" { + #[doc = "PhysicalDeviceProperties are fetched from physicalDevice by the allocator."] + #[doc = "You can access it here, without fetching it again on your own."] + pub fn vmaGetPhysicalDeviceProperties( + allocator: VmaAllocator, + ppPhysicalDeviceProperties: *mut *const PhysicalDeviceProperties, + ); +} +extern "C" { + #[doc = "PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator."] + #[doc = "You can access it here, without fetching it again on your own."] + pub fn vmaGetMemoryProperties( + allocator: VmaAllocator, + ppPhysicalDeviceMemoryProperties: *mut *const PhysicalDeviceMemoryProperties, + ); +} +extern "C" { + #[doc = "\\brief Given Memory Type Index, returns Property Flags of this memory type."] + #[doc = ""] + #[doc = "This is just a convenience function. Same information can be obtained using"] + #[doc = "vmaGetMemoryProperties()."] + pub fn vmaGetMemoryTypeProperties( + allocator: VmaAllocator, + memoryTypeIndex: u32, + pFlags: *mut MemoryPropertyFlags, + ); +} +extern "C" { + #[doc = " \\brief Sets index of the current frame."] + pub fn vmaSetCurrentFrameIndex(allocator: VmaAllocator, frameIndex: u32); +} +extern "C" { + #[doc = " \\brief Retrieves statistics from current state of the Allocator."] + #[doc = ""] + #[doc = "This function is called \"calculate\" not \"get\" because it has to traverse all"] + #[doc = "internal data structures, so it may be quite slow. For faster but more brief statistics"] + #[doc = "suitable to be called every frame or every allocation, use vmaGetHeapBudgets()."] + #[doc = ""] + #[doc = "Note that when using allocator from multiple threads, returned information may immediately"] + #[doc = "become outdated."] + pub fn vmaCalculateStats(allocator: VmaAllocator, pStats: *mut VmaStats); +} +extern "C" { + #[doc = " \\brief Retrieves information about current memory budget for all memory heaps."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used."] + #[doc = ""] + #[doc = "This function is called \"get\" not \"calculate\" because it is very fast, suitable to be called"] + #[doc = "every frame or every allocation. For more detailed statistics use vmaCalculateStats()."] + #[doc = ""] + #[doc = "Note that when using allocator from multiple threads, returned information may immediately"] + #[doc = "become outdated."] + pub fn vmaGetHeapBudgets(allocator: VmaAllocator, pBudgets: *mut VmaBudget); +} +extern "C" { + #[doc = "\\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo."] + #[doc = ""] + #[doc = "This algorithm tries to find a memory type that:"] + #[doc = ""] + #[doc = "- Is allowed by memoryTypeBits."] + #[doc = "- Contains all the flags from pAllocationCreateInfo->requiredFlags."] + #[doc = "- Matches intended usage."] + #[doc = "- Has as many flags from pAllocationCreateInfo->preferredFlags as possible."] + #[doc = ""] + #[doc = "\\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result"] + #[doc = "from this function or any other allocating function probably means that your"] + #[doc = "device doesn't support any memory type with requested features for the specific"] + #[doc = "type of resource you want to use it for. Please check parameters of your"] + #[doc = "resource, like image layout (OPTIMAL versus LINEAR) or mip level count."] + pub fn vmaFindMemoryTypeIndex( + allocator: VmaAllocator, + memoryTypeBits: u32, + pAllocationCreateInfo: *const VmaAllocationCreateInfo, + pMemoryTypeIndex: *mut u32, + ) -> Result; +} +extern "C" { + #[doc = "\\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo."] + #[doc = ""] + #[doc = "It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex."] + #[doc = "It internally creates a temporary, dummy buffer that never has memory bound."] + #[doc = "It is just a convenience function, equivalent to calling:"] + #[doc = ""] + #[doc = "- `vkCreateBuffer`"] + #[doc = "- `vkGetBufferMemoryRequirements`"] + #[doc = "- `vmaFindMemoryTypeIndex`"] + #[doc = "- `vkDestroyBuffer`"] + pub fn vmaFindMemoryTypeIndexForBufferInfo( + allocator: VmaAllocator, + pBufferCreateInfo: *const BufferCreateInfo, + pAllocationCreateInfo: *const VmaAllocationCreateInfo, + pMemoryTypeIndex: *mut u32, + ) -> Result; +} +extern "C" { + #[doc = "\\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo."] + #[doc = ""] + #[doc = "It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex."] + #[doc = "It internally creates a temporary, dummy image that never has memory bound."] + #[doc = "It is just a convenience function, equivalent to calling:"] + #[doc = ""] + #[doc = "- `vkCreateImage`"] + #[doc = "- `vkGetImageMemoryRequirements`"] + #[doc = "- `vmaFindMemoryTypeIndex`"] + #[doc = "- `vkDestroyImage`"] + pub fn vmaFindMemoryTypeIndexForImageInfo( + allocator: VmaAllocator, + pImageCreateInfo: *const ImageCreateInfo, + pAllocationCreateInfo: *const VmaAllocationCreateInfo, + pMemoryTypeIndex: *mut u32, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Allocates Vulkan device memory and creates #VmaPool object."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param pCreateInfo Parameters of pool to create."] + #[doc = "\\param[out] pPool Handle to created pool."] + pub fn vmaCreatePool( + allocator: VmaAllocator, + pCreateInfo: *const VmaPoolCreateInfo, + pPool: *mut VmaPool, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Destroys #VmaPool object and frees Vulkan device memory."] + pub fn vmaDestroyPool(allocator: VmaAllocator, pool: VmaPool); +} +extern "C" { + #[doc = " \\brief Retrieves statistics of existing #VmaPool object."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param pool Pool object."] + #[doc = "\\param[out] pPoolStats Statistics of specified pool."] + pub fn vmaGetPoolStats(allocator: VmaAllocator, pool: VmaPool, pPoolStats: *mut VmaPoolStats); +} +extern "C" { + #[doc = " \\brief Checks magic number in margins around all allocations in given memory pool in search for corruptions."] + #[doc = ""] + #[doc = "Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,"] + #[doc = "`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is"] + #[doc = "`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection)."] + #[doc = ""] + #[doc = "Possible return values:"] + #[doc = ""] + #[doc = "- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool."] + #[doc = "- `VK_SUCCESS` - corruption detection has been performed and succeeded."] + #[doc = "- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations."] + #[doc = "`VMA_ASSERT` is also fired in that case."] + #[doc = "- Other value: Error returned by Vulkan, e.g. memory mapping failure."] + pub fn vmaCheckPoolCorruption(allocator: VmaAllocator, pool: VmaPool) -> Result; +} +extern "C" { + #[doc = " \\brief Retrieves name of a custom pool."] + #[doc = ""] + #[doc = "After the call `ppName` is either null or points to an internally-owned null-terminated string"] + #[doc = "containing name of the pool that was previously set. The pointer becomes invalid when the pool is"] + #[doc = "destroyed or its name is changed using vmaSetPoolName()."] + pub fn vmaGetPoolName( + allocator: VmaAllocator, + pool: VmaPool, + ppName: *mut *const ::std::os::raw::c_char, + ); +} +extern "C" { + #[doc = " \\brief Sets name of a custom pool."] + #[doc = ""] + #[doc = "`pName` can be either null or pointer to a null-terminated string with new name for the pool."] + #[doc = "Function makes internal copy of the string, so it can be changed or freed immediately after this call."] + pub fn vmaSetPoolName( + allocator: VmaAllocator, + pool: VmaPool, + pName: *const ::std::os::raw::c_char, + ); +} +extern "C" { + #[doc = " \\brief General purpose memory allocation."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param pVkMemoryRequirements"] + #[doc = "\\param pCreateInfo"] + #[doc = "\\param[out] pAllocation Handle to allocated memory."] + #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] + #[doc = ""] + #[doc = "You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages()."] + #[doc = ""] + #[doc = "It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(),"] + #[doc = "vmaCreateBuffer(), vmaCreateImage() instead whenever possible."] + pub fn vmaAllocateMemory( + allocator: VmaAllocator, + pVkMemoryRequirements: *const MemoryRequirements, + pCreateInfo: *const VmaAllocationCreateInfo, + pAllocation: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = " \\brief General purpose memory allocation for multiple allocation objects at once."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param pVkMemoryRequirements Memory requirements for each allocation."] + #[doc = "\\param pCreateInfo Creation parameters for each allocation."] + #[doc = "\\param allocationCount Number of allocations to make."] + #[doc = "\\param[out] pAllocations Pointer to array that will be filled with handles to created allocations."] + #[doc = "\\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations."] + #[doc = ""] + #[doc = "You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages()."] + #[doc = ""] + #[doc = "Word \"pages\" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding."] + #[doc = "It is just a general purpose allocation function able to make multiple allocations at once."] + #[doc = "It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times."] + #[doc = ""] + #[doc = "All allocations are made using same parameters. All of them are created out of the same memory pool and type."] + #[doc = "If any allocation fails, all allocations already made within this function call are also freed, so that when"] + #[doc = "returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`."] + pub fn vmaAllocateMemoryPages( + allocator: VmaAllocator, + pVkMemoryRequirements: *const MemoryRequirements, + pCreateInfo: *const VmaAllocationCreateInfo, + allocationCount: usize, + pAllocations: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = "\\param allocator"] + #[doc = "\\param buffer"] + #[doc = "\\param pCreateInfo"] + #[doc = "\\param[out] pAllocation Handle to allocated memory."] + #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] + #[doc = ""] + #[doc = "You should free the memory using vmaFreeMemory()."] + pub fn vmaAllocateMemoryForBuffer( + allocator: VmaAllocator, + buffer: Buffer, + pCreateInfo: *const VmaAllocationCreateInfo, + pAllocation: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = " Function similar to vmaAllocateMemoryForBuffer()."] + pub fn vmaAllocateMemoryForImage( + allocator: VmaAllocator, + image: Image, + pCreateInfo: *const VmaAllocationCreateInfo, + pAllocation: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage()."] + #[doc = ""] + #[doc = "Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped."] + pub fn vmaFreeMemory(allocator: VmaAllocator, allocation: VmaAllocation); +} +extern "C" { + #[doc = " \\brief Frees memory and destroys multiple allocations."] + #[doc = ""] + #[doc = "Word \"pages\" is just a suggestion to use this function to free pieces of memory used for sparse binding."] + #[doc = "It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(),"] + #[doc = "vmaAllocateMemoryPages() and other functions."] + #[doc = "It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times."] + #[doc = ""] + #[doc = "Allocations in `pAllocations` array can come from any memory pools and types."] + #[doc = "Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped."] + pub fn vmaFreeMemoryPages( + allocator: VmaAllocator, + allocationCount: usize, + pAllocations: *mut VmaAllocation, + ); +} +extern "C" { + #[doc = " \\brief Returns current information about specified allocation."] + #[doc = ""] + #[doc = "Current paramteres of given allocation are returned in `pAllocationInfo`."] + #[doc = ""] + #[doc = "Although this function doesn't lock any mutex, so it should be quite efficient,"] + #[doc = "you should avoid calling it too often."] + #[doc = "You can retrieve same VmaAllocationInfo structure while creating your resource, from function"] + #[doc = "vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change"] + #[doc = "(e.g. due to defragmentation)."] + pub fn vmaGetAllocationInfo( + allocator: VmaAllocator, + allocation: VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ); +} +extern "C" { + #[doc = " \\brief Sets pUserData in given allocation to new value."] + #[doc = ""] + #[doc = "If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,"] + #[doc = "pUserData must be either null, or pointer to a null-terminated string. The function"] + #[doc = "makes local copy of the string and sets it as allocation's `pUserData`. String"] + #[doc = "passed as pUserData doesn't need to be valid for whole lifetime of the allocation -"] + #[doc = "you can free it after this call. String previously pointed by allocation's"] + #[doc = "pUserData is freed from memory."] + #[doc = ""] + #[doc = "If the flag was not used, the value of pointer `pUserData` is just copied to"] + #[doc = "allocation's `pUserData`. It is opaque, so you can use it however you want - e.g."] + #[doc = "as a pointer, ordinal number or some handle to you own data."] + pub fn vmaSetAllocationUserData( + allocator: VmaAllocator, + allocation: VmaAllocation, + pUserData: *mut ::std::os::raw::c_void, + ); +} +extern "C" { + #[doc = "\\brief Given an allocation, returns Property Flags of its memory type."] + #[doc = ""] + #[doc = "This is just a convenience function. Same information can be obtained using"] + #[doc = "vmaGetAllocationInfo() + vmaGetMemoryProperties()."] + pub fn vmaGetAllocationMemoryProperties( + allocator: VmaAllocator, + allocation: VmaAllocation, + pFlags: *mut MemoryPropertyFlags, + ); +} +extern "C" { + #[doc = " \\brief Maps memory represented by given allocation and returns pointer to it."] + #[doc = ""] + #[doc = "Maps memory represented by given allocation to make it accessible to CPU code."] + #[doc = "When succeeded, `*ppData` contains pointer to first byte of this memory."] + #[doc = ""] + #[doc = "\\warning"] + #[doc = "If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is"] + #[doc = "correctly offsetted to the beginning of region assigned to this particular allocation."] + #[doc = "Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block."] + #[doc = "You should not add VmaAllocationInfo::offset to it!"] + #[doc = ""] + #[doc = "Mapping is internally reference-counted and synchronized, so despite raw Vulkan"] + #[doc = "function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`"] + #[doc = "multiple times simultaneously, it is safe to call this function on allocations"] + #[doc = "assigned to the same memory block. Actual Vulkan memory will be mapped on first"] + #[doc = "mapping and unmapped on last unmapping."] + #[doc = ""] + #[doc = "If the function succeeded, you must call vmaUnmapMemory() to unmap the"] + #[doc = "allocation when mapping is no longer needed or before freeing the allocation, at"] + #[doc = "the latest."] + #[doc = ""] + #[doc = "It also safe to call this function multiple times on the same allocation. You"] + #[doc = "must call vmaUnmapMemory() same number of times as you called vmaMapMemory()."] + #[doc = ""] + #[doc = "It is also safe to call this function on allocation created with"] + #[doc = "#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time."] + #[doc = "You must still call vmaUnmapMemory() same number of times as you called"] + #[doc = "vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the"] + #[doc = "\"0-th\" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag."] + #[doc = ""] + #[doc = "This function fails when used on allocation made in memory type that is not"] + #[doc = "`HOST_VISIBLE`."] + #[doc = ""] + #[doc = "This function doesn't automatically flush or invalidate caches."] + #[doc = "If the allocation is made from a memory types that is not `HOST_COHERENT`,"] + #[doc = "you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification."] + pub fn vmaMapMemory( + allocator: VmaAllocator, + allocation: VmaAllocation, + ppData: *mut *mut ::std::os::raw::c_void, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory()."] + #[doc = ""] + #[doc = "For details, see description of vmaMapMemory()."] + #[doc = ""] + #[doc = "This function doesn't automatically flush or invalidate caches."] + #[doc = "If the allocation is made from a memory types that is not `HOST_COHERENT`,"] + #[doc = "you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification."] + pub fn vmaUnmapMemory(allocator: VmaAllocator, allocation: VmaAllocation); +} +extern "C" { + #[doc = " \\brief Flushes memory of given allocation."] + #[doc = ""] + #[doc = "Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation."] + #[doc = "It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`."] + #[doc = "Unmap operation doesn't do that automatically."] + #[doc = ""] + #[doc = "- `offset` must be relative to the beginning of allocation."] + #[doc = "- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation."] + #[doc = "- `offset` and `size` don't have to be aligned."] + #[doc = "They are internally rounded down/up to multiply of `nonCoherentAtomSize`."] + #[doc = "- If `size` is 0, this call is ignored."] + #[doc = "- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,"] + #[doc = "this call is ignored."] + #[doc = ""] + #[doc = "Warning! `offset` and `size` are relative to the contents of given `allocation`."] + #[doc = "If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively."] + #[doc = "Do not pass allocation's offset as `offset`!!!"] + #[doc = ""] + #[doc = "This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is"] + #[doc = "called, otherwise `VK_SUCCESS`."] + pub fn vmaFlushAllocation( + allocator: VmaAllocator, + allocation: VmaAllocation, + offset: DeviceSize, + size: DeviceSize, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Invalidates memory of given allocation."] + #[doc = ""] + #[doc = "Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation."] + #[doc = "It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`."] + #[doc = "Map operation doesn't do that automatically."] + #[doc = ""] + #[doc = "- `offset` must be relative to the beginning of allocation."] + #[doc = "- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation."] + #[doc = "- `offset` and `size` don't have to be aligned."] + #[doc = "They are internally rounded down/up to multiply of `nonCoherentAtomSize`."] + #[doc = "- If `size` is 0, this call is ignored."] + #[doc = "- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,"] + #[doc = "this call is ignored."] + #[doc = ""] + #[doc = "Warning! `offset` and `size` are relative to the contents of given `allocation`."] + #[doc = "If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively."] + #[doc = "Do not pass allocation's offset as `offset`!!!"] + #[doc = ""] + #[doc = "This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if"] + #[doc = "it is called, otherwise `VK_SUCCESS`."] + pub fn vmaInvalidateAllocation( + allocator: VmaAllocator, + allocation: VmaAllocation, + offset: DeviceSize, + size: DeviceSize, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Flushes memory of given set of allocations."] + #[doc = ""] + #[doc = "Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations."] + #[doc = "For more information, see documentation of vmaFlushAllocation()."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param allocationCount"] + #[doc = "\\param allocations"] + #[doc = "\\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero."] + #[doc = "\\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations."] + #[doc = ""] + #[doc = "This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is"] + #[doc = "called, otherwise `VK_SUCCESS`."] + pub fn vmaFlushAllocations( + allocator: VmaAllocator, + allocationCount: u32, + allocations: *mut VmaAllocation, + offsets: *const DeviceSize, + sizes: *const DeviceSize, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Invalidates memory of given set of allocations."] + #[doc = ""] + #[doc = "Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations."] + #[doc = "For more information, see documentation of vmaInvalidateAllocation()."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param allocationCount"] + #[doc = "\\param allocations"] + #[doc = "\\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero."] + #[doc = "\\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations."] + #[doc = ""] + #[doc = "This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is"] + #[doc = "called, otherwise `VK_SUCCESS`."] + pub fn vmaInvalidateAllocations( + allocator: VmaAllocator, + allocationCount: u32, + allocations: *mut VmaAllocation, + offsets: *const DeviceSize, + sizes: *const DeviceSize, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked."] + #[doc = ""] + #[doc = "Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,"] + #[doc = "`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are"] + #[doc = "`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection)."] + #[doc = ""] + #[doc = "Possible return values:"] + #[doc = ""] + #[doc = "- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types."] + #[doc = "- `VK_SUCCESS` - corruption detection has been performed and succeeded."] + #[doc = "- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations."] + #[doc = "`VMA_ASSERT` is also fired in that case."] + #[doc = "- Other value: Error returned by Vulkan, e.g. memory mapping failure."] + pub fn vmaCheckCorruption(allocator: VmaAllocator, memoryTypeBits: u32) -> Result; +} +extern "C" { + #[doc = " \\brief Begins defragmentation process."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param pInfo Structure filled with parameters of defragmentation."] + #[doc = "\\param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information."] + #[doc = "\\param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation."] + #[doc = "\\return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error."] + #[doc = ""] + #[doc = "Use this function instead of old, deprecated vmaDefragment()."] + #[doc = ""] + #[doc = "Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():"] + #[doc = ""] + #[doc = "- You should not use any of allocations passed as `pInfo->pAllocations` or"] + #[doc = "any allocations that belong to pools passed as `pInfo->pPools`,"] + #[doc = "including calling vmaGetAllocationInfo(), or access"] + #[doc = "their data."] + #[doc = "- Some mutexes protecting internal data structures may be locked, so trying to"] + #[doc = "make or free any allocations, bind buffers or images, map memory, or launch"] + #[doc = "another simultaneous defragmentation in between may cause stall (when done on"] + #[doc = "another thread) or deadlock (when done on the same thread), unless you are"] + #[doc = "100% sure that defragmented allocations are in different pools."] + #[doc = "- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined."] + #[doc = "They become valid after call to vmaDefragmentationEnd()."] + #[doc = "- If `pInfo->commandBuffer` is not null, you must submit that command buffer"] + #[doc = "and make sure it finished execution before calling vmaDefragmentationEnd()."] + #[doc = ""] + #[doc = "For more information and important limitations regarding defragmentation, see documentation chapter:"] + #[doc = "[Defragmentation](@ref defragmentation)."] + pub fn vmaDefragmentationBegin( + allocator: VmaAllocator, + pInfo: *const VmaDefragmentationInfo2, + pStats: *mut VmaDefragmentationStats, + pContext: *mut VmaDefragmentationContext, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Ends defragmentation process."] + #[doc = ""] + #[doc = "Use this function to finish defragmentation started by vmaDefragmentationBegin()."] + #[doc = "It is safe to pass `context == null`. The function then does nothing."] + pub fn vmaDefragmentationEnd( + allocator: VmaAllocator, + context: VmaDefragmentationContext, + ) -> Result; +} +extern "C" { + pub fn vmaBeginDefragmentationPass( + allocator: VmaAllocator, + context: VmaDefragmentationContext, + pInfo: *mut VmaDefragmentationPassInfo, + ) -> Result; +} +extern "C" { + pub fn vmaEndDefragmentationPass( + allocator: VmaAllocator, + context: VmaDefragmentationContext, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Deprecated. Compacts memory by moving allocations."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param pAllocations Array of allocations that can be moved during this compation."] + #[doc = "\\param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays."] + #[doc = "\\param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information."] + #[doc = "\\param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values."] + #[doc = "\\param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information."] + #[doc = "\\return `VK_SUCCESS` if completed, negative error code in case of error."] + #[doc = ""] + #[doc = "\\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead."] + #[doc = ""] + #[doc = "This function works by moving allocations to different places (different"] + #[doc = "`VkDeviceMemory` objects and/or different offsets) in order to optimize memory"] + #[doc = "usage. Only allocations that are in `pAllocations` array can be moved. All other"] + #[doc = "allocations are considered nonmovable in this call. Basic rules:"] + #[doc = ""] + #[doc = "- Only allocations made in memory types that have"] + #[doc = "`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`"] + #[doc = "flags can be compacted. You may pass other allocations but it makes no sense -"] + #[doc = "these will never be moved."] + #[doc = "- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or"] + #[doc = "#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations"] + #[doc = "passed to this function that come from such pools are ignored."] + #[doc = "- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or"] + #[doc = "created as dedicated allocations for any other reason are also ignored."] + #[doc = "- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT"] + #[doc = "flag can be compacted. If not persistently mapped, memory will be mapped"] + #[doc = "temporarily inside this function if needed."] + #[doc = "- You must not pass same #VmaAllocation object multiple times in `pAllocations` array."] + #[doc = ""] + #[doc = "The function also frees empty `VkDeviceMemory` blocks."] + #[doc = ""] + #[doc = "Warning: This function may be time-consuming, so you shouldn't call it too often"] + #[doc = "(like after every resource creation/destruction)."] + #[doc = "You can call it on special occasions (like when reloading a game level or"] + #[doc = "when you just destroyed a lot of objects). Calling it every frame may be OK, but"] + #[doc = "you should measure that on your platform."] + #[doc = ""] + #[doc = "For more information, see [Defragmentation](@ref defragmentation) chapter."] + pub fn vmaDefragment( + allocator: VmaAllocator, + pAllocations: *mut VmaAllocation, + allocationCount: usize, + pAllocationsChanged: *mut Bool32, + pDefragmentationInfo: *const VmaDefragmentationInfo, + pDefragmentationStats: *mut VmaDefragmentationStats, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Binds buffer to allocation."] + #[doc = ""] + #[doc = "Binds specified buffer to region of memory represented by specified allocation."] + #[doc = "Gets `VkDeviceMemory` handle and offset from the allocation."] + #[doc = "If you want to create a buffer, allocate memory for it and bind them together separately,"] + #[doc = "you should use this function for binding instead of standard `vkBindBufferMemory()`,"] + #[doc = "because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple"] + #[doc = "allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously"] + #[doc = "(which is illegal in Vulkan)."] + #[doc = ""] + #[doc = "It is recommended to use function vmaCreateBuffer() instead of this one."] + pub fn vmaBindBufferMemory( + allocator: VmaAllocator, + allocation: VmaAllocation, + buffer: Buffer, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Binds buffer to allocation with additional parameters."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param allocation"] + #[doc = "\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0."] + #[doc = "\\param buffer"] + #[doc = "\\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null."] + #[doc = ""] + #[doc = "This function is similar to vmaBindBufferMemory(), but it provides additional parameters."] + #[doc = ""] + #[doc = "If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag"] + #[doc = "or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails."] + pub fn vmaBindBufferMemory2( + allocator: VmaAllocator, + allocation: VmaAllocation, + allocationLocalOffset: DeviceSize, + buffer: Buffer, + pNext: *const ::std::os::raw::c_void, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Binds image to allocation."] + #[doc = ""] + #[doc = "Binds specified image to region of memory represented by specified allocation."] + #[doc = "Gets `VkDeviceMemory` handle and offset from the allocation."] + #[doc = "If you want to create an image, allocate memory for it and bind them together separately,"] + #[doc = "you should use this function for binding instead of standard `vkBindImageMemory()`,"] + #[doc = "because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple"] + #[doc = "allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously"] + #[doc = "(which is illegal in Vulkan)."] + #[doc = ""] + #[doc = "It is recommended to use function vmaCreateImage() instead of this one."] + pub fn vmaBindImageMemory( + allocator: VmaAllocator, + allocation: VmaAllocation, + image: Image, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Binds image to allocation with additional parameters."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param allocation"] + #[doc = "\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0."] + #[doc = "\\param image"] + #[doc = "\\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null."] + #[doc = ""] + #[doc = "This function is similar to vmaBindImageMemory(), but it provides additional parameters."] + #[doc = ""] + #[doc = "If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag"] + #[doc = "or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails."] + pub fn vmaBindImageMemory2( + allocator: VmaAllocator, + allocation: VmaAllocation, + allocationLocalOffset: DeviceSize, + image: Image, + pNext: *const ::std::os::raw::c_void, + ) -> Result; +} +extern "C" { + #[doc = "\\param allocator"] + #[doc = "\\param pBufferCreateInfo"] + #[doc = "\\param pAllocationCreateInfo"] + #[doc = "\\param[out] pBuffer Buffer that was created."] + #[doc = "\\param[out] pAllocation Allocation that was created."] + #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] + #[doc = ""] + #[doc = "This function automatically:"] + #[doc = ""] + #[doc = "-# Creates buffer."] + #[doc = "-# Allocates appropriate memory for it."] + #[doc = "-# Binds the buffer with the memory."] + #[doc = ""] + #[doc = "If any of these operations fail, buffer and allocation are not created,"] + #[doc = "returned value is negative error code, *pBuffer and *pAllocation are null."] + #[doc = ""] + #[doc = "If the function succeeded, you must destroy both buffer and allocation when you"] + #[doc = "no longer need them using either convenience function vmaDestroyBuffer() or"] + #[doc = "separately, using `vkDestroyBuffer()` and vmaFreeMemory()."] + #[doc = ""] + #[doc = "If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,"] + #[doc = "VK_KHR_dedicated_allocation extension is used internally to query driver whether"] + #[doc = "it requires or prefers the new buffer to have dedicated allocation. If yes,"] + #[doc = "and if dedicated allocation is possible"] + #[doc = "(#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated"] + #[doc = "allocation for this buffer, just like when using"] + #[doc = "#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] + #[doc = ""] + #[doc = "\\note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer,"] + #[doc = "although recommended as a good practice, is out of scope of this library and could be implemented"] + #[doc = "by the user as a higher-level logic on top of VMA."] + pub fn vmaCreateBuffer( + allocator: VmaAllocator, + pBufferCreateInfo: *const BufferCreateInfo, + pAllocationCreateInfo: *const VmaAllocationCreateInfo, + pBuffer: *mut Buffer, + pAllocation: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Creates a buffer with additional minimum alignment."] + #[doc = ""] + #[doc = "Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom,"] + #[doc = "minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g."] + #[doc = "for interop with OpenGL."] + pub fn vmaCreateBufferWithAlignment( + allocator: VmaAllocator, + pBufferCreateInfo: *const BufferCreateInfo, + pAllocationCreateInfo: *const VmaAllocationCreateInfo, + minAlignment: DeviceSize, + pBuffer: *mut Buffer, + pAllocation: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Destroys Vulkan buffer and frees allocated memory."] + #[doc = ""] + #[doc = "This is just a convenience function equivalent to:"] + #[doc = ""] + #[doc = "\\code"] + #[doc = "vkDestroyBuffer(device, buffer, allocationCallbacks);"] + #[doc = "vmaFreeMemory(allocator, allocation);"] + #[doc = "\\endcode"] + #[doc = ""] + #[doc = "It it safe to pass null as buffer and/or allocation."] + pub fn vmaDestroyBuffer(allocator: VmaAllocator, buffer: Buffer, allocation: VmaAllocation); +} +extern "C" { + #[doc = " Function similar to vmaCreateBuffer()."] + pub fn vmaCreateImage( + allocator: VmaAllocator, + pImageCreateInfo: *const ImageCreateInfo, + pAllocationCreateInfo: *const VmaAllocationCreateInfo, + pImage: *mut Image, + pAllocation: *mut VmaAllocation, + pAllocationInfo: *mut VmaAllocationInfo, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Destroys Vulkan image and frees allocated memory."] + #[doc = ""] + #[doc = "This is just a convenience function equivalent to:"] + #[doc = ""] + #[doc = "\\code"] + #[doc = "vkDestroyImage(device, image, allocationCallbacks);"] + #[doc = "vmaFreeMemory(allocator, allocation);"] + #[doc = "\\endcode"] + #[doc = ""] + #[doc = "It it safe to pass null as image and/or allocation."] + pub fn vmaDestroyImage(allocator: VmaAllocator, image: Image, allocation: VmaAllocation); +} +extern "C" { + #[doc = " \\brief Creates new #VmaVirtualBlock object."] + #[doc = ""] + #[doc = "\\param pCreateInfo Parameters for creation."] + #[doc = "\\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed."] + pub fn vmaCreateVirtualBlock( + pCreateInfo: *const VmaVirtualBlockCreateInfo, + pVirtualBlock: *mut VmaVirtualBlock, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Destroys #VmaVirtualBlock object."] + #[doc = ""] + #[doc = "Please note that you should consciously handle virtual allocations that could remain unfreed in the block."] + #[doc = "You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock()"] + #[doc = "if you are sure this is what you want. If you do neither, an assert is called."] + #[doc = ""] + #[doc = "If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`,"] + #[doc = "don't forget to free them."] + pub fn vmaDestroyVirtualBlock(virtualBlock: VmaVirtualBlock); +} +extern "C" { + #[doc = " \\brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations."] + pub fn vmaIsVirtualBlockEmpty(virtualBlock: VmaVirtualBlock) -> Bool32; +} +extern "C" { + #[doc = " \\brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer."] + pub fn vmaGetVirtualAllocationInfo( + virtualBlock: VmaVirtualBlock, + allocation: VmaVirtualAllocation, + pVirtualAllocInfo: *mut VmaVirtualAllocationInfo, + ); +} +extern "C" { + #[doc = " \\brief Allocates new virtual allocation inside given #VmaVirtualBlock."] + #[doc = ""] + #[doc = "If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned"] + #[doc = "(despite the function doesn't ever allocate actual GPU memory)."] + #[doc = "`pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`."] + #[doc = ""] + #[doc = "\\param virtualBlock Virtual block"] + #[doc = "\\param pCreateInfo Parameters for the allocation"] + #[doc = "\\param[out] pAllocation Returned handle of the new allocation"] + #[doc = "\\param[out] pOffset Returned offset of the new allocation. Optional, can be null."] + pub fn vmaVirtualAllocate( + virtualBlock: VmaVirtualBlock, + pCreateInfo: *const VmaVirtualAllocationCreateInfo, + pAllocation: *mut VmaVirtualAllocation, + pOffset: *mut DeviceSize, + ) -> Result; +} +extern "C" { + #[doc = " \\brief Frees virtual allocation inside given #VmaVirtualBlock."] + #[doc = ""] + #[doc = "It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing."] + pub fn vmaVirtualFree(virtualBlock: VmaVirtualBlock, allocation: VmaVirtualAllocation); +} +extern "C" { + #[doc = " \\brief Frees all virtual allocations inside given #VmaVirtualBlock."] + #[doc = ""] + #[doc = "You must either call this function or free each virtual allocation individually with vmaVirtualFree()"] + #[doc = "before destroying a virtual block. Otherwise, an assert is called."] + #[doc = ""] + #[doc = "If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`,"] + #[doc = "don't forget to free it as well."] + pub fn vmaClearVirtualBlock(virtualBlock: VmaVirtualBlock); +} +extern "C" { + #[doc = " \\brief Changes custom pointer associated with given virtual allocation."] + pub fn vmaSetVirtualAllocationUserData( + virtualBlock: VmaVirtualBlock, + allocation: VmaVirtualAllocation, + pUserData: *mut ::std::os::raw::c_void, + ); +} +extern "C" { + #[doc = " \\brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock."] + pub fn vmaCalculateVirtualBlockStats( + virtualBlock: VmaVirtualBlock, + pStatInfo: *mut VmaStatInfo, + ); +} +extern "C" { + #[doc = " \\brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock."] + #[doc = "\\param virtualBlock Virtual block."] + #[doc = "\\param[out] ppStatsString Returned string."] + #[doc = "\\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStats(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces."] + #[doc = ""] + #[doc = "Returned string must be freed using vmaFreeVirtualBlockStatsString()."] + pub fn vmaBuildVirtualBlockStatsString( + virtualBlock: VmaVirtualBlock, + ppStatsString: *mut *mut ::std::os::raw::c_char, + detailedMap: Bool32, + ); +} +extern "C" { + #[doc = " Frees a string returned by vmaBuildVirtualBlockStatsString()."] + pub fn vmaFreeVirtualBlockStatsString( + virtualBlock: VmaVirtualBlock, + pStatsString: *mut ::std::os::raw::c_char, + ); +} +extern "C" { + #[doc = " \\brief Builds and returns statistics as a null-terminated string in JSON format."] + #[doc = "\\param allocator"] + #[doc = "\\param[out] ppStatsString Must be freed using vmaFreeStatsString() function."] + #[doc = "\\param detailedMap"] + pub fn vmaBuildStatsString( + allocator: VmaAllocator, + ppStatsString: *mut *mut ::std::os::raw::c_char, + detailedMap: Bool32, + ); +} +extern "C" { + pub fn vmaFreeStatsString(allocator: VmaAllocator, pStatsString: *mut ::std::os::raw::c_char); +} From 7e6bfe8f04dcca027ce4c1deebbd6779b04407c0 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Tue, 10 May 2022 22:39:49 -0700 Subject: [PATCH 02/23] remove reference to PhysicalDevice. Physical Device is Copy. --- src/definitions.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index e5d1220..42a1c1d 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -329,22 +329,21 @@ bitflags! { pub struct AllocatorCreateInfo<'a> { pub(crate) inner: ffi::VmaAllocatorCreateInfo, - pub(crate) physical_device: &'a PhysicalDevice, + pub(crate) physical_device: PhysicalDevice, pub(crate) device: &'a Device, pub(crate) instance: &'a Instance, - pub(crate) marker: ::std::marker::PhantomData<&'a ()>, } impl<'a> AllocatorCreateInfo<'a> { pub fn new( instance: &'a ash::Instance, device: &'a ash::Device, - physical_device: &'a ash::vk::PhysicalDevice, + physical_device: ash::vk::PhysicalDevice, ) -> AllocatorCreateInfo<'a> { AllocatorCreateInfo { inner: ffi::VmaAllocatorCreateInfo { flags: 0, - physicalDevice: *physical_device, + physicalDevice: physical_device, instance: instance.handle(), device: device.handle(), preferredLargeHeapBlockSize: 0, @@ -358,7 +357,6 @@ impl<'a> AllocatorCreateInfo<'a> { physical_device, device, instance, - marker: ::std::marker::PhantomData, } } @@ -376,7 +374,7 @@ impl<'a> AllocatorCreateInfo<'a> { unsafe { debug_assert!( self.instance - .get_physical_device_memory_properties(*self.physical_device) + .get_physical_device_memory_properties(self.physical_device) .memory_heap_count == device_sizes.len() as u32 ); @@ -402,7 +400,7 @@ impl<'a> AllocatorCreateInfo<'a> { unsafe { debug_assert!( self.instance - .get_physical_device_memory_properties(*self.physical_device) + .get_physical_device_memory_properties(self.physical_device) .memory_type_count == external_memory_handles.len() as u32 ); From 3ace2cefbe44b724672d7ba50dee04a9efc6d150 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Tue, 10 May 2022 23:33:12 -0700 Subject: [PATCH 03/23] add feature flags --- Cargo.toml | 7 ++-- build.rs | 44 ---------------------- src/lib.rs | 105 +++++++++++++++++++++++++++-------------------------- 3 files changed, 58 insertions(+), 98 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eb172a7..10356b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ travis-ci = { repository = "gwihlidal/vk-mem-rs" } maintenance = { status = "actively-developed" } [dependencies] -ash = "0.37" +ash = { version = "0.37", default-features = false } bitflags = "1.2.1" [build-dependencies] @@ -45,7 +45,8 @@ opt-level = 3 codegen-units = 1 [features] -default = [] +default = ["loaded"] generate_bindings=["bindgen"] -link_vulkan=[] +linked=["ash/linked"] +loaded=["ash/loaded"] recording=[] diff --git a/build.rs b/build.rs index cba6e3b..64bf762 100644 --- a/build.rs +++ b/build.rs @@ -104,53 +104,9 @@ fn main() { build.compile("vma"); - link_vulkan(); generate_bindings("src/ffi.rs"); } -#[cfg(feature = "link_vulkan")] -fn link_vulkan() { - use std::path::PathBuf; - let target = env::var("TARGET").unwrap(); - if target.contains("windows") { - if let Ok(vulkan_sdk) = env::var("VULKAN_SDK") { - let mut vulkan_sdk_path = PathBuf::from(vulkan_sdk); - - if target.contains("x86_64") { - vulkan_sdk_path.push("Lib"); - } else { - vulkan_sdk_path.push("Lib32"); - } - - println!( - "cargo:rustc-link-search=native={}", - vulkan_sdk_path.to_str().unwrap() - ); - } - - println!("cargo:rustc-link-lib=dylib=vulkan-1"); - } else { - if target.contains("apple") { - if let Ok(vulkan_sdk) = env::var("VULKAN_SDK") { - let mut vulkan_sdk_path = PathBuf::from(vulkan_sdk); - vulkan_sdk_path.push("macOS/lib"); - println!( - "cargo:rustc-link-search=native={}", - vulkan_sdk_path.to_str().unwrap() - ); - } else { - let lib_path = "wrapper/macOS/lib"; - println!("cargo:rustc-link-search=native={}", lib_path); - } - - println!("cargo:rustc-link-lib=dylib=vulkan"); - } - } -} - -#[cfg(not(feature = "link_vulkan"))] -fn link_vulkan() {} - #[cfg(feature = "generate_bindings")] fn generate_bindings(output_file: &str) { let bindings = bindgen::Builder::default() diff --git a/src/lib.rs b/src/lib.rs index 92c0a9a..7a699a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -260,57 +260,60 @@ impl Allocator { panic!("VMA_DYNAMIC_VULKAN_FUNCTIONS is unsupported") } - let routed_functions = ffi::VmaVulkanFunctions { - vkGetInstanceProcAddr: get_instance_proc_addr_stub, - vkGetDeviceProcAddr: get_get_device_proc_stub, - vkGetPhysicalDeviceProperties: create_info - .instance - .fp_v1_0() - .get_physical_device_properties, - vkGetPhysicalDeviceMemoryProperties: create_info - .instance - .fp_v1_0() - .get_physical_device_memory_properties, - vkAllocateMemory: create_info.device.fp_v1_0().allocate_memory, - vkFreeMemory: create_info.device.fp_v1_0().free_memory, - vkMapMemory: create_info.device.fp_v1_0().map_memory, - vkUnmapMemory: create_info.device.fp_v1_0().unmap_memory, - vkFlushMappedMemoryRanges: create_info.device.fp_v1_0().flush_mapped_memory_ranges, - vkInvalidateMappedMemoryRanges: create_info - .device - .fp_v1_0() - .invalidate_mapped_memory_ranges, - vkBindBufferMemory: create_info.device.fp_v1_0().bind_buffer_memory, - vkBindImageMemory: create_info.device.fp_v1_0().bind_image_memory, - vkGetBufferMemoryRequirements: create_info - .device - .fp_v1_0() - .get_buffer_memory_requirements, - vkGetImageMemoryRequirements: create_info - .device - .fp_v1_0() - .get_image_memory_requirements, - vkCreateBuffer: create_info.device.fp_v1_0().create_buffer, - vkDestroyBuffer: create_info.device.fp_v1_0().destroy_buffer, - vkCreateImage: create_info.device.fp_v1_0().create_image, - vkDestroyImage: create_info.device.fp_v1_0().destroy_image, - vkCmdCopyBuffer: create_info.device.fp_v1_0().cmd_copy_buffer, - vkGetBufferMemoryRequirements2KHR: create_info - .device - .fp_v1_1() - .get_buffer_memory_requirements2, - vkGetImageMemoryRequirements2KHR: create_info - .device - .fp_v1_1() - .get_image_memory_requirements2, - vkBindBufferMemory2KHR: create_info.device.fp_v1_1().bind_buffer_memory2, - vkBindImageMemory2KHR: create_info.device.fp_v1_1().bind_image_memory2, - vkGetPhysicalDeviceMemoryProperties2KHR: create_info - .instance - .fp_v1_1() - .get_physical_device_memory_properties2, - }; - create_info.inner.pVulkanFunctions = &routed_functions; + #[cfg(feature = "loaded")] + { + let routed_functions = ffi::VmaVulkanFunctions { + vkGetInstanceProcAddr: get_instance_proc_addr_stub, + vkGetDeviceProcAddr: get_get_device_proc_stub, + vkGetPhysicalDeviceProperties: create_info + .instance + .fp_v1_0() + .get_physical_device_properties, + vkGetPhysicalDeviceMemoryProperties: create_info + .instance + .fp_v1_0() + .get_physical_device_memory_properties, + vkAllocateMemory: create_info.device.fp_v1_0().allocate_memory, + vkFreeMemory: create_info.device.fp_v1_0().free_memory, + vkMapMemory: create_info.device.fp_v1_0().map_memory, + vkUnmapMemory: create_info.device.fp_v1_0().unmap_memory, + vkFlushMappedMemoryRanges: create_info.device.fp_v1_0().flush_mapped_memory_ranges, + vkInvalidateMappedMemoryRanges: create_info + .device + .fp_v1_0() + .invalidate_mapped_memory_ranges, + vkBindBufferMemory: create_info.device.fp_v1_0().bind_buffer_memory, + vkBindImageMemory: create_info.device.fp_v1_0().bind_image_memory, + vkGetBufferMemoryRequirements: create_info + .device + .fp_v1_0() + .get_buffer_memory_requirements, + vkGetImageMemoryRequirements: create_info + .device + .fp_v1_0() + .get_image_memory_requirements, + vkCreateBuffer: create_info.device.fp_v1_0().create_buffer, + vkDestroyBuffer: create_info.device.fp_v1_0().destroy_buffer, + vkCreateImage: create_info.device.fp_v1_0().create_image, + vkDestroyImage: create_info.device.fp_v1_0().destroy_image, + vkCmdCopyBuffer: create_info.device.fp_v1_0().cmd_copy_buffer, + vkGetBufferMemoryRequirements2KHR: create_info + .device + .fp_v1_1() + .get_buffer_memory_requirements2, + vkGetImageMemoryRequirements2KHR: create_info + .device + .fp_v1_1() + .get_image_memory_requirements2, + vkBindBufferMemory2KHR: create_info.device.fp_v1_1().bind_buffer_memory2, + vkBindImageMemory2KHR: create_info.device.fp_v1_1().bind_image_memory2, + vkGetPhysicalDeviceMemoryProperties2KHR: create_info + .instance + .fp_v1_1() + .get_physical_device_memory_properties2, + }; + create_info.inner.pVulkanFunctions = &routed_functions; + } unsafe { let mut internal: ffi::VmaAllocator = mem::zeroed(); ffi_to_result(ffi::vmaCreateAllocator( From 53aa82678dc685e548fc2aa8f11f4e23ac35e62c Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Tue, 10 May 2022 23:46:39 -0700 Subject: [PATCH 04/23] update tests --- tests/mod.rs | 74 ++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/mod.rs b/tests/mod.rs index 9e5f007..85fd851 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -1,24 +1,24 @@ extern crate ash; extern crate vk_mem; -use ash::extensions::ext::DebugReport; -use std::os::raw::{c_char, c_void}; +use ash::{extensions::ext::DebugUtils, vk}; +use std::os::raw::c_void; fn extension_names() -> Vec<*const i8> { - vec![DebugReport::name().as_ptr()] + vec![DebugUtils::name().as_ptr()] } unsafe extern "system" fn vulkan_debug_callback( - _: ash::vk::DebugReportFlagsEXT, - _: ash::vk::DebugReportObjectTypeEXT, - _: u64, - _: usize, - _: i32, - _: *const c_char, - p_message: *const c_char, - _: *mut c_void, -) -> u32 { - println!("{:?}", ::std::ffi::CStr::from_ptr(p_message)); + _message_severity: ash::vk::DebugUtilsMessageSeverityFlagsEXT, + _message_types: ash::vk::DebugUtilsMessageTypeFlagsEXT, + p_callback_data: *const ash::vk::DebugUtilsMessengerCallbackDataEXT, + _p_user_data: *mut c_void, +) -> ash::vk::Bool32 { + let p_callback_data = &*p_callback_data; + println!( + "{:?}", + ::std::ffi::CStr::from_ptr(p_callback_data.p_message) + ); ash::vk::FALSE } @@ -27,8 +27,8 @@ pub struct TestHarness { pub instance: ash::Instance, pub device: ash::Device, pub physical_device: ash::vk::PhysicalDevice, - pub debug_callback: ash::vk::DebugReportCallbackEXT, - pub debug_report_loader: ash::extensions::ext::DebugReport, + pub debug_callback: ash::vk::DebugUtilsMessengerEXT, + pub debug_report_loader: ash::extensions::ext::DebugUtils, } impl Drop for TestHarness { @@ -37,7 +37,7 @@ impl Drop for TestHarness { self.device.device_wait_idle().unwrap(); self.device.destroy_device(None); self.debug_report_loader - .destroy_debug_report_callback(self.debug_callback, None); + .destroy_debug_utils_messenger(self.debug_callback, None); self.instance.destroy_instance(None); } } @@ -50,7 +50,7 @@ impl TestHarness { .application_version(0) .engine_name(&app_name) .engine_version(0) - .api_version(ash::vk::make_version(1, 0, 0)); + .api_version(ash::vk::make_api_version(0, 1, 0, 0)); let layer_names = [::std::ffi::CString::new("VK_LAYER_KHRONOS_validation").unwrap()]; let layers_names_raw: Vec<*const i8> = layer_names @@ -64,7 +64,6 @@ impl TestHarness { .enabled_layer_names(&layers_names_raw) .enabled_extension_names(&extension_names_raw); - let entry = unsafe { ash::Entry::load().unwrap() }; let instance: ash::Instance = unsafe { entry @@ -72,18 +71,18 @@ impl TestHarness { .expect("Instance creation error") }; - let debug_info = ash::vk::DebugReportCallbackCreateInfoEXT::builder() - .flags( - ash::vk::DebugReportFlagsEXT::ERROR - | ash::vk::DebugReportFlagsEXT::WARNING - | ash::vk::DebugReportFlagsEXT::PERFORMANCE_WARNING, + let debug_info = ash::vk::DebugUtilsMessengerCreateInfoEXT::builder() + .message_severity( + ash::vk::DebugUtilsMessageSeverityFlagsEXT::ERROR + | ash::vk::DebugUtilsMessageSeverityFlagsEXT::WARNING, ) - .pfn_callback(Some(vulkan_debug_callback)); + .message_type(vk::DebugUtilsMessageTypeFlagsEXT::GENERAL | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION) + .pfn_user_callback(Some(vulkan_debug_callback)); - let debug_report_loader = DebugReport::new(&entry, &instance); + let debug_report_loader = DebugUtils::new(&entry, &instance); let debug_callback = unsafe { debug_report_loader - .create_debug_report_callback(&debug_info, None) + .create_debug_utils_messenger(&debug_info, None) .unwrap() }; @@ -136,7 +135,8 @@ impl TestHarness { } pub fn create_allocator(&self) -> vk_mem::Allocator { - let create_info = vk_mem::AllocatorCreateInfo::new(&self.instance, &self.device, &self.physical_device); + let create_info = + vk_mem::AllocatorCreateInfo::new(&self.instance, &self.device, self.physical_device); vk_mem::Allocator::new(create_info).unwrap() } } @@ -156,7 +156,7 @@ fn create_allocator() { fn create_gpu_buffer() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); + let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); unsafe { let (buffer, allocation, allocation_info) = allocator @@ -180,10 +180,11 @@ fn create_gpu_buffer() { fn create_cpu_buffer_preferred() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new() + let allocation_info = vk_mem::AllocationCreateInfo::new() .required_flags(ash::vk::MemoryPropertyFlags::HOST_VISIBLE) - .preferred_flags(ash::vk::MemoryPropertyFlags::HOST_COHERENT - | ash::vk::MemoryPropertyFlags::HOST_CACHED) + .preferred_flags( + ash::vk::MemoryPropertyFlags::HOST_COHERENT | ash::vk::MemoryPropertyFlags::HOST_CACHED, + ) .flags(vk_mem::AllocationCreateFlags::MAPPED); unsafe { let (buffer, allocation, allocation_info) = allocator @@ -215,8 +216,9 @@ fn create_gpu_buffer_pool() { let mut allocation_info = vk_mem::AllocationCreateInfo::new() .required_flags(ash::vk::MemoryPropertyFlags::HOST_VISIBLE) - .preferred_flags(ash::vk::MemoryPropertyFlags::HOST_COHERENT - | ash::vk::MemoryPropertyFlags::HOST_CACHED) + .preferred_flags( + ash::vk::MemoryPropertyFlags::HOST_COHERENT | ash::vk::MemoryPropertyFlags::HOST_CACHED, + ) .flags(vk_mem::AllocationCreateFlags::MAPPED); unsafe { let memory_type_index = allocator @@ -245,8 +247,7 @@ fn create_gpu_buffer_pool() { fn test_gpu_stats() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new() - .usage(vk_mem::MemoryUsage::GpuOnly); + let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); unsafe { let stats_1 = allocator.calculate_stats().unwrap(); @@ -286,8 +287,7 @@ fn test_stats_string() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new() - .usage(vk_mem::MemoryUsage::GpuOnly); + let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); unsafe { let stats_1 = allocator.build_stats_string(true).unwrap(); From beac6d43f7e159a328bf51f9e78d6fae0a5e59e6 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 00:55:45 -0700 Subject: [PATCH 05/23] Upgrade VMA --- src/definitions.rs | 19 - src/ffi.rs | 755 +++++++++++++++++++---------------- src/lib.rs | 326 +++------------ vendor/VulkanMemoryAllocator | 2 +- 4 files changed, 480 insertions(+), 622 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index 42a1c1d..0092fa6 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -303,25 +303,6 @@ bitflags! { /// When using this flag, you must specify PoolCreateInfo::max_block_count == 1 (or 0 for default). const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT as u32; - /// Enables alternative, buddy allocation algorithm in this pool. - /// - /// It operates on a tree of blocks, each having size that is a power of two and - /// a half of its parent's size. Comparing to default algorithm, this one provides - /// faster allocation and deallocation and decreased external fragmentation, - /// at the expense of more memory wasted (internal fragmentation). - const BUDDY_ALGORITHM = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT as u32; - - /// \brief Enables alternative, Two-Level Segregated Fit (TLSF) allocation algorithm in this pool. - /// - /// This algorithm is based on 2-level lists dividing address space into smaller - /// chunks. The first level is aligned to power of two which serves as buckets for requested - /// memory to fall into, and the second level is lineary subdivided into lists of free memory. - /// This algorithm aims to achieve bounded response time even in the worst case scenario. - /// Allocation time can be sometimes slightly longer than compared to other algorithms - /// but in return the application can avoid stalls in case of fragmentation, giving - /// predictable results, suitable for real-time use cases. - const TLSF_ALGORITHM_BIT = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_TLSF_ALGORITHM_BIT as u32; - /// Bit mask to extract only `*_ALGORITHM` bits from entire set of flags. const ALGORITHM_MASK = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_ALGORITHM_MASK as u32; } diff --git a/src/ffi.rs b/src/ffi.rs index 0e28be4..537534b 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -122,6 +122,7 @@ pub enum VmaAllocatorCreateFlagBits { #[doc = "For more details, see the documentation of the VK_EXT_memory_priority extension."] VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, } +#[doc = " See #VmaAllocatorCreateFlagBits."] pub type VmaAllocatorCreateFlags = Flags; #[repr(i32)] #[doc = " \\brief Intended usage of the allocated memory."] @@ -130,62 +131,68 @@ pub enum VmaMemoryUsage { #[doc = " No intended memory usage specified."] #[doc = "Use other members of VmaAllocationCreateInfo to specify your requirements."] VMA_MEMORY_USAGE_UNKNOWN = 0, - #[doc = " Memory will be used on device only, so fast access from the device is preferred."] - #[doc = "It usually means device-local GPU (video) memory."] - #[doc = "No need to be mappable on host."] - #[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`."] - #[doc = ""] - #[doc = "Usage:"] - #[doc = ""] - #[doc = "- Resources written and read by device, e.g. images used as attachments."] - #[doc = "- Resources transferred from host once (immutable) or infrequently and read by"] - #[doc = "device multiple times, e.g. textures to be sampled, vertex buffers, uniform"] - #[doc = "(constant) buffers, and majority of other types of resources used on GPU."] - #[doc = ""] - #[doc = "Allocation may still end up in `HOST_VISIBLE` memory on some implementations."] - #[doc = "In such case, you are free to map it."] - #[doc = "You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type."] + #[doc = "\\deprecated Obsolete, preserved for backward compatibility."] + #[doc = "Prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`."] VMA_MEMORY_USAGE_GPU_ONLY = 1, - #[doc = " Memory will be mappable on host."] - #[doc = "It usually means CPU (system) memory."] - #[doc = "Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`."] - #[doc = "CPU access is typically uncached. Writes may be write-combined."] - #[doc = "Resources created in this pool may still be accessible to the device, but access to them can be slow."] - #[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`."] - #[doc = ""] - #[doc = "Usage: Staging copy of resources used as transfer source."] + #[doc = "\\deprecated Obsolete, preserved for backward compatibility."] + #[doc = "Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`."] VMA_MEMORY_USAGE_CPU_ONLY = 2, - #[doc = "Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU."] - #[doc = "CPU access is typically uncached. Writes may be write-combined."] - #[doc = ""] - #[doc = "Usage: Resources written frequently by host (dynamic), read by device. E.g. textures (with LINEAR layout), vertex buffers, uniform buffers updated every frame or every draw call."] + #[doc = "\\deprecated Obsolete, preserved for backward compatibility."] + #[doc = "Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`."] VMA_MEMORY_USAGE_CPU_TO_GPU = 3, - #[doc = " Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached."] - #[doc = "It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`."] - #[doc = ""] - #[doc = "Usage:"] - #[doc = ""] - #[doc = "- Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping."] - #[doc = "- Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection."] + #[doc = "\\deprecated Obsolete, preserved for backward compatibility."] + #[doc = "Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`."] VMA_MEMORY_USAGE_GPU_TO_CPU = 4, - #[doc = " CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`."] - #[doc = ""] - #[doc = "Usage: Staging copy of resources moved from GPU memory to CPU memory as part"] - #[doc = "of custom paging/residency mechanism, to be moved back to GPU memory when needed."] + #[doc = "\\deprecated Obsolete, preserved for backward compatibility."] + #[doc = "Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`."] VMA_MEMORY_USAGE_CPU_COPY = 5, - #[doc = " Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] + #[doc = "Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] #[doc = "Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation."] #[doc = ""] #[doc = "Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`."] #[doc = ""] #[doc = "Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, - #[doc = " Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`."] - #[doc = "Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation."] - #[doc = ""] - #[doc = "Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`."] - #[doc = ""] - #[doc = "Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT."] + #[doc = "Selects best memory type automatically."] + #[doc = "This flag is recommended for most common use cases."] + #[doc = ""] + #[doc = "When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),"] + #[doc = "you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT"] + #[doc = "in VmaAllocationCreateInfo::flags."] + #[doc = ""] + #[doc = "It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g."] + #[doc = "vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()"] + #[doc = "and not with generic memory allocation functions."] + VMA_MEMORY_USAGE_AUTO = 7, + #[doc = "Selects best memory type automatically with preference for GPU (device) memory."] + #[doc = ""] + #[doc = "When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),"] + #[doc = "you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT"] + #[doc = "in VmaAllocationCreateInfo::flags."] + #[doc = ""] + #[doc = "It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g."] + #[doc = "vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()"] + #[doc = "and not with generic memory allocation functions."] + VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE = 8, + #[doc = "Selects best memory type automatically with preference for CPU (host) memory."] + #[doc = ""] + #[doc = "When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),"] + #[doc = "you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT"] + #[doc = "in VmaAllocationCreateInfo::flags."] + #[doc = ""] + #[doc = "It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g."] + #[doc = "vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()"] + #[doc = "and not with generic memory allocation functions."] + VMA_MEMORY_USAGE_AUTO_PREFER_HOST = 9, + #[doc = "Selects best memory type automatically with preference for CPU (host) memory."] + #[doc = ""] + #[doc = "When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),"] + #[doc = "you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT"] + #[doc = "in VmaAllocationCreateInfo::flags."] + #[doc = ""] + #[doc = "It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g."] + #[doc = "vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()"] + #[doc = "and not with generic memory allocation functions."] VMA_MEMORY_USAGE_MAX_ENUM = 2147483647, } impl VmaAllocationCreateFlagBits { @@ -211,8 +218,6 @@ pub enum VmaAllocationCreateFlagBits { #[doc = ""] #[doc = "You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and"] #[doc = "#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense."] - #[doc = ""] - #[doc = "If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored."] VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 2, #[doc = " \\brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it."] #[doc = ""] @@ -224,13 +229,11 @@ pub enum VmaAllocationCreateFlagBits { #[doc = "(`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that"] #[doc = "support it (e.g. Intel GPU)."] VMA_ALLOCATION_CREATE_MAPPED_BIT = 4, - #[doc = " \\deprecated Removed. Do not use."] - VMA_ALLOCATION_CREATE_RESERVED_1_BIT = 8, - #[doc = " \\deprecated Removed. Do not use."] - VMA_ALLOCATION_CREATE_RESERVED_2_BIT = 16, - #[doc = " Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a"] + #[doc = " \\deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead."] + #[doc = ""] + #[doc = "Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a"] #[doc = "null-terminated string. Instead of copying pointer value, a local copy of the"] - #[doc = "string is made and stored in allocation's `pUserData`. The string is automatically"] + #[doc = "string is made and stored in allocation's `pName`. The string is automatically"] #[doc = "freed together with the allocation. It is also used in vmaBuildStatsString()."] VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 32, #[doc = " Allocation will be created from upper stack in a double stack pool."] @@ -241,6 +244,10 @@ pub enum VmaAllocationCreateFlagBits { #[doc = "It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions."] #[doc = "The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage()."] #[doc = "Otherwise it is ignored."] + #[doc = ""] + #[doc = "If you want to make sure the new buffer/image is not tied to the new memory allocation"] + #[doc = "through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block,"] + #[doc = "use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT."] VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 128, #[doc = " Create allocation only if additional device memory required for it, if any, won't exceed"] #[doc = "memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`."] @@ -250,6 +257,40 @@ pub enum VmaAllocationCreateFlagBits { #[doc = "Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified."] #[doc = "Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors."] VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 512, + #[doc = "Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT)."] + #[doc = ""] + #[doc = "- If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,"] + #[doc = "you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect."] + #[doc = "- If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`."] + #[doc = "This includes allocations created in \\ref custom_memory_pools."] + #[doc = ""] + #[doc = "Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number,"] + #[doc = "never read or accessed randomly, so a memory type can be selected that is uncached and write-combined."] + #[doc = ""] + #[doc = "\\warning Violating this declaration may work correctly, but will likely be very slow."] + #[doc = "Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;`"] + #[doc = "Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once."] + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 1024, + #[doc = "Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT)."] + #[doc = ""] + #[doc = "- If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,"] + #[doc = "you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect."] + #[doc = "- If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`."] + #[doc = "This includes allocations created in \\ref custom_memory_pools."] + #[doc = ""] + #[doc = "Declares that mapped memory can be read, written, and accessed in random order,"] + #[doc = "so a `HOST_CACHED` memory type is required."] + VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = 2048, + #[doc = "Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,"] + #[doc = "it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected"] + #[doc = "if it may improve performance."] + #[doc = ""] + #[doc = "By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type"] + #[doc = "(e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some \"staging\" buffer and"] + #[doc = "issue an explicit transfer to write/read your data."] + #[doc = "To prepare for this possibility, don't forget to add appropriate flags like"] + #[doc = "`VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image."] + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT = 4096, #[doc = " Allocation strategy that chooses smallest possible free range for the allocation"] #[doc = "to minimize memory usage and fragmentation, possibly at the expense of allocation time."] VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 65536, @@ -257,12 +298,21 @@ pub enum VmaAllocationCreateFlagBits { #[doc = "not necessarily in terms of the smallest offset but the one that is easiest and fastest to find"] #[doc = "to minimize allocation time, possibly at the expense of allocation quality."] VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 131072, + #[doc = " Allocation strategy that chooses always the lowest offset in available space."] + #[doc = "This is not the most efficient strategy but achieves highly packed data."] + #[doc = "Used internally by defragmentation, not recomended in typical usage."] + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = 262144, #[doc = " A bit mask to extract only `STRATEGY` bits from entire set of flags."] - VMA_ALLOCATION_CREATE_STRATEGY_MASK = 196608, + VMA_ALLOCATION_CREATE_STRATEGY_MASK = 458752, #[doc = " A bit mask to extract only `STRATEGY` bits from entire set of flags."] VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, } +#[doc = " See #VmaAllocationCreateFlagBits."] pub type VmaAllocationCreateFlags = Flags; +impl VmaPoolCreateFlagBits { + pub const VMA_POOL_CREATE_ALGORITHM_MASK: VmaPoolCreateFlagBits = + VmaPoolCreateFlagBits::VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT; +} #[repr(i32)] #[doc = " Flags to be passed as VmaPoolCreateInfo::flags."] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -295,40 +345,46 @@ pub enum VmaPoolCreateFlagBits { #[doc = "ring buffer, and double stack."] #[doc = "For details, see documentation chapter \\ref linear_algorithm."] VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 4, - #[doc = " \\brief Enables alternative, buddy allocation algorithm in this pool."] - #[doc = ""] - #[doc = "It operates on a tree of blocks, each having size that is a power of two and"] - #[doc = "a half of its parent's size. Comparing to default algorithm, this one provides"] - #[doc = "faster allocation and deallocation and decreased external fragmentation,"] - #[doc = "at the expense of more memory wasted (internal fragmentation)."] - #[doc = "For details, see documentation chapter \\ref buddy_algorithm."] - VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 8, - #[doc = " \\brief Enables alternative, Two-Level Segregated Fit (TLSF) allocation algorithm in this pool."] - #[doc = ""] - #[doc = "This algorithm is based on 2-level lists dividing address space into smaller"] - #[doc = "chunks. The first level is aligned to power of two which serves as buckets for requested"] - #[doc = "memory to fall into, and the second level is lineary subdivided into lists of free memory."] - #[doc = "This algorithm aims to achieve bounded response time even in the worst case scenario."] - #[doc = "Allocation time can be sometimes slightly longer than compared to other algorithms"] - #[doc = "but in return the application can avoid stalls in case of fragmentation, giving"] - #[doc = "predictable results, suitable for real-time use cases."] - VMA_POOL_CREATE_TLSF_ALGORITHM_BIT = 16, - #[doc = " Bit mask to extract only `ALGORITHM` bits from entire set of flags."] - VMA_POOL_CREATE_ALGORITHM_MASK = 28, #[doc = " Bit mask to extract only `ALGORITHM` bits from entire set of flags."] VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, } #[doc = " Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits."] pub type VmaPoolCreateFlags = Flags; #[repr(i32)] -#[doc = " Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use."] +#[doc = " Flags to be passed as VmaDefragmentationInfo::flags."] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum VmaDefragmentationFlagBits { - VMA_DEFRAGMENTATION_FLAG_INCREMENTAL = 1, + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT = 1, + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT = 2, + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT = 4, + #[doc = " \\brief Use the most roboust algorithm at the cost of time to compute and number of copies to make."] + #[doc = "Only available when bufferImageGranularity is greater than 1, since it aims to reduce"] + #[doc = "alignment issues between different types of resources."] + #[doc = "Otherwise falls back to same behavior as #VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT."] + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 8, + #[doc = " A bit mask to extract only `ALGORITHM` bits from entire set of flags."] + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK = 15, + #[doc = " A bit mask to extract only `ALGORITHM` bits from entire set of flags."] VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 2147483647, } +#[doc = " See #VmaDefragmentationFlagBits."] pub type VmaDefragmentationFlags = Flags; #[repr(i32)] +#[doc = " Operation performed on single defragmentation move. See structure #VmaDefragmentationMove."] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum VmaDefragmentationMoveOperation { + #[doc = " Buffer/image has been recreated at `dstTmpAllocation`, data has been copied, old buffer/image has been destroyed. `srcAllocation` should be changed to point to the new place. This is the default value set by vmaBeginDefragmentationPass()."] + VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY = 0, + #[doc = " Set this value if you cannot move the allocation. New place reserved at `dstTmpAllocation` will be freed. `srcAllocation` will remain unchanged."] + VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1, + #[doc = " Set this value if you decide to abandon the allocation and you destroyed the buffer/image. New place reserved at `dstTmpAllocation` will be freed, along with `srcAllocation`, which will be destroyed."] + VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2, +} +impl VmaVirtualBlockCreateFlagBits { + pub const VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK: VmaVirtualBlockCreateFlagBits = + VmaVirtualBlockCreateFlagBits::VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT; +} +#[repr(i32)] #[doc = " Flags to be passed as VmaVirtualBlockCreateInfo::flags."] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum VmaVirtualBlockCreateFlagBits { @@ -343,26 +399,6 @@ pub enum VmaVirtualBlockCreateFlagBits { #[doc = "ring buffer, and double stack."] #[doc = "For details, see documentation chapter \\ref linear_algorithm."] VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 1, - #[doc = " \\brief Enables alternative, buddy allocation algorithm in this virtual block."] - #[doc = ""] - #[doc = "It operates on a tree of blocks, each having size that is a power of two and"] - #[doc = "a half of its parent's size. Comparing to default algorithm, this one provides"] - #[doc = "faster allocation and deallocation and decreased external fragmentation,"] - #[doc = "at the expense of more memory wasted (internal fragmentation)."] - #[doc = "For details, see documentation chapter \\ref buddy_algorithm."] - VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT = 2, - #[doc = " \\brief Enables alternative, TLSF allocation algorithm in virtual block."] - #[doc = ""] - #[doc = "This algorithm is based on 2-level lists dividing address space into smaller"] - #[doc = "chunks. The first level is aligned to power of two which serves as buckets for requested"] - #[doc = "memory to fall into, and the second level is lineary subdivided into lists of free memory."] - #[doc = "This algorithm aims to achieve bounded response time even in the worst case scenario."] - #[doc = "Allocation time can be sometimes slightly longer than compared to other algorithms"] - #[doc = "but in return the application can avoid stalls in case of fragmentation, giving"] - #[doc = "predictable results, suitable for real-time use cases."] - VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT = 4, - #[doc = " \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags."] - VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK = 7, #[doc = " \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags."] VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 2147483647, } @@ -380,10 +416,13 @@ pub enum VmaVirtualAllocationCreateFlagBits { VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 65536, #[doc = " \\brief Allocation strategy that tries to minimize allocation time."] VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 131072, + #[doc = " Allocation strategy that chooses always the lowest offset in available space."] + #[doc = "This is not the most efficient strategy but achieves highly packed data."] + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = 262144, #[doc = " \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags."] #[doc = ""] #[doc = "These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits."] - VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = 196608, + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = 458752, #[doc = " \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags."] #[doc = ""] #[doc = "These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits."] @@ -498,6 +537,10 @@ pub struct VmaVulkanFunctions { #[doc = " Fetch \"vkBindImageMemory2\" on Vulkan >= 1.1, fetch \"vkBindImageMemory2KHR\" when using VK_KHR_bind_memory2 extension."] pub vkBindImageMemory2KHR: PFN_vkBindImageMemory2, pub vkGetPhysicalDeviceMemoryProperties2KHR: PFN_vkGetPhysicalDeviceMemoryProperties2, + #[doc = " Fetch from \"vkGetDeviceBufferMemoryRequirements\" on Vulkan >= 1.3, but you can also fetch it from \"vkGetDeviceBufferMemoryRequirementsKHR\" if you enabled extension VK_KHR_maintenance4."] + pub vkGetDeviceBufferMemoryRequirements: PFN_vkGetDeviceBufferMemoryRequirements, + #[doc = " Fetch from \"vkGetDeviceImageMemoryRequirements\" on Vulkan >= 1.3, but you can also fetch it from \"vkGetDeviceImageMemoryRequirementsKHR\" if you enabled extension VK_KHR_maintenance4."] + pub vkGetDeviceImageMemoryRequirements: PFN_vkGetDeviceImageMemoryRequirements, } #[doc = " Description of a Allocator to be created."] #[repr(C)] @@ -585,64 +628,99 @@ pub struct VmaAllocatorInfo { #[doc = "This is the same value as has been passed through VmaAllocatorCreateInfo::device."] pub device: Device, } -#[doc = " Calculated statistics of memory usage in entire allocator."] +#[doc = " \\brief Calculated statistics of memory usage e.g. in a specific memory type, heap, custom pool, or total."] +#[doc = ""] +#[doc = "These are fast to calculate."] +#[doc = "See functions: vmaGetHeapBudgets(), vmaGetPoolStatistics()."] #[repr(C)] -pub struct VmaStatInfo { - #[doc = " Number of `VkDeviceMemory` Vulkan memory blocks allocated."] +pub struct VmaStatistics { + #[doc = " \\brief Number of `VkDeviceMemory` objects - Vulkan memory blocks allocated."] pub blockCount: u32, - #[doc = " Number of #VmaAllocation allocation objects allocated."] + #[doc = " \\brief Number of #VmaAllocation objects allocated."] + #[doc = ""] + #[doc = "Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`."] pub allocationCount: u32, + #[doc = " \\brief Number of bytes allocated in `VkDeviceMemory` blocks."] + #[doc = ""] + #[doc = "\\note To avoid confusion, please be aware that what Vulkan calls an \"allocation\" - a whole `VkDeviceMemory` object"] + #[doc = "(e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a \"block\" in VMA, while VMA calls"] + #[doc = "\"allocation\" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image."] + pub blockBytes: DeviceSize, + #[doc = " \\brief Total number of bytes occupied by all #VmaAllocation objects."] + #[doc = ""] + #[doc = "Always less or equal than `blockBytes`."] + #[doc = "Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan"] + #[doc = "but unused by any #VmaAllocation."] + pub allocationBytes: DeviceSize, +} +#[doc = " \\brief More detailed statistics than #VmaStatistics."] +#[doc = ""] +#[doc = "These are slower to calculate. Use for debugging purposes."] +#[doc = "See functions: vmaCalculateStatistics(), vmaCalculatePoolStatistics()."] +#[doc = ""] +#[doc = "Previous version of the statistics API provided averages, but they have been removed"] +#[doc = "because they can be easily calculated as:"] +#[doc = ""] +#[doc = "\\code"] +#[doc = "VkDeviceSize allocationSizeAvg = detailedStats.statistics.allocationBytes / detailedStats.statistics.allocationCount;"] +#[doc = "VkDeviceSize unusedBytes = detailedStats.statistics.blockBytes - detailedStats.statistics.allocationBytes;"] +#[doc = "VkDeviceSize unusedRangeSizeAvg = unusedBytes / detailedStats.unusedRangeCount;"] +#[doc = "\\endcode"] +#[repr(C)] +pub struct VmaDetailedStatistics { + #[doc = " Basic statistics."] + pub statistics: VmaStatistics, #[doc = " Number of free ranges of memory between allocations."] pub unusedRangeCount: u32, - #[doc = " Total number of bytes occupied by all allocations."] - pub usedBytes: DeviceSize, - #[doc = " Total number of bytes occupied by unused ranges."] - pub unusedBytes: DeviceSize, + #[doc = " Smallest allocation size. `VK_WHOLE_SIZE` if there are 0 allocations."] pub allocationSizeMin: DeviceSize, - pub allocationSizeAvg: DeviceSize, + #[doc = " Largest allocation size. 0 if there are 0 allocations."] pub allocationSizeMax: DeviceSize, + #[doc = " Smallest empty range size. `VK_WHOLE_SIZE` if there are 0 empty ranges."] pub unusedRangeSizeMin: DeviceSize, - pub unusedRangeSizeAvg: DeviceSize, + #[doc = " Largest empty range size. 0 if there are 0 empty ranges."] pub unusedRangeSizeMax: DeviceSize, } -#[doc = " General statistics from current state of Allocator."] +#[doc = " \\brief General statistics from current state of the Allocator -"] +#[doc = "total memory usage across all memory heaps and types."] +#[doc = ""] +#[doc = "These are slower to calculate. Use for debugging purposes."] +#[doc = "See function vmaCalculateStatistics()."] #[repr(C)] -pub struct VmaStats { - pub memoryType: [VmaStatInfo; 32usize], - pub memoryHeap: [VmaStatInfo; 16usize], - pub total: VmaStatInfo, +pub struct VmaTotalStatistics { + pub memoryType: [VmaDetailedStatistics; 32usize], + pub memoryHeap: [VmaDetailedStatistics; 16usize], + pub total: VmaDetailedStatistics, } -#[doc = " Statistics of current memory usage and available budget, in bytes, for specific memory heap."] +#[doc = " \\brief Statistics of current memory usage and available budget for a specific memory heap."] +#[doc = ""] +#[doc = "These are fast to calculate."] +#[doc = "See function vmaGetHeapBudgets()."] #[repr(C)] pub struct VmaBudget { - #[doc = " \\brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes."] - pub blockBytes: DeviceSize, - #[doc = " \\brief Sum size of all allocations created in particular heap, in bytes."] - #[doc = ""] - #[doc = "Usually less or equal than `blockBytes`."] - #[doc = "Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused -"] - #[doc = "available for new allocations or wasted due to fragmentation."] - pub allocationBytes: DeviceSize, + #[doc = " \\brief Statistics fetched from the library."] + pub statistics: VmaStatistics, #[doc = " \\brief Estimated current memory usage of the program, in bytes."] #[doc = ""] - #[doc = "Fetched from system using `VK_EXT_memory_budget` extension if enabled."] + #[doc = "Fetched from system using VK_EXT_memory_budget extension if enabled."] #[doc = ""] - #[doc = "It might be different than `blockBytes` (usually higher) due to additional implicit objects"] + #[doc = "It might be different than `statistics.blockBytes` (usually higher) due to additional implicit objects"] #[doc = "also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or"] #[doc = "`VkDeviceMemory` blocks allocated outside of this library, if any."] pub usage: DeviceSize, #[doc = " \\brief Estimated amount of memory available to the program, in bytes."] #[doc = ""] - #[doc = "Fetched from system using `VK_EXT_memory_budget` extension if enabled."] + #[doc = "Fetched from system using VK_EXT_memory_budget extension if enabled."] #[doc = ""] #[doc = "It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors"] - #[doc = "external to the program, like other programs also consuming system resources."] + #[doc = "external to the program, decided by the operating system."] #[doc = "Difference `budget - usage` is the amount of additional memory that can probably"] #[doc = "be allocated without problems. Exceeding the budget may result in various problems."] pub budget: DeviceSize, } -#[doc = "\\addtogroup group_alloc"] -#[doc = "@{"] +#[doc = " \\brief Parameters of new #VmaAllocation."] +#[doc = ""] +#[doc = "To be used with functions like vmaCreateBuffer(), vmaCreateImage(), and many others."] #[repr(C)] pub struct VmaAllocationCreateInfo { #[doc = " Use #VmaAllocationCreateFlagBits enum."] @@ -735,20 +813,6 @@ pub struct VmaPoolCreateInfo { #[doc = "can be attached automatically by this library when using other, more convenient of its features."] pub pMemoryAllocateNext: *mut ::std::os::raw::c_void, } -#[doc = " Describes parameter of existing #VmaPool."] -#[repr(C)] -pub struct VmaPoolStats { - #[doc = " \\brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes."] - pub size: DeviceSize, - #[doc = " \\brief Total number of bytes in the pool not used by any #VmaAllocation."] - pub unusedSize: DeviceSize, - #[doc = " \\brief Number of #VmaAllocation objects created from this pool that were not destroyed."] - pub allocationCount: usize, - #[doc = " \\brief Number of continuous memory ranges in the pool not used by any #VmaAllocation."] - pub unusedRangeCount: usize, - #[doc = " \\brief Number of `VkDeviceMemory` blocks allocated for this pool."] - pub blockCount: usize, -} #[doc = " Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo()."] #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -761,7 +825,7 @@ pub struct VmaAllocationInfo { #[doc = ""] #[doc = "Same memory object can be shared by multiple allocations."] #[doc = ""] - #[doc = "It can change after call to vmaDefragment() if this allocation is passed to the function."] + #[doc = "It can change after the allocation is moved during \\ref defragmentation."] pub deviceMemory: DeviceMemory, #[doc = " \\brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation."] #[doc = ""] @@ -770,7 +834,7 @@ pub struct VmaAllocationInfo { #[doc = "not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation"] #[doc = "and apply this offset automatically."] #[doc = ""] - #[doc = "It can change after call to vmaDefragment() if this allocation is passed to the function."] + #[doc = "It can change after the allocation is moved during \\ref defragmentation."] pub offset: DeviceSize, #[doc = " \\brief Size of this allocation, in bytes."] #[doc = ""] @@ -788,106 +852,88 @@ pub struct VmaAllocationInfo { #[doc = "created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null."] #[doc = ""] #[doc = "It can change after call to vmaMapMemory(), vmaUnmapMemory()."] - #[doc = "It can also change after call to vmaDefragment() if this allocation is passed to the function."] + #[doc = "It can also change after the allocation is moved during \\ref defragmentation."] pub pMappedData: *mut ::std::os::raw::c_void, #[doc = " \\brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData()."] #[doc = ""] #[doc = "It can change after call to vmaSetAllocationUserData() for this allocation."] pub pUserData: *mut ::std::os::raw::c_void, + #[doc = " \\brief Custom allocation name that was set with vmaSetAllocationName()."] + #[doc = ""] + #[doc = "It can change after call to vmaSetAllocationName() for this allocation."] + #[doc = ""] + #[doc = "Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with"] + #[doc = "additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]."] + pub pName: *const ::std::os::raw::c_char, } #[doc = " \\brief Parameters for defragmentation."] #[doc = ""] -#[doc = "To be used with function vmaDefragmentationBegin()."] +#[doc = "To be used with function vmaBeginDefragmentation()."] #[repr(C)] -pub struct VmaDefragmentationInfo2 { - #[doc = " \\brief Reserved for future use. Should be 0."] +pub struct VmaDefragmentationInfo { + #[doc = " \\brief Use combination of #VmaDefragmentationFlagBits."] pub flags: VmaDefragmentationFlags, - #[doc = " \\brief Number of allocations in `pAllocations` array."] - pub allocationCount: u32, - #[doc = " \\brief Pointer to array of allocations that can be defragmented."] - #[doc = ""] - #[doc = "The array should have `allocationCount` elements."] - #[doc = "The array should not contain nulls."] - #[doc = "Elements in the array should be unique - same allocation cannot occur twice."] - #[doc = "All allocations not present in this array are considered non-moveable during this defragmentation."] - pub pAllocations: *mut VmaAllocation, - #[doc = " \\brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation."] - #[doc = ""] - #[doc = "The array should have `allocationCount` elements."] - #[doc = "You can pass null if you are not interested in this information."] - pub pAllocationsChanged: *mut Bool32, - #[doc = " \\brief Numer of pools in `pPools` array."] - pub poolCount: u32, - #[doc = " \\brief Either null or pointer to array of pools to be defragmented."] - #[doc = ""] - #[doc = "All the allocations in the specified pools can be moved during defragmentation"] - #[doc = "and there is no way to check if they were really moved as in `pAllocationsChanged`,"] - #[doc = "so you must query all the allocations in all these pools for new `VkDeviceMemory`"] - #[doc = "and offset using vmaGetAllocationInfo() if you might need to recreate buffers"] - #[doc = "and images bound to them."] - #[doc = ""] - #[doc = "The array should have `poolCount` elements."] - #[doc = "The array should not contain nulls."] - #[doc = "Elements in the array should be unique - same pool cannot occur twice."] - #[doc = ""] - #[doc = "Using this array is equivalent to specifying all allocations from the pools in `pAllocations`."] - #[doc = "It might be more efficient."] - pub pPools: *mut VmaPool, - #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`."] - #[doc = ""] - #[doc = "`VK_WHOLE_SIZE` means no limit."] - pub maxCpuBytesToMove: DeviceSize, - #[doc = " \\brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`."] - #[doc = ""] - #[doc = "`UINT32_MAX` means no limit."] - pub maxCpuAllocationsToMove: u32, - #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`."] - #[doc = ""] - #[doc = "`VK_WHOLE_SIZE` means no limit."] - pub maxGpuBytesToMove: DeviceSize, - #[doc = " \\brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`."] - #[doc = ""] - #[doc = "`UINT32_MAX` means no limit."] - pub maxGpuAllocationsToMove: u32, - #[doc = " \\brief Optional. Command buffer where GPU copy commands will be posted."] - #[doc = ""] - #[doc = "If not null, it must be a valid command buffer handle that supports Transfer queue type."] - #[doc = "It must be in the recording state and outside of a render pass instance."] - #[doc = "You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd()."] - #[doc = ""] - #[doc = "Passing null means that only CPU defragmentation will be performed."] - pub commandBuffer: CommandBuffer, + #[doc = " \\brief Custom pool to be defragmented."] + #[doc = ""] + #[doc = "If null then default pools will undergo defragmentation process."] + pub pool: VmaPool, + #[doc = " \\brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places."] + #[doc = ""] + #[doc = "`0` means no limit."] + pub maxBytesPerPass: DeviceSize, + #[doc = " \\brief Maximum number of allocations that can be moved during single pass to a different place."] + #[doc = ""] + #[doc = "`0` means no limit."] + pub maxAllocationsPerPass: u32, } +#[doc = " Single move of an allocation to be done for defragmentation."] #[repr(C)] -pub struct VmaDefragmentationPassMoveInfo { - pub allocation: VmaAllocation, - pub memory: DeviceMemory, - pub offset: DeviceSize, +#[derive(Debug, Copy, Clone)] +pub struct VmaDefragmentationMove { + #[doc = " Operation to be performed on the allocation by vmaEndDefragmentationPass(). Default value is #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it."] + pub operation: VmaDefragmentationMoveOperation, + #[doc = " Allocation that should be moved."] + pub srcAllocation: VmaAllocation, + #[doc = " \\brief Temporary allocation pointing to destination memory that will replace `srcAllocation`."] + #[doc = ""] + #[doc = "\\warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass,"] + #[doc = "to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory()."] + #[doc = "vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory."] + pub dstTmpAllocation: VmaAllocation, } #[doc = " \\brief Parameters for incremental defragmentation steps."] #[doc = ""] #[doc = "To be used with function vmaBeginDefragmentationPass()."] #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct VmaDefragmentationPassInfo { +pub struct VmaDefragmentationPassMoveInfo { + #[doc = " Number of elements in the `pMoves` array."] pub moveCount: u32, - pub pMoves: *mut VmaDefragmentationPassMoveInfo, -} -#[doc = " \\brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment()."] -#[doc = ""] -#[doc = "\\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead."] -#[repr(C)] -pub struct VmaDefragmentationInfo { - #[doc = " \\brief Maximum total numbers of bytes that can be copied while moving allocations to different places."] + #[doc = " \\brief Array of moves to be performed by the user in the current defragmentation pass."] #[doc = ""] - #[doc = "Default is `VK_WHOLE_SIZE`, which means no limit."] - pub maxBytesToMove: DeviceSize, - #[doc = " \\brief Maximum number of allocations that can be moved to different place."] + #[doc = "Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass()."] #[doc = ""] - #[doc = "Default is `UINT32_MAX`, which means no limit."] - pub maxAllocationsToMove: u32, + #[doc = "For each element, you should:"] + #[doc = ""] + #[doc = "1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset."] + #[doc = "2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`."] + #[doc = "3. Make sure these commands finished executing on the GPU."] + #[doc = "4. Destroy the old buffer/image."] + #[doc = ""] + #[doc = "Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass()."] + #[doc = "After this call, the allocation will point to the new place in memory."] + #[doc = ""] + #[doc = "Alternatively, if you cannot move specific allocation, you can set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE."] + #[doc = ""] + #[doc = "Alternatively, if you decide you want to completely remove the allocation:"] + #[doc = ""] + #[doc = "1. Destroy its buffer/image."] + #[doc = "2. Set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY."] + #[doc = ""] + #[doc = "Then, after vmaEndDefragmentationPass() the allocation will be freed."] + pub pMoves: *mut VmaDefragmentationMove, } -#[doc = " Statistics returned by function vmaDefragment()."] +#[doc = " Statistics returned for defragmentation process in function vmaEndDefragmentation()."] #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct VmaDefragmentationStats { @@ -1002,21 +1048,22 @@ extern "C" { #[doc = " \\brief Retrieves statistics from current state of the Allocator."] #[doc = ""] #[doc = "This function is called \"calculate\" not \"get\" because it has to traverse all"] - #[doc = "internal data structures, so it may be quite slow. For faster but more brief statistics"] - #[doc = "suitable to be called every frame or every allocation, use vmaGetHeapBudgets()."] + #[doc = "internal data structures, so it may be quite slow. Use it for debugging purposes."] + #[doc = "For faster but more brief statistics suitable to be called every frame or every allocation,"] + #[doc = "use vmaGetHeapBudgets()."] #[doc = ""] #[doc = "Note that when using allocator from multiple threads, returned information may immediately"] #[doc = "become outdated."] - pub fn vmaCalculateStats(allocator: VmaAllocator, pStats: *mut VmaStats); + pub fn vmaCalculateStatistics(allocator: VmaAllocator, pStats: *mut VmaTotalStatistics); } extern "C" { - #[doc = " \\brief Retrieves information about current memory budget for all memory heaps."] + #[doc = " \\brief Retrieves information about current memory usage and budget for all memory heaps."] #[doc = ""] #[doc = "\\param allocator"] #[doc = "\\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used."] #[doc = ""] #[doc = "This function is called \"get\" not \"calculate\" because it is very fast, suitable to be called"] - #[doc = "every frame or every allocation. For more detailed statistics use vmaCalculateStats()."] + #[doc = "every frame or every allocation. For more detailed statistics use vmaCalculateStatistics()."] #[doc = ""] #[doc = "Note that when using allocator from multiple threads, returned information may immediately"] #[doc = "become outdated."] @@ -1049,12 +1096,6 @@ extern "C" { #[doc = ""] #[doc = "It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex."] #[doc = "It internally creates a temporary, dummy buffer that never has memory bound."] - #[doc = "It is just a convenience function, equivalent to calling:"] - #[doc = ""] - #[doc = "- `vkCreateBuffer`"] - #[doc = "- `vkGetBufferMemoryRequirements`"] - #[doc = "- `vmaFindMemoryTypeIndex`"] - #[doc = "- `vkDestroyBuffer`"] pub fn vmaFindMemoryTypeIndexForBufferInfo( allocator: VmaAllocator, pBufferCreateInfo: *const BufferCreateInfo, @@ -1067,12 +1108,6 @@ extern "C" { #[doc = ""] #[doc = "It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex."] #[doc = "It internally creates a temporary, dummy image that never has memory bound."] - #[doc = "It is just a convenience function, equivalent to calling:"] - #[doc = ""] - #[doc = "- `vkCreateImage`"] - #[doc = "- `vkGetImageMemoryRequirements`"] - #[doc = "- `vmaFindMemoryTypeIndex`"] - #[doc = "- `vkDestroyImage`"] pub fn vmaFindMemoryTypeIndexForImageInfo( allocator: VmaAllocator, pImageCreateInfo: *const ImageCreateInfo, @@ -1102,7 +1137,23 @@ extern "C" { #[doc = "\\param allocator Allocator object."] #[doc = "\\param pool Pool object."] #[doc = "\\param[out] pPoolStats Statistics of specified pool."] - pub fn vmaGetPoolStats(allocator: VmaAllocator, pool: VmaPool, pPoolStats: *mut VmaPoolStats); + pub fn vmaGetPoolStatistics( + allocator: VmaAllocator, + pool: VmaPool, + pPoolStats: *mut VmaStatistics, + ); +} +extern "C" { + #[doc = " \\brief Retrieves detailed statistics of existing #VmaPool object."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param pool Pool object."] + #[doc = "\\param[out] pPoolStats Statistics of specified pool."] + pub fn vmaCalculatePoolStatistics( + allocator: VmaAllocator, + pool: VmaPool, + pPoolStats: *mut VmaDetailedStatistics, + ); } extern "C" { #[doc = " \\brief Checks magic number in margins around all allocations in given memory pool in search for corruptions."] @@ -1193,13 +1244,19 @@ extern "C" { ) -> Result; } extern "C" { + #[doc = " \\brief Allocates memory suitable for given `VkBuffer`."] + #[doc = ""] #[doc = "\\param allocator"] #[doc = "\\param buffer"] #[doc = "\\param pCreateInfo"] #[doc = "\\param[out] pAllocation Handle to allocated memory."] #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] #[doc = ""] - #[doc = "You should free the memory using vmaFreeMemory()."] + #[doc = "It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindBufferMemory()."] + #[doc = ""] + #[doc = "This is a special-purpose function. In most cases you should use vmaCreateBuffer()."] + #[doc = ""] + #[doc = "You must free the allocation using vmaFreeMemory() when no longer needed."] pub fn vmaAllocateMemoryForBuffer( allocator: VmaAllocator, buffer: Buffer, @@ -1209,7 +1266,19 @@ extern "C" { ) -> Result; } extern "C" { - #[doc = " Function similar to vmaAllocateMemoryForBuffer()."] + #[doc = " \\brief Allocates memory suitable for given `VkImage`."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param image"] + #[doc = "\\param pCreateInfo"] + #[doc = "\\param[out] pAllocation Handle to allocated memory."] + #[doc = "\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo()."] + #[doc = ""] + #[doc = "It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindImageMemory()."] + #[doc = ""] + #[doc = "This is a special-purpose function. In most cases you should use vmaCreateImage()."] + #[doc = ""] + #[doc = "You must free the allocation using vmaFreeMemory() when no longer needed."] pub fn vmaAllocateMemoryForImage( allocator: VmaAllocator, image: Image, @@ -1259,15 +1328,8 @@ extern "C" { extern "C" { #[doc = " \\brief Sets pUserData in given allocation to new value."] #[doc = ""] - #[doc = "If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,"] - #[doc = "pUserData must be either null, or pointer to a null-terminated string. The function"] - #[doc = "makes local copy of the string and sets it as allocation's `pUserData`. String"] - #[doc = "passed as pUserData doesn't need to be valid for whole lifetime of the allocation -"] - #[doc = "you can free it after this call. String previously pointed by allocation's"] - #[doc = "pUserData is freed from memory."] - #[doc = ""] - #[doc = "If the flag was not used, the value of pointer `pUserData` is just copied to"] - #[doc = "allocation's `pUserData`. It is opaque, so you can use it however you want - e.g."] + #[doc = "The value of pointer `pUserData` is copied to allocation's `pUserData`."] + #[doc = "It is opaque, so you can use it however you want - e.g."] #[doc = "as a pointer, ordinal number or some handle to you own data."] pub fn vmaSetAllocationUserData( allocator: VmaAllocator, @@ -1275,6 +1337,20 @@ extern "C" { pUserData: *mut ::std::os::raw::c_void, ); } +extern "C" { + #[doc = " \\brief Sets pName in given allocation to new value."] + #[doc = ""] + #[doc = "`pName` must be either null, or pointer to a null-terminated string. The function"] + #[doc = "makes local copy of the string and sets it as allocation's `pName`. String"] + #[doc = "passed as pName doesn't need to be valid for whole lifetime of the allocation -"] + #[doc = "you can free it after this call. String previously pointed by allocation's"] + #[doc = "`pName` is freed from memory."] + pub fn vmaSetAllocationName( + allocator: VmaAllocator, + allocation: VmaAllocation, + pName: *const ::std::os::raw::c_char, + ); +} extern "C" { #[doc = "\\brief Given an allocation, returns Property Flags of its memory type."] #[doc = ""] @@ -1463,108 +1539,71 @@ extern "C" { #[doc = ""] #[doc = "\\param allocator Allocator object."] #[doc = "\\param pInfo Structure filled with parameters of defragmentation."] - #[doc = "\\param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information."] - #[doc = "\\param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation."] - #[doc = "\\return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error."] - #[doc = ""] - #[doc = "Use this function instead of old, deprecated vmaDefragment()."] - #[doc = ""] - #[doc = "Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():"] - #[doc = ""] - #[doc = "- You should not use any of allocations passed as `pInfo->pAllocations` or"] - #[doc = "any allocations that belong to pools passed as `pInfo->pPools`,"] - #[doc = "including calling vmaGetAllocationInfo(), or access"] - #[doc = "their data."] - #[doc = "- Some mutexes protecting internal data structures may be locked, so trying to"] - #[doc = "make or free any allocations, bind buffers or images, map memory, or launch"] - #[doc = "another simultaneous defragmentation in between may cause stall (when done on"] - #[doc = "another thread) or deadlock (when done on the same thread), unless you are"] - #[doc = "100% sure that defragmented allocations are in different pools."] - #[doc = "- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined."] - #[doc = "They become valid after call to vmaDefragmentationEnd()."] - #[doc = "- If `pInfo->commandBuffer` is not null, you must submit that command buffer"] - #[doc = "and make sure it finished execution before calling vmaDefragmentationEnd()."] - #[doc = ""] - #[doc = "For more information and important limitations regarding defragmentation, see documentation chapter:"] + #[doc = "\\param[out] pContext Context object that must be passed to vmaEndDefragmentation() to finish defragmentation."] + #[doc = "\\returns"] + #[doc = "- `VK_SUCCESS` if defragmentation can begin."] + #[doc = "- `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported."] + #[doc = ""] + #[doc = "For more information about defragmentation, see documentation chapter:"] #[doc = "[Defragmentation](@ref defragmentation)."] - pub fn vmaDefragmentationBegin( + pub fn vmaBeginDefragmentation( allocator: VmaAllocator, - pInfo: *const VmaDefragmentationInfo2, - pStats: *mut VmaDefragmentationStats, + pInfo: *const VmaDefragmentationInfo, pContext: *mut VmaDefragmentationContext, ) -> Result; } extern "C" { #[doc = " \\brief Ends defragmentation process."] #[doc = ""] - #[doc = "Use this function to finish defragmentation started by vmaDefragmentationBegin()."] - #[doc = "It is safe to pass `context == null`. The function then does nothing."] - pub fn vmaDefragmentationEnd( + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param context Context object that has been created by vmaBeginDefragmentation()."] + #[doc = "\\param[out] pStats Optional stats for the defragmentation. Can be null."] + #[doc = ""] + #[doc = "Use this function to finish defragmentation started by vmaBeginDefragmentation()."] + pub fn vmaEndDefragmentation( allocator: VmaAllocator, context: VmaDefragmentationContext, - ) -> Result; + pStats: *mut VmaDefragmentationStats, + ); } extern "C" { + #[doc = " \\brief Starts single defragmentation pass."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param context Context object that has been created by vmaBeginDefragmentation()."] + #[doc = "\\param[out] pPassInfo Computed informations for current pass."] + #[doc = "\\returns"] + #[doc = "- `VK_SUCCESS` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation."] + #[doc = "- `VK_INCOMPLETE` if there are pending moves returned in `pPassInfo`. You need to perform them, call vmaEndDefragmentationPass(),"] + #[doc = "and then preferably try another pass with vmaBeginDefragmentationPass()."] pub fn vmaBeginDefragmentationPass( allocator: VmaAllocator, context: VmaDefragmentationContext, - pInfo: *mut VmaDefragmentationPassInfo, + pPassInfo: *mut VmaDefragmentationPassMoveInfo, ) -> Result; } extern "C" { + #[doc = " \\brief Ends single defragmentation pass."] + #[doc = ""] + #[doc = "\\param allocator Allocator object."] + #[doc = "\\param context Context object that has been created by vmaBeginDefragmentation()."] + #[doc = "\\param pPassInfo Computed informations for current pass filled by vmaBeginDefragmentationPass() and possibly modified by you."] + #[doc = ""] + #[doc = "Returns `VK_SUCCESS` if no more moves are possible or `VK_INCOMPLETE` if more defragmentations are possible."] + #[doc = ""] + #[doc = "Ends incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`."] + #[doc = "After this call:"] + #[doc = ""] + #[doc = "- Allocations at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY"] + #[doc = "(which is the default) will be pointing to the new destination place."] + #[doc = "- Allocation at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY"] + #[doc = "will be freed."] + #[doc = ""] + #[doc = "If no more moves are possible you can end whole defragmentation."] pub fn vmaEndDefragmentationPass( allocator: VmaAllocator, context: VmaDefragmentationContext, - ) -> Result; -} -extern "C" { - #[doc = " \\brief Deprecated. Compacts memory by moving allocations."] - #[doc = ""] - #[doc = "\\param allocator"] - #[doc = "\\param pAllocations Array of allocations that can be moved during this compation."] - #[doc = "\\param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays."] - #[doc = "\\param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information."] - #[doc = "\\param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values."] - #[doc = "\\param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information."] - #[doc = "\\return `VK_SUCCESS` if completed, negative error code in case of error."] - #[doc = ""] - #[doc = "\\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead."] - #[doc = ""] - #[doc = "This function works by moving allocations to different places (different"] - #[doc = "`VkDeviceMemory` objects and/or different offsets) in order to optimize memory"] - #[doc = "usage. Only allocations that are in `pAllocations` array can be moved. All other"] - #[doc = "allocations are considered nonmovable in this call. Basic rules:"] - #[doc = ""] - #[doc = "- Only allocations made in memory types that have"] - #[doc = "`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`"] - #[doc = "flags can be compacted. You may pass other allocations but it makes no sense -"] - #[doc = "these will never be moved."] - #[doc = "- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or"] - #[doc = "#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations"] - #[doc = "passed to this function that come from such pools are ignored."] - #[doc = "- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or"] - #[doc = "created as dedicated allocations for any other reason are also ignored."] - #[doc = "- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT"] - #[doc = "flag can be compacted. If not persistently mapped, memory will be mapped"] - #[doc = "temporarily inside this function if needed."] - #[doc = "- You must not pass same #VmaAllocation object multiple times in `pAllocations` array."] - #[doc = ""] - #[doc = "The function also frees empty `VkDeviceMemory` blocks."] - #[doc = ""] - #[doc = "Warning: This function may be time-consuming, so you shouldn't call it too often"] - #[doc = "(like after every resource creation/destruction)."] - #[doc = "You can call it on special occasions (like when reloading a game level or"] - #[doc = "when you just destroyed a lot of objects). Calling it every frame may be OK, but"] - #[doc = "you should measure that on your platform."] - #[doc = ""] - #[doc = "For more information, see [Defragmentation](@ref defragmentation) chapter."] - pub fn vmaDefragment( - allocator: VmaAllocator, - pAllocations: *mut VmaAllocation, - allocationCount: usize, - pAllocationsChanged: *mut Bool32, - pDefragmentationInfo: *const VmaDefragmentationInfo, - pDefragmentationStats: *mut VmaDefragmentationStats, + pPassInfo: *mut VmaDefragmentationPassMoveInfo, ) -> Result; } extern "C" { @@ -1646,6 +1685,8 @@ extern "C" { ) -> Result; } extern "C" { + #[doc = " \\brief Creates a new `VkBuffer`, allocates and binds memory for it."] + #[doc = ""] #[doc = "\\param allocator"] #[doc = "\\param pBufferCreateInfo"] #[doc = "\\param pAllocationCreateInfo"] @@ -1660,7 +1701,7 @@ extern "C" { #[doc = "-# Binds the buffer with the memory."] #[doc = ""] #[doc = "If any of these operations fail, buffer and allocation are not created,"] - #[doc = "returned value is negative error code, *pBuffer and *pAllocation are null."] + #[doc = "returned value is negative error code, `*pBuffer` and `*pAllocation` are null."] #[doc = ""] #[doc = "If the function succeeded, you must destroy both buffer and allocation when you"] #[doc = "no longer need them using either convenience function vmaDestroyBuffer() or"] @@ -1702,6 +1743,32 @@ extern "C" { pAllocationInfo: *mut VmaAllocationInfo, ) -> Result; } +extern "C" { + #[doc = " \\brief Creates a new `VkBuffer`, binds already created memory for it."] + #[doc = ""] + #[doc = "\\param allocator"] + #[doc = "\\param allocation Allocation that provides memory to be used for binding new buffer to it."] + #[doc = "\\param pBufferCreateInfo"] + #[doc = "\\param[out] pBuffer Buffer that was created."] + #[doc = ""] + #[doc = "This function automatically:"] + #[doc = ""] + #[doc = "-# Creates buffer."] + #[doc = "-# Binds the buffer with the supplied memory."] + #[doc = ""] + #[doc = "If any of these operations fail, buffer is not created,"] + #[doc = "returned value is negative error code and `*pBuffer` is null."] + #[doc = ""] + #[doc = "If the function succeeded, you must destroy the buffer when you"] + #[doc = "no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding"] + #[doc = "allocation you can use convenience function vmaDestroyBuffer()."] + pub fn vmaCreateAliasingBuffer( + allocator: VmaAllocator, + allocation: VmaAllocation, + pBufferCreateInfo: *const BufferCreateInfo, + pBuffer: *mut Buffer, + ) -> Result; +} extern "C" { #[doc = " \\brief Destroys Vulkan buffer and frees allocated memory."] #[doc = ""] @@ -1726,6 +1793,15 @@ extern "C" { pAllocationInfo: *mut VmaAllocationInfo, ) -> Result; } +extern "C" { + #[doc = " Function similar to vmaCreateAliasingBuffer()."] + pub fn vmaCreateAliasingImage( + allocator: VmaAllocator, + allocation: VmaAllocation, + pImageCreateInfo: *const ImageCreateInfo, + pImage: *mut Image, + ) -> Result; +} extern "C" { #[doc = " \\brief Destroys Vulkan image and frees allocated memory."] #[doc = ""] @@ -1816,16 +1892,25 @@ extern "C" { } extern "C" { #[doc = " \\brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock."] - pub fn vmaCalculateVirtualBlockStats( + #[doc = ""] + #[doc = "This function is fast to call. For more detailed statistics, see vmaCalculateVirtualBlockStatistics()."] + pub fn vmaGetVirtualBlockStatistics(virtualBlock: VmaVirtualBlock, pStats: *mut VmaStatistics); +} +extern "C" { + #[doc = " \\brief Calculates and returns detailed statistics about virtual allocations and memory usage in given #VmaVirtualBlock."] + #[doc = ""] + #[doc = "This function is slow to call. Use for debugging purposes."] + #[doc = "For less detailed statistics, see vmaGetVirtualBlockStatistics()."] + pub fn vmaCalculateVirtualBlockStatistics( virtualBlock: VmaVirtualBlock, - pStatInfo: *mut VmaStatInfo, + pStats: *mut VmaDetailedStatistics, ); } extern "C" { #[doc = " \\brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock."] #[doc = "\\param virtualBlock Virtual block."] #[doc = "\\param[out] ppStatsString Returned string."] - #[doc = "\\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStats(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces."] + #[doc = "\\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStatistics(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces."] #[doc = ""] #[doc = "Returned string must be freed using vmaFreeVirtualBlockStatsString()."] pub fn vmaBuildVirtualBlockStatsString( diff --git a/src/lib.rs b/src/lib.rs index 7a699a9..4a9b78d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,112 +137,6 @@ fn ffi_to_result(result: vk::Result) -> VkResult<()> { } } -#[derive(Debug)] -pub struct DefragmentationContext { - pub(crate) internal: ffi::VmaDefragmentationContext, - pub(crate) stats: ffi::VmaDefragmentationStats, - pub(crate) changed: Vec, -} - -/// Optional configuration parameters to be passed to `Allocator::defragment` -/// -/// DEPRECATED. -#[derive(Debug, Copy, Clone)] -pub struct DefragmentationInfo { - /// Maximum total numbers of bytes that can be copied while moving - /// allocations to different places. - /// - /// Default is `ash::vk::WHOLE_SIZE`, which means no limit. - pub max_bytes_to_move: usize, - - /// Maximum number of allocations that can be moved to different place. - /// - /// Default is `std::u32::MAX`, which means no limit. - pub max_allocations_to_move: u32, -} - -/// Construct `DefragmentationInfo` with default values -impl Default for DefragmentationInfo { - fn default() -> Self { - DefragmentationInfo { - max_bytes_to_move: ash::vk::WHOLE_SIZE as usize, - max_allocations_to_move: std::u32::MAX, - } - } -} - -/// Parameters for defragmentation. -/// -/// To be used with function `Allocator::defragmentation_begin`. -#[derive(Debug, Clone)] -pub struct DefragmentationInfo2<'a> { - /// Collection of allocations that can be defragmented. - /// - /// Elements in the slice should be unique - same allocation cannot occur twice. - /// It is safe to pass allocations that are in the lost state - they are ignored. - /// All allocations not present in this slice are considered non-moveable during this defragmentation. - pub allocations: &'a [Allocation], - - /// Either `None` or a slice of pools to be defragmented. - /// - /// All the allocations in the specified pools can be moved during defragmentation - /// and there is no way to check if they were really moved as in `allocations_changed`, - /// so you must query all the allocations in all these pools for new `ash::vk::DeviceMemory` - /// and offset using `Allocator::get_allocation_info` if you might need to recreate buffers - /// and images bound to them. - /// - /// Elements in the array should be unique - same pool cannot occur twice. - /// - /// Using this array is equivalent to specifying all allocations from the pools in `allocations`. - /// It might be more efficient. - pub pools: Option<&'a [AllocatorPool]>, - - /// Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`. - /// - /// `ash::vk::WHOLE_SIZE` means no limit. - pub max_cpu_bytes_to_move: ash::vk::DeviceSize, - - /// Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`. - /// - /// `std::u32::MAX` means no limit. - pub max_cpu_allocations_to_move: u32, - - /// Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `command_buffer`. - /// - /// `ash::vk::WHOLE_SIZE` means no limit. - pub max_gpu_bytes_to_move: ash::vk::DeviceSize, - - /// Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `command_buffer`. - /// - /// `std::u32::MAX` means no limit. - pub max_gpu_allocations_to_move: u32, - - /// Command buffer where GPU copy commands will be posted. - /// - /// If not `None`, it must be a valid command buffer handle that supports transfer queue type. - /// It must be in the recording state and outside of a render pass instance. - /// You need to submit it and make sure it finished execution before calling `Allocator::defragmentation_end`. - /// - /// Passing `None` means that only CPU defragmentation will be performed. - pub command_buffer: Option, -} - -/// Statistics returned by `Allocator::defragment` -#[derive(Debug, Copy, Clone)] -pub struct DefragmentationStats { - /// Total number of bytes that have been copied while moving allocations to different places. - pub bytes_moved: usize, - - /// Total number of bytes that have been released to the system by freeing empty `ash::vk::DeviceMemory` objects. - pub bytes_freed: usize, - - /// Number of allocations that have been moved to different places. - pub allocations_moved: u32, - - /// Number of empty `ash::vk::DeviceMemory` objects that have been released to the system. - pub device_memory_blocks_freed: u32, -} - impl Allocator { /// Constructor a new `Allocator` using the provided options. pub fn new(mut create_info: AllocatorCreateInfo) -> VkResult { @@ -311,6 +205,14 @@ impl Allocator { .instance .fp_v1_1() .get_physical_device_memory_properties2, + vkGetDeviceBufferMemoryRequirements: create_info + .device + .fp_v1_3() + .get_device_buffer_memory_requirements, + vkGetDeviceImageMemoryRequirements: create_info + .device + .fp_v1_3() + .get_device_image_memory_requirements, }; create_info.inner.pVulkanFunctions = &routed_functions; } @@ -371,9 +273,9 @@ impl Allocator { } /// Retrieves statistics from current state of the `Allocator`. - pub unsafe fn calculate_stats(&self) -> VkResult { - let mut vma_stats: ffi::VmaStats = mem::zeroed(); - ffi::vmaCalculateStats(self.internal, &mut vma_stats); + pub unsafe fn calculate_stats(&self) -> VkResult { + let mut vma_stats: ffi::VmaTotalStatistics = mem::zeroed(); + ffi::vmaCalculateStatistics(self.internal, &mut vma_stats); Ok(vma_stats) } @@ -496,9 +398,9 @@ impl Allocator { } /// Retrieves statistics of existing `AllocatorPool` object. - pub unsafe fn get_pool_stats(&self, pool: AllocatorPool) -> VkResult { - let mut pool_stats: ffi::VmaPoolStats = mem::zeroed(); - ffi::vmaGetPoolStats(self.internal, pool, &mut pool_stats); + pub unsafe fn get_pool_stats(&self, pool: AllocatorPool) -> VkResult { + let mut pool_stats: ffi::VmaStatistics = mem::zeroed(); + ffi::vmaGetPoolStatistics(self.internal, pool, &mut pool_stats); Ok(pool_stats) } @@ -802,177 +704,67 @@ impl Allocator { /// Begins defragmentation process. /// - /// Use this function instead of old, deprecated `Allocator::defragment`. - /// - /// Warning! Between the call to `Allocator::defragmentation_begin` and `Allocator::defragmentation_end`. - /// - /// - You should not use any of allocations passed as `allocations` or - /// any allocations that belong to pools passed as `pools`, - /// including calling `Allocator::get_allocation_info`, `Allocator::touch_allocation`, or access - /// their data. - /// - /// - Some mutexes protecting internal data structures may be locked, so trying to - /// make or free any allocations, bind buffers or images, map memory, or launch - /// another simultaneous defragmentation in between may cause stall (when done on - /// another thread) or deadlock (when done on the same thread), unless you are - /// 100% sure that defragmented allocations are in different pools. - /// - /// - Information returned via stats and `info.allocations_changed` are undefined. - /// They become valid after call to `Allocator::defragmentation_end`. - /// - /// - If `info.command_buffer` is not null, you must submit that command buffer - /// and make sure it finished execution before calling `Allocator::defragmentation_end`. - pub unsafe fn defragmentation_begin( + /// ## Returns + /// `VK_SUCCESS` if defragmentation can begin. + /// `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported. + pub unsafe fn begin_defragmentation( &self, - info: &DefragmentationInfo2, - ) -> VkResult { - let command_buffer = match info.command_buffer { - Some(command_buffer) => command_buffer, - None => ash::vk::CommandBuffer::null(), - }; - - let mut context = DefragmentationContext { - internal: mem::zeroed(), - stats: ffi::VmaDefragmentationStats { - bytesMoved: 0, - bytesFreed: 0, - allocationsMoved: 0, - deviceMemoryBlocksFreed: 0, - }, - changed: vec![ash::vk::FALSE; info.allocations.len()], - }; - - let pools = info.pools.unwrap_or(&[]); - - let ffi_info = ffi::VmaDefragmentationInfo2 { - flags: 0, // Reserved for future use - allocationCount: info.allocations.len() as u32, - pAllocations: info.allocations.as_ptr() as *mut _, - pAllocationsChanged: context.changed.as_mut_ptr(), - poolCount: pools.len() as u32, - pPools: pools.as_ptr() as *mut _, - maxCpuBytesToMove: info.max_cpu_bytes_to_move, - maxCpuAllocationsToMove: info.max_cpu_allocations_to_move, - maxGpuBytesToMove: info.max_gpu_bytes_to_move, - maxGpuAllocationsToMove: info.max_gpu_allocations_to_move, - commandBuffer: command_buffer, - }; + info: &ffi::VmaDefragmentationInfo, + ) -> VkResult { + let mut context: ffi::VmaDefragmentationContext = std::ptr::null_mut(); - ffi_to_result(ffi::vmaDefragmentationBegin( - self.internal, - &ffi_info, - &mut context.stats as *mut _, - &mut context.internal, - ))?; + ffi::vmaBeginDefragmentation(self.internal, info, &mut context).result()?; Ok(context) } /// Ends defragmentation process. /// - /// Use this function to finish defragmentation started by `Allocator::defragmentation_begin`. - pub unsafe fn defragmentation_end( + /// Use this function to finish defragmentation started by `Allocator::begin_defragmentation`. + pub unsafe fn end_defragmentation( &self, - context: &mut DefragmentationContext, - ) -> VkResult<(DefragmentationStats, Vec)> { - ffi_to_result(ffi::vmaDefragmentationEnd(self.internal, context.internal))?; - - let changed: Vec = context.changed.iter().map(|change| *change == 1).collect(); - - let stats = DefragmentationStats { - bytes_moved: context.stats.bytesMoved as usize, - bytes_freed: context.stats.bytesFreed as usize, - allocations_moved: context.stats.allocationsMoved, - device_memory_blocks_freed: context.stats.deviceMemoryBlocksFreed, + context: ffi::VmaDefragmentationContext, + ) -> ffi::VmaDefragmentationStats { + let mut stats = ffi::VmaDefragmentationStats { + bytesMoved: 0, + bytesFreed: 0, + allocationsMoved: 0, + deviceMemoryBlocksFreed: 0, }; + ffi::vmaEndDefragmentation(self.internal, context, &mut stats); - Ok((stats, changed)) + stats } - /// Compacts memory by moving allocations. - /// - /// `allocations` is a slice of allocations that can be moved during this compaction. - /// `defrag_info` optional configuration parameters. - /// Returns statistics from the defragmentation, and an associated array to `allocations` - /// which indicates which allocations were changed (if any). - /// - /// Possible error values: - /// - /// - `ash::vk::Result::INCOMPLETE` if succeeded but didn't make all possible optimizations because limits specified in - /// `defrag_info` have been reached, negative error code in case of error. - /// - /// This function works by moving allocations to different places (different - /// `ash::vk::DeviceMemory` objects and/or different offsets) in order to optimize memory - /// usage. Only allocations that are in `allocations` slice can be moved. All other - /// allocations are considered nonmovable in this call. Basic rules: + /// Ends single defragmentation pass. + /// * `context` - Context object that has been created by `begin_defragmentation` + /// * `pass_info` - Coputed informations for current pass filled by `begin_defragmentation_pass` and possibly modified by you. /// - /// - Only allocations made in memory types that have - /// `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` and `ash::vk::MemoryPropertyFlags::HOST_COHERENT` - /// flags can be compacted. You may pass other allocations but it makes no sense - - /// these will never be moved. - /// - /// - Custom pools created with `AllocatorPoolCreateFlags::LINEAR_ALGORITHM` or `AllocatorPoolCreateFlags::BUDDY_ALGORITHM` flag are not - /// defragmented. Allocations passed to this function that come from such pools are ignored. - /// - /// - Allocations created with `AllocationCreateFlags::DEDICATED_MEMORY` or created as dedicated allocations for any - /// other reason are also ignored. - /// - /// - Both allocations made with or without `AllocationCreateFlags::MAPPED` flag can be compacted. If not persistently - /// mapped, memory will be mapped temporarily inside this function if needed. - /// - /// - You must not pass same `allocation` object multiple times in `allocations` slice. - /// - /// The function also frees empty `ash::vk::DeviceMemory` blocks. - /// - /// Warning: This function may be time-consuming, so you shouldn't call it too often - /// (like after every resource creation/destruction). - /// You can call it on special occasions (like when reloading a game level or - /// when you just destroyed a lot of objects). Calling it every frame may be OK, but - /// you should measure that on your platform. - #[deprecated( - since = "0.1.3", - note = "This is a part of the old interface. It is recommended to use structure `DefragmentationInfo2` and function `Allocator::defragmentation_begin` instead." - )] - pub unsafe fn defragment( + /// Returns: + /// - `false` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation. + /// - `true` if there are pending moves returned in pPassInfo. You need to perform them, call vmaEndDefragmentationPass(), and then + /// preferably try another pass with vmaBeginDefragmentationPass(). + pub unsafe fn begin_defragmentation_pass( &self, - allocations: &[Allocation], - defrag_info: Option<&DefragmentationInfo>, - ) -> VkResult<(DefragmentationStats, Vec)> { - let mut ffi_change_list: Vec = vec![0; allocations.len()]; - let ffi_info = match defrag_info { - Some(info) => ffi::VmaDefragmentationInfo { - maxBytesToMove: info.max_bytes_to_move as vk::DeviceSize, - maxAllocationsToMove: info.max_allocations_to_move, - }, - None => ffi::VmaDefragmentationInfo { - maxBytesToMove: ash::vk::WHOLE_SIZE, - maxAllocationsToMove: std::u32::MAX, - }, - }; - - let mut ffi_stats: ffi::VmaDefragmentationStats = mem::zeroed(); - ffi_to_result(ffi::vmaDefragment( - self.internal, - allocations.as_ptr() as *mut _, - allocations.len(), - ffi_change_list.as_mut_ptr(), - &ffi_info, - &mut ffi_stats, - ))?; - - let change_list: Vec = ffi_change_list - .iter() - .map(|change| *change == ash::vk::TRUE) - .collect(); - - let stats = DefragmentationStats { - bytes_moved: ffi_stats.bytesMoved as usize, - bytes_freed: ffi_stats.bytesFreed as usize, - allocations_moved: ffi_stats.allocationsMoved, - device_memory_blocks_freed: ffi_stats.deviceMemoryBlocksFreed, - }; + context: ffi::VmaDefragmentationContext, + pass_info: &mut ffi::VmaDefragmentationPassMoveInfo, + ) -> bool { + let result = ffi::vmaBeginDefragmentationPass(self.internal, context, pass_info); + return result == vk::Result::INCOMPLETE; + } - Ok((stats, change_list)) + /// Ends single defragmentation pass. + /// * `context` - Context object that has been created by `begin_defragmentation` + /// * `pass_info` - Coputed informations for current pass filled by `begin_defragmentation_pass` and possibly modified by you. + /// + /// Returns false if no more moves are possible or true if more defragmentations are possible. + pub unsafe fn end_defragmentation_pass( + &self, + context: ffi::VmaDefragmentationContext, + pass_info: &mut ffi::VmaDefragmentationPassMoveInfo, + ) -> bool { + let result = ffi::vmaEndDefragmentationPass(self.internal, context, pass_info); + return result == vk::Result::INCOMPLETE; } /// Binds buffer to allocation. diff --git a/vendor/VulkanMemoryAllocator b/vendor/VulkanMemoryAllocator index 5c710e8..5ab8c17 160000 --- a/vendor/VulkanMemoryAllocator +++ b/vendor/VulkanMemoryAllocator @@ -1 +1 @@ -Subproject commit 5c710e86a0ce0664bbc2374c39b956b9928b2f29 +Subproject commit 5ab8c1752ab9720b7a38a3bc72ebcf17ef3ce6f1 From ed4d498a476e1f1e8e515ff1fbefd66d90324326 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 01:33:29 -0700 Subject: [PATCH 06/23] memory usage flags & extract defragmentation --- src/definitions.rs | 54 ++++++++++++++++++++++++++++ src/defragmentation.rs | 82 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 67 ++-------------------------------- 3 files changed, 138 insertions(+), 65 deletions(-) create mode 100644 src/defragmentation.rs diff --git a/src/definitions.rs b/src/definitions.rs index 0092fa6..4e23839 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -27,6 +27,7 @@ pub enum MemoryUsage { /// Allocation may still end up in `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` memory on some implementations. /// In such case, you are free to map it. /// You can use `AllocationCreateFlags::MAPPED` with this usage type. + #[deprecated(since = "0.3")] GpuOnly, /// Memory will be mappable on host. @@ -37,6 +38,7 @@ pub enum MemoryUsage { /// It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`. /// /// Usage: Staging copy of resources used as transfer source. + #[deprecated(since = "0.3")] CpuOnly, /// Memory that is both mappable on host (guarantees to be `ash::vk::MemoryPropertyFlags::HOST_VISIBLE`) and preferably fast to access by GPU. @@ -44,6 +46,7 @@ pub enum MemoryUsage { /// /// Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers, /// uniform buffers updated every frame or every draw call. + #[deprecated(since = "0.3")] CpuToGpu, /// Memory mappable on host (guarantees to be `ash::vk::MemoryPropertFlags::HOST_VISIBLE`) and cached. @@ -53,15 +56,55 @@ pub enum MemoryUsage { /// /// - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping. /// - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection. + #[deprecated(since = "0.3")] GpuToCpu, + /// Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + #[deprecated(since = "0.3")] + CpuCopy, + /// Lazily allocated GPU memory having (guarantees to be `ash::vk::MemoryPropertFlags::LAZILY_ALLOCATED`). /// Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation. /// /// Usage: /// /// - Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`. + /// Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. GpuLazy, + + /// Selects best memory type automatically. + /// This flag is recommended for most common use cases. + /// + /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + /// in VmaAllocationCreateInfo::flags. + /// + /// It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + /// vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + /// and not with generic memory allocation functions. + Auto, + + /// Selects best memory type automatically with preference for CPU (host) memory. + /// + /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + /// in VmaAllocationCreateInfo::flags. + /// + /// It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + /// vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + /// and not with generic memory allocation functions. + AutoPreferDevice, + + /// Selects best memory type automatically with preference for CPU (host) memory. + /// + /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + /// in VmaAllocationCreateInfo::flags. + /// + /// It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + /// vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + /// and not with generic memory allocation functions. + AutoPreferHost, } bitflags! { @@ -484,11 +527,22 @@ impl<'a> AllocationCreateInfo<'a> { pub fn usage(mut self, usage: MemoryUsage) -> Self { self.inner.usage = match usage { MemoryUsage::Unknown => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN, + #[allow(deprecated)] MemoryUsage::GpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_ONLY, + #[allow(deprecated)] MemoryUsage::CpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_ONLY, + #[allow(deprecated)] MemoryUsage::CpuToGpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU, + #[allow(deprecated)] MemoryUsage::GpuToCpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_TO_CPU, + #[allow(deprecated)] + MemoryUsage::CpuCopy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_COPY, MemoryUsage::GpuLazy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED, + MemoryUsage::Auto => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, + MemoryUsage::AutoPreferDevice => { + ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE + } + MemoryUsage::AutoPreferHost => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_HOST, }; self } diff --git a/src/defragmentation.rs b/src/defragmentation.rs new file mode 100644 index 0000000..607e9a9 --- /dev/null +++ b/src/defragmentation.rs @@ -0,0 +1,82 @@ +use crate::ffi; +use crate::Allocator; +use ash::prelude::VkResult; +use ash::vk; + +pub use ffi::VmaDefragmentationMove as DefragmentationMove; +pub use ffi::VmaDefragmentationStats as DefragmentationStats; +pub struct DefragmentationContext<'a> { + allocator: &'a Allocator, + raw: ffi::VmaDefragmentationContext, +} + +impl<'a> Drop for DefragmentationContext<'a> { + fn drop(&mut self) { + unsafe { + ffi::vmaEndDefragmentation(self.allocator.internal, self.raw, std::ptr::null_mut()); + } + } +} + +impl<'a> DefragmentationContext<'a> { + /// Ends defragmentation process. + pub fn end(self) -> DefragmentationStats { + let mut stats = DefragmentationStats { + bytesMoved: 0, + bytesFreed: 0, + allocationsMoved: 0, + deviceMemoryBlocksFreed: 0, + }; + unsafe { + ffi::vmaEndDefragmentation(self.allocator.internal, self.raw, &mut stats); + } + std::mem::forget(self); + stats + } + + /// Returns `false` if no more moves are possible or `true` if more defragmentations are possible. + pub fn begin_pass(&self, mover: impl FnOnce(&mut [DefragmentationMove]) -> ()) -> bool { + let mut pass_info = ffi::VmaDefragmentationPassMoveInfo { + moveCount: 0, + pMoves: std::ptr::null_mut(), + }; + let result = unsafe { + ffi::vmaBeginDefragmentationPass(self.allocator.internal, self.raw, &mut pass_info) + }; + if result == vk::Result::SUCCESS { + return false; + } + debug_assert_eq!(result, vk::Result::INCOMPLETE); + let moves = unsafe { + std::slice::from_raw_parts_mut(pass_info.pMoves, pass_info.moveCount as usize) + }; + mover(moves); + + let result = unsafe { + ffi::vmaEndDefragmentationPass(self.allocator.internal, self.raw, &mut pass_info) + }; + + return result == vk::Result::INCOMPLETE; + } +} + +impl Allocator { + /// Begins defragmentation process. + /// + /// ## Returns + /// `VK_SUCCESS` if defragmentation can begin. + /// `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported. + pub unsafe fn begin_defragmentation( + &self, + info: &ffi::VmaDefragmentationInfo, + ) -> VkResult { + let mut context: ffi::VmaDefragmentationContext = std::ptr::null_mut(); + + ffi::vmaBeginDefragmentation(self.internal, info, &mut context).result()?; + + Ok(DefragmentationContext { + allocator: self, + raw: context, + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 4a9b78d..6793135 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,10 @@ //! Easy to use, high performance memory manager for Vulkan. mod definitions; +mod defragmentation; pub mod ffi; pub use definitions::*; +pub use defragmentation::*; use ash::prelude::VkResult; use ash::vk; @@ -702,71 +704,6 @@ impl Allocator { )) } - /// Begins defragmentation process. - /// - /// ## Returns - /// `VK_SUCCESS` if defragmentation can begin. - /// `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported. - pub unsafe fn begin_defragmentation( - &self, - info: &ffi::VmaDefragmentationInfo, - ) -> VkResult { - let mut context: ffi::VmaDefragmentationContext = std::ptr::null_mut(); - - ffi::vmaBeginDefragmentation(self.internal, info, &mut context).result()?; - - Ok(context) - } - - /// Ends defragmentation process. - /// - /// Use this function to finish defragmentation started by `Allocator::begin_defragmentation`. - pub unsafe fn end_defragmentation( - &self, - context: ffi::VmaDefragmentationContext, - ) -> ffi::VmaDefragmentationStats { - let mut stats = ffi::VmaDefragmentationStats { - bytesMoved: 0, - bytesFreed: 0, - allocationsMoved: 0, - deviceMemoryBlocksFreed: 0, - }; - ffi::vmaEndDefragmentation(self.internal, context, &mut stats); - - stats - } - - /// Ends single defragmentation pass. - /// * `context` - Context object that has been created by `begin_defragmentation` - /// * `pass_info` - Coputed informations for current pass filled by `begin_defragmentation_pass` and possibly modified by you. - /// - /// Returns: - /// - `false` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation. - /// - `true` if there are pending moves returned in pPassInfo. You need to perform them, call vmaEndDefragmentationPass(), and then - /// preferably try another pass with vmaBeginDefragmentationPass(). - pub unsafe fn begin_defragmentation_pass( - &self, - context: ffi::VmaDefragmentationContext, - pass_info: &mut ffi::VmaDefragmentationPassMoveInfo, - ) -> bool { - let result = ffi::vmaBeginDefragmentationPass(self.internal, context, pass_info); - return result == vk::Result::INCOMPLETE; - } - - /// Ends single defragmentation pass. - /// * `context` - Context object that has been created by `begin_defragmentation` - /// * `pass_info` - Coputed informations for current pass filled by `begin_defragmentation_pass` and possibly modified by you. - /// - /// Returns false if no more moves are possible or true if more defragmentations are possible. - pub unsafe fn end_defragmentation_pass( - &self, - context: ffi::VmaDefragmentationContext, - pass_info: &mut ffi::VmaDefragmentationPassMoveInfo, - ) -> bool { - let result = ffi::vmaEndDefragmentationPass(self.internal, context, pass_info); - return result == vk::Result::INCOMPLETE; - } - /// Binds buffer to allocation. /// /// Binds specified buffer to region of memory represented by specified allocation. From e62880f71a9fae701395732d0a690b03eeb2cca8 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 01:39:17 -0700 Subject: [PATCH 07/23] Add calculate_pool_statistics --- src/lib.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6793135..32ffe3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -275,7 +275,7 @@ impl Allocator { } /// Retrieves statistics from current state of the `Allocator`. - pub unsafe fn calculate_stats(&self) -> VkResult { + pub unsafe fn calculate_statistics(&self) -> VkResult { let mut vma_stats: ffi::VmaTotalStatistics = mem::zeroed(); ffi::vmaCalculateStatistics(self.internal, &mut vma_stats); Ok(vma_stats) @@ -406,6 +406,16 @@ impl Allocator { Ok(pool_stats) } + /// Retrieves detailed statistics of existing `AllocatorPool` object. + pub unsafe fn calculate_pool_statistics( + &self, + pool: AllocatorPool, + ) -> VkResult { + let mut pool_stats: ffi::VmaDetailedStatistics = mem::zeroed(); + ffi::vmaCalculatePoolStatistics(self.internal, pool, &mut pool_stats); + Ok(pool_stats) + } + /// Checks magic number in margins around all allocations in given memory pool in search for corruptions. /// /// Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, From d5f58f33ba748587a5aa128403d57edb801aee13 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 01:48:37 -0700 Subject: [PATCH 08/23] remove ffi_to_result --- src/lib.rs | 92 ++++++++++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 52 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 32ffe3f..dacc27f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -130,15 +130,6 @@ impl Default for AllocatorCreateFlags { } } -/// Converts a raw result into an ash result. -#[inline] -fn ffi_to_result(result: vk::Result) -> VkResult<()> { - match result { - vk::Result::SUCCESS => Ok(()), - _ => Err(result), - } -} - impl Allocator { /// Constructor a new `Allocator` using the provided options. pub fn new(mut create_info: AllocatorCreateInfo) -> VkResult { @@ -220,10 +211,7 @@ impl Allocator { } unsafe { let mut internal: ffi::VmaAllocator = mem::zeroed(); - ffi_to_result(ffi::vmaCreateAllocator( - &create_info.inner as *const _, - &mut internal, - ))?; + ffi::vmaCreateAllocator(&create_info.inner as *const _, &mut internal).result()?; Ok(Allocator { internal }) } @@ -321,12 +309,13 @@ impl Allocator { allocation_info: &AllocationCreateInfo, ) -> VkResult { let mut memory_type_index: u32 = 0; - ffi_to_result(ffi::vmaFindMemoryTypeIndex( + ffi::vmaFindMemoryTypeIndex( self.internal, memory_type_bits, &allocation_info.inner, &mut memory_type_index, - ))?; + ) + .result()?; Ok(memory_type_index) } @@ -347,12 +336,13 @@ impl Allocator { allocation_info: &AllocationCreateInfo, ) -> VkResult { let mut memory_type_index: u32 = 0; - ffi_to_result(ffi::vmaFindMemoryTypeIndexForBufferInfo( + ffi::vmaFindMemoryTypeIndexForBufferInfo( self.internal, buffer_info, &allocation_info.inner, &mut memory_type_index, - ))?; + ) + .result()?; Ok(memory_type_index) } @@ -373,12 +363,13 @@ impl Allocator { allocation_info: &AllocationCreateInfo, ) -> VkResult { let mut memory_type_index: u32 = 0; - ffi_to_result(ffi::vmaFindMemoryTypeIndexForImageInfo( + ffi::vmaFindMemoryTypeIndexForImageInfo( self.internal, &image_info, &allocation_info.inner, &mut memory_type_index, - ))?; + ) + .result()?; Ok(memory_type_index) } @@ -386,11 +377,7 @@ impl Allocator { /// Allocates Vulkan device memory and creates `AllocatorPool` object. pub unsafe fn create_pool(&self, create_info: &PoolCreateInfo) -> VkResult { let mut ffi_pool: ffi::VmaPool = mem::zeroed(); - ffi_to_result(ffi::vmaCreatePool( - self.internal, - &create_info.inner, - &mut ffi_pool, - ))?; + ffi::vmaCreatePool(self.internal, &create_info.inner, &mut ffi_pool).result()?; Ok(ffi_pool) } @@ -429,7 +416,7 @@ impl Allocator { /// `VMA_ASSERT` is also fired in that case. /// - Other value: Error returned by Vulkan, e.g. memory mapping failure. pub unsafe fn check_pool_corruption(&self, pool: AllocatorPool) -> VkResult<()> { - ffi_to_result(ffi::vmaCheckPoolCorruption(self.internal, pool)) + ffi::vmaCheckPoolCorruption(self.internal, pool).result() } /// General purpose memory allocation. @@ -445,13 +432,14 @@ impl Allocator { ) -> VkResult<(Allocation, AllocationInfo)> { let mut allocation: Allocation = mem::zeroed(); let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi_to_result(ffi::vmaAllocateMemory( + ffi::vmaAllocateMemory( self.internal, memory_requirements, &create_info.inner, &mut allocation, &mut allocation_info.internal, - ))?; + ) + .result()?; Ok((allocation, allocation_info)) } @@ -474,14 +462,15 @@ impl Allocator { let mut allocations: Vec = vec![mem::zeroed(); allocation_count]; let mut allocation_info: Vec = vec![mem::zeroed(); allocation_count]; - ffi_to_result(ffi::vmaAllocateMemoryPages( + ffi::vmaAllocateMemoryPages( self.internal, memory_requirements, &create_info.inner, allocation_count, allocations.as_mut_ptr(), allocation_info.as_mut_ptr(), - ))?; + ) + .result()?; let it = allocations.iter().zip(allocation_info.iter()); let allocations: Vec<(Allocation, AllocationInfo)> = it @@ -501,13 +490,14 @@ impl Allocator { ) -> VkResult<(Allocation, AllocationInfo)> { let mut allocation: Allocation = mem::zeroed(); let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi_to_result(ffi::vmaAllocateMemoryForBuffer( + ffi::vmaAllocateMemoryForBuffer( self.internal, buffer, &create_info.inner, &mut allocation, &mut allocation_info.internal, - ))?; + ) + .result()?; Ok((allocation, allocation_info)) } @@ -522,13 +512,14 @@ impl Allocator { ) -> VkResult<(Allocation, AllocationInfo)> { let mut allocation: Allocation = mem::zeroed(); let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi_to_result(ffi::vmaAllocateMemoryForImage( + ffi::vmaAllocateMemoryForImage( self.internal, image, &create_info.inner, &mut allocation, &mut allocation_info.internal, - ))?; + ) + .result()?; Ok((allocation, allocation_info)) } @@ -631,11 +622,7 @@ impl Allocator { /// `AllocationCreateFlags::CAN_BECOME_LOST` flag. Such allocations cannot be mapped. pub unsafe fn map_memory(&self, allocation: Allocation) -> VkResult<*mut u8> { let mut mapped_data: *mut ::std::os::raw::c_void = ::std::ptr::null_mut(); - ffi_to_result(ffi::vmaMapMemory( - self.internal, - allocation, - &mut mapped_data, - ))?; + ffi::vmaMapMemory(self.internal, allocation, &mut mapped_data).result()?; Ok(mapped_data as *mut u8) } @@ -660,12 +647,13 @@ impl Allocator { offset: usize, size: usize, ) -> VkResult<()> { - ffi_to_result(ffi::vmaFlushAllocation( + ffi::vmaFlushAllocation( self.internal, allocation, offset as vk::DeviceSize, size as vk::DeviceSize, - )) + ) + .result() } /// Invalidates memory of given allocation. @@ -683,12 +671,13 @@ impl Allocator { offset: usize, size: usize, ) -> VkResult<()> { - ffi_to_result(ffi::vmaInvalidateAllocation( + ffi::vmaInvalidateAllocation( self.internal, allocation, offset as vk::DeviceSize, size as vk::DeviceSize, - )) + ) + .result() } /// Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. @@ -708,10 +697,7 @@ impl Allocator { &self, memory_types: ash::vk::MemoryPropertyFlags, ) -> VkResult<()> { - ffi_to_result(ffi::vmaCheckCorruption( - self.internal, - memory_types.as_raw(), - )) + ffi::vmaCheckCorruption(self.internal, memory_types.as_raw()).result() } /// Binds buffer to allocation. @@ -732,7 +718,7 @@ impl Allocator { buffer: ash::vk::Buffer, allocation: Allocation, ) -> VkResult<()> { - ffi_to_result(ffi::vmaBindBufferMemory(self.internal, allocation, buffer)) + ffi::vmaBindBufferMemory(self.internal, allocation, buffer).result() } /// Binds image to allocation. @@ -753,7 +739,7 @@ impl Allocator { image: ash::vk::Image, allocation: Allocation, ) -> VkResult<()> { - ffi_to_result(ffi::vmaBindImageMemory(self.internal, allocation, image)) + ffi::vmaBindImageMemory(self.internal, allocation, image).result() } /// This function automatically creates a buffer, allocates appropriate memory @@ -777,14 +763,15 @@ impl Allocator { let mut buffer = vk::Buffer::null(); let mut allocation: Allocation = mem::zeroed(); let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi_to_result(ffi::vmaCreateBuffer( + ffi::vmaCreateBuffer( self.internal, &*buffer_info, &allocation_create_info.inner, &mut buffer, &mut allocation, &mut allocation_info.internal, - ))?; + ) + .result()?; Ok((buffer, allocation, allocation_info)) } @@ -828,14 +815,15 @@ impl Allocator { let mut image = vk::Image::null(); let mut allocation: Allocation = mem::zeroed(); let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi_to_result(ffi::vmaCreateImage( + ffi::vmaCreateImage( self.internal, &*image_info, &allocation_create_info.inner, &mut image, &mut allocation, &mut allocation_info.internal, - ))?; + ) + .result()?; Ok((image, allocation, allocation_info)) } From ca846acbf3dabb1102d44b66474f0b5d27044a10 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 02:14:53 -0700 Subject: [PATCH 09/23] Create pools --- src/definitions.rs | 4 +- src/lib.rs | 118 +++++++++++---------------------------------- src/pool.rs | 70 +++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 93 deletions(-) create mode 100644 src/pool.rs diff --git a/src/definitions.rs b/src/definitions.rs index 4e23839..b5f2726 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -562,8 +562,8 @@ impl<'a> AllocationCreateInfo<'a> { self } - pub fn pool(mut self, pool: AllocatorPool) -> Self { - self.inner.pool = pool; + pub fn pool(mut self, pool: &AllocatorPool) -> Self { + self.inner.pool = pool.raw; self } diff --git a/src/lib.rs b/src/lib.rs index dacc27f..21e6739 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,8 +3,10 @@ mod definitions; mod defragmentation; pub mod ffi; +mod pool; pub use definitions::*; pub use defragmentation::*; +pub use pool::*; use ash::prelude::VkResult; use ash::vk; @@ -20,12 +22,6 @@ pub struct Allocator { unsafe impl Send for Allocator {} unsafe impl Sync for Allocator {} -/// Represents custom memory pool handle. -/// -/// Fill structure `AllocatorPoolCreateInfo` and call `Allocator::create_pool` to create it. -/// Call `Allocator::destroy_pool` to destroy it. -pub type AllocatorPool = ffi::VmaPool; - /// Represents single memory allocation. /// /// It may be either dedicated block of `ash::vk::DeviceMemory` or a specific region of a @@ -231,25 +227,11 @@ impl Allocator { /// The allocator fetches `ash::vk::PhysicalDeviceMemoryProperties` from the physical device. /// You can get it here, without fetching it again on your own. - pub unsafe fn get_memory_properties(&self) -> VkResult { - let mut properties = vk::PhysicalDeviceMemoryProperties::default(); - ffi::vmaGetMemoryProperties(self.internal, &mut properties as *mut _ as *mut *const _); - - Ok(properties) - } + pub unsafe fn get_memory_properties(&self) -> &vk::PhysicalDeviceMemoryProperties { + let mut properties: *const vk::PhysicalDeviceMemoryProperties = std::ptr::null(); + ffi::vmaGetMemoryProperties(self.internal, &mut properties); - /// Given a memory type index, returns `ash::vk::MemoryPropertyFlags` of this memory type. - /// - /// This is just a convenience function; the same information can be obtained using - /// `Allocator::get_memory_properties`. - pub unsafe fn get_memory_type_properties( - &self, - memory_type_index: u32, - ) -> VkResult { - let mut flags = vk::MemoryPropertyFlags::empty(); - ffi::vmaGetMemoryTypeProperties(self.internal, memory_type_index, &mut flags); - - Ok(flags) + &*properties } /// Sets index of the current frame. @@ -263,30 +245,29 @@ impl Allocator { } /// Retrieves statistics from current state of the `Allocator`. - pub unsafe fn calculate_statistics(&self) -> VkResult { - let mut vma_stats: ffi::VmaTotalStatistics = mem::zeroed(); - ffi::vmaCalculateStatistics(self.internal, &mut vma_stats); - Ok(vma_stats) + pub fn calculate_statistics(&self) -> VkResult { + unsafe { + let mut vma_stats: ffi::VmaTotalStatistics = mem::zeroed(); + ffi::vmaCalculateStatistics(self.internal, &mut vma_stats); + Ok(vma_stats) + } } - /// Builds and returns statistics in `JSON` format. - pub unsafe fn build_stats_string(&self, detailed_map: bool) -> VkResult { - let mut stats_string: *mut ::std::os::raw::c_char = ::std::ptr::null_mut(); - ffi::vmaBuildStatsString( - self.internal, - &mut stats_string, - if detailed_map { 1 } else { 0 }, - ); - - Ok(if stats_string.is_null() { - String::new() - } else { - let result = std::ffi::CStr::from_ptr(stats_string) - .to_string_lossy() - .into_owned(); - ffi::vmaFreeStatsString(self.internal, stats_string); - result - }) + /// Retrieves information about current memory usage and budget for all memory heaps. + /// + /// This function is called "get" not "calculate" because it is very fast, suitable to be called + /// every frame or every allocation. For more detailed statistics use vmaCalculateStatistics(). + /// + /// Note that when using allocator from multiple threads, returned information may immediately + /// become outdated. + pub fn get_heap_budgets(&self) -> VkResult> { + unsafe { + let len = self.get_memory_properties().memory_heap_count as usize; + let mut vma_budgets: Vec = Vec::with_capacity(len); + ffi::vmaGetHeapBudgets(self.internal, vma_budgets.as_mut_ptr()); + vma_budgets.set_len(len); + Ok(vma_budgets) + } } /// Helps to find memory type index, given memory type bits and allocation info. @@ -374,51 +355,6 @@ impl Allocator { Ok(memory_type_index) } - /// Allocates Vulkan device memory and creates `AllocatorPool` object. - pub unsafe fn create_pool(&self, create_info: &PoolCreateInfo) -> VkResult { - let mut ffi_pool: ffi::VmaPool = mem::zeroed(); - ffi::vmaCreatePool(self.internal, &create_info.inner, &mut ffi_pool).result()?; - Ok(ffi_pool) - } - - /// Destroys `AllocatorPool` object and frees Vulkan device memory. - pub unsafe fn destroy_pool(&self, pool: AllocatorPool) { - ffi::vmaDestroyPool(self.internal, pool); - } - - /// Retrieves statistics of existing `AllocatorPool` object. - pub unsafe fn get_pool_stats(&self, pool: AllocatorPool) -> VkResult { - let mut pool_stats: ffi::VmaStatistics = mem::zeroed(); - ffi::vmaGetPoolStatistics(self.internal, pool, &mut pool_stats); - Ok(pool_stats) - } - - /// Retrieves detailed statistics of existing `AllocatorPool` object. - pub unsafe fn calculate_pool_statistics( - &self, - pool: AllocatorPool, - ) -> VkResult { - let mut pool_stats: ffi::VmaDetailedStatistics = mem::zeroed(); - ffi::vmaCalculatePoolStatistics(self.internal, pool, &mut pool_stats); - Ok(pool_stats) - } - - /// Checks magic number in margins around all allocations in given memory pool in search for corruptions. - /// - /// Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, - /// `VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is - /// `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` and `ash::vk::MemoryPropertyFlags::HOST_COHERENT`. - /// - /// Possible error values: - /// - /// - `ash::vk::Result::ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool. - /// - `ash::vk::Result::ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations. - /// `VMA_ASSERT` is also fired in that case. - /// - Other value: Error returned by Vulkan, e.g. memory mapping failure. - pub unsafe fn check_pool_corruption(&self, pool: AllocatorPool) -> VkResult<()> { - ffi::vmaCheckPoolCorruption(self.internal, pool).result() - } - /// General purpose memory allocation. /// /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. diff --git a/src/pool.rs b/src/pool.rs new file mode 100644 index 0000000..2b334f2 --- /dev/null +++ b/src/pool.rs @@ -0,0 +1,70 @@ +use std::sync::Arc; + +use crate::ffi; +use crate::Allocator; +use crate::PoolCreateInfo; +use ash::prelude::VkResult; + +/// Represents custom memory pool handle. +pub struct AllocatorPool { + allocator: Arc, + pub(crate) raw: ffi::VmaPool, +} + +impl Allocator { + /// Allocates Vulkan device memory and creates `AllocatorPool` object. + pub fn create_pool(self: &Arc, create_info: &PoolCreateInfo) -> VkResult { + unsafe { + let mut ffi_pool: ffi::VmaPool = std::mem::zeroed(); + ffi::vmaCreatePool(self.internal, &create_info.inner, &mut ffi_pool).result()?; + Ok(AllocatorPool { + raw: ffi_pool, + allocator: self.clone(), + }) + } + } +} + +impl Drop for AllocatorPool { + fn drop(&mut self) { + unsafe { + ffi::vmaDestroyPool(self.allocator.internal, self.raw); + } + } +} + +impl AllocatorPool { + /// Retrieves statistics of existing `AllocatorPool` object. + pub fn get_statistics(&self) -> VkResult { + unsafe { + let mut pool_stats: ffi::VmaStatistics = std::mem::zeroed(); + ffi::vmaGetPoolStatistics(self.allocator.internal, self.raw, &mut pool_stats); + Ok(pool_stats) + } + } + + /// Retrieves statistics of existing `AllocatorPool` object. + pub fn calculate_statistics(&self) -> VkResult { + unsafe { + let mut pool_stats: ffi::VmaDetailedStatistics = std::mem::zeroed(); + ffi::vmaCalculatePoolStatistics(self.allocator.internal, self.raw, &mut pool_stats); + Ok(pool_stats) + } + } + + /// Checks magic number in margins around all allocations in given memory pool in search for corruptions. + /// + /// Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, + /// `VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is + /// `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` and `ash::vk::MemoryPropertyFlags::HOST_COHERENT`. + /// + /// Possible error values: + /// + /// - `ash::vk::Result::ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool. + /// - `ash::vk::Result::ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations. + /// `VMA_ASSERT` is also fired in that case. + /// - Other value: Error returned by Vulkan, e.g. memory mapping failure. + pub unsafe fn check_corruption(&self) -> VkResult<()> { + ffi::vmaCheckPoolCorruption(self.allocator.internal, self.raw).result() + } +} From 8c2387d55643287c728ceab0c1d298653743742c Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 02:22:02 -0700 Subject: [PATCH 10/23] fix tests --- src/lib.rs | 14 ++-------- tests/mod.rs | 75 +++++++++++++++------------------------------------- 2 files changed, 23 insertions(+), 66 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 21e6739..7baed9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -777,24 +777,14 @@ impl Allocator { pub unsafe fn destroy_image(&self, image: ash::vk::Image, allocation: Allocation) { ffi::vmaDestroyImage(self.internal, image, allocation); } - - /// Destroys the internal allocator instance. After this has been called, - /// no other functions may be called. Useful for ensuring a specific destruction - /// order (for example, if an Allocator is a member of something that owns the Vulkan - /// instance and destroys it in its own Drop). - pub unsafe fn destroy(&mut self) { - if !self.internal.is_null() { - ffi::vmaDestroyAllocator(self.internal); - self.internal = std::ptr::null_mut(); - } - } } /// Custom `Drop` implementation to clean up internal allocation instance impl Drop for Allocator { fn drop(&mut self) { unsafe { - self.destroy(); + ffi::vmaDestroyAllocator(self.internal); + self.internal = std::ptr::null_mut(); } } } diff --git a/tests/mod.rs b/tests/mod.rs index 85fd851..bf5a7a0 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -2,7 +2,7 @@ extern crate ash; extern crate vk_mem; use ash::{extensions::ext::DebugUtils, vk}; -use std::os::raw::c_void; +use std::{os::raw::c_void, sync::Arc}; fn extension_names() -> Vec<*const i8> { vec![DebugUtils::name().as_ptr()] @@ -50,7 +50,7 @@ impl TestHarness { .application_version(0) .engine_name(&app_name) .engine_version(0) - .api_version(ash::vk::make_api_version(0, 1, 0, 0)); + .api_version(ash::vk::make_api_version(0, 1, 3, 0)); let layer_names = [::std::ffi::CString::new("VK_LAYER_KHRONOS_validation").unwrap()]; let layers_names_raw: Vec<*const i8> = layer_names @@ -76,7 +76,11 @@ impl TestHarness { ash::vk::DebugUtilsMessageSeverityFlagsEXT::ERROR | ash::vk::DebugUtilsMessageSeverityFlagsEXT::WARNING, ) - .message_type(vk::DebugUtilsMessageTypeFlagsEXT::GENERAL | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION) + .message_type( + vk::DebugUtilsMessageTypeFlagsEXT::GENERAL + | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE + | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION, + ) .pfn_user_callback(Some(vulkan_debug_callback)); let debug_report_loader = DebugUtils::new(&entry, &instance); @@ -208,6 +212,7 @@ fn create_cpu_buffer_preferred() { fn create_gpu_buffer_pool() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); + let allocator = Arc::new(allocator); let buffer_info = ash::vk::BufferCreateInfo::builder() .size(16 * 1024) @@ -232,14 +237,13 @@ fn create_gpu_buffer_pool() { .max_block_count(2); let pool = allocator.create_pool(&pool_info).unwrap(); - allocation_info = allocation_info.pool(pool.clone()); + allocation_info = allocation_info.pool(&pool); let (buffer, allocation, allocation_info) = allocator .create_buffer(&buffer_info, &allocation_info) .unwrap(); assert_ne!(allocation_info.get_mapped_data(), std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); - allocator.destroy_pool(pool); } } @@ -250,48 +254,10 @@ fn test_gpu_stats() { let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); unsafe { - let stats_1 = allocator.calculate_stats().unwrap(); - assert_eq!(stats_1.total.blockCount, 0); - assert_eq!(stats_1.total.allocationCount, 0); - assert_eq!(stats_1.total.usedBytes, 0); - - let (buffer, allocation, _allocation_info) = allocator - .create_buffer( - &ash::vk::BufferCreateInfo::builder() - .size(16 * 1024) - .usage( - ash::vk::BufferUsageFlags::VERTEX_BUFFER - | ash::vk::BufferUsageFlags::TRANSFER_DST, - ) - .build(), - &allocation_info, - ) - .unwrap(); - - let stats_2 = allocator.calculate_stats().unwrap(); - assert_eq!(stats_2.total.blockCount, 1); - assert_eq!(stats_2.total.allocationCount, 1); - assert_eq!(stats_2.total.usedBytes, 16 * 1024); - - allocator.destroy_buffer(buffer, allocation); - - let stats_3 = allocator.calculate_stats().unwrap(); - assert_eq!(stats_3.total.blockCount, 1); - assert_eq!(stats_3.total.allocationCount, 0); - assert_eq!(stats_3.total.usedBytes, 0); - } -} - -#[test] -fn test_stats_string() { - let harness = TestHarness::new(); - let allocator = harness.create_allocator(); - - let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); - - unsafe { - let stats_1 = allocator.build_stats_string(true).unwrap(); - assert!(stats_1.len() > 0); + let stats_1 = allocator.calculate_statistics().unwrap(); + assert_eq!(stats_1.total.statistics.blockCount, 0); + assert_eq!(stats_1.total.statistics.allocationCount, 0); + assert_eq!(stats_1.total.statistics.allocationBytes, 0); let (buffer, allocation, _allocation_info) = allocator .create_buffer( @@ -306,15 +272,16 @@ fn test_stats_string() { ) .unwrap(); - let stats_2 = allocator.build_stats_string(true).unwrap(); - assert!(stats_2.len() > 0); - assert_ne!(stats_1, stats_2); + let stats_2 = allocator.calculate_statistics().unwrap(); + assert_eq!(stats_2.total.statistics.blockCount, 1); + assert_eq!(stats_2.total.statistics.allocationCount, 1); + assert_eq!(stats_2.total.statistics.allocationBytes, 16 * 1024); allocator.destroy_buffer(buffer, allocation); - let stats_3 = allocator.build_stats_string(true).unwrap(); - assert!(stats_3.len() > 0); - assert_ne!(stats_3, stats_1); - assert_ne!(stats_3, stats_2); + let stats_3 = allocator.calculate_statistics().unwrap(); + assert_eq!(stats_3.total.statistics.blockCount, 1); + assert_eq!(stats_3.total.statistics.allocationCount, 0); + assert_eq!(stats_3.total.statistics.allocationBytes, 0); } } From 52bc7aa61c1a2d0214f9e696e9baf5fa8b3e7b1a Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 22:30:27 -0700 Subject: [PATCH 11/23] Update ALlocationCreateFlags --- src/definitions.rs | 115 +++++++++++++++++++++++++++------------------ tests/mod.rs | 4 +- 2 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index b5f2726..6c61ec6 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -217,15 +217,10 @@ bitflags! { bitflags! { /// Flags for configuring `Allocation` construction. pub struct AllocationCreateFlags: u32 { - /// Default configuration for allocation. - const NONE = 0x0000_0000; - /// Set this flag if the allocation should have its own memory block. /// /// Use it for special, big resources, like fullscreen images used as attachments. - /// - /// You should not use this flag if `AllocationCreateInfo::pool` is not `None`. - const DEDICATED_MEMORY = 0x0000_0001; + const DEDICATED_MEMORY = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT as u32; /// Set this flag to only try to allocate from existing `ash::vk::DeviceMemory` blocks and never create new such block. /// @@ -233,9 +228,7 @@ bitflags! { /// fails with `ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY` error. /// /// You should not use `AllocationCreateFlags::DEDICATED_MEMORY` and `AllocationCreateFlags::NEVER_ALLOCATE` at the same time. It makes no sense. - /// - /// If `AllocationCreateInfo::pool` is not `None`, this flag is implied and ignored. - const NEVER_ALLOCATE = 0x0000_0002; + const NEVER_ALLOCATE = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT as u32; /// Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. /// @@ -248,64 +241,96 @@ bitflags! { /// support it (e.g. Intel GPU). /// /// You should not use this flag together with `AllocationCreateFlags::CAN_BECOME_LOST`. - const MAPPED = 0x0000_0004; - - /// Allocation created with this flag can become lost as a result of another - /// allocation with `AllocationCreateFlags::CAN_MAKE_OTHER_LOST` flag, so you must check it before use. - /// - /// To check if allocation is not lost, call `Allocator::get_allocation_info` and check if - /// `AllocationInfo::device_memory` is not null. - /// - /// You should not use this flag together with `AllocationCreateFlags::MAPPED`. - const CAN_BECOME_LOST = 0x0000_0008; - - /// While creating allocation using this flag, other allocations that were - /// created with flag `AllocationCreateFlags::CAN_BECOME_LOST` can become lost. - const CAN_MAKE_OTHER_LOST = 0x0000_0010; + const MAPPED = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT as u32; /// Set this flag to treat `AllocationCreateInfo::user_data` as pointer to a /// null-terminated string. Instead of copying pointer value, a local copy of the /// string is made and stored in allocation's user data. The string is automatically /// freed together with the allocation. It is also used in `Allocator::build_stats_string`. - const USER_DATA_COPY_STRING = 0x0000_0020; + #[deprecated(since = "0.3", note = "Consider using vmaSetAllocationName() instead.")] + const USER_DATA_COPY_STRING = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT as u32; /// Allocation will be created from upper stack in a double stack pool. /// /// This flag is only allowed for custom pools created with `AllocatorPoolCreateFlags::LINEAR_ALGORITHM` flag. - const UPPER_ADDRESS = 0x0000_0040; + const UPPER_ADDRESS = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT as u32; /// Create both buffer/image and allocation, but don't bind them together. /// It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions. /// The flag is meaningful only with functions that bind by default, such as `Allocator::create_buffer` /// or `Allocator::create_image`. Otherwise it is ignored. - const CREATE_DONT_BIND = 0x0000_0080; + /// + /// If you want to make sure the new buffer/image is not tied to the new memory allocation + /// through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block, + /// use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT. + const DONT_BIND = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DONT_BIND_BIT as u32; - /// Allocation strategy that chooses smallest possible free range for the - /// allocation. - const STRATEGY_BEST_FIT = 0x0001_0000; + /// Create allocation only if additional device memory required for it, if any, won't exceed + /// memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + const WITHIN_BUDGET = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT as u32; - /// Allocation strategy that chooses biggest possible free range for the - /// allocation. - const STRATEGY_WORST_FIT = 0x0002_0000; + /// Set this flag if the allocated memory will have aliasing resources. + /// + /// Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified. + /// Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors. + const CAN_ALIAS = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT as u32; - /// Allocation strategy that chooses first suitable free range for the - /// allocation. + /// Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). /// - /// "First" doesn't necessarily means the one with smallest offset in memory, - /// but rather the one that is easiest and fastest to find. - const STRATEGY_FIRST_FIT = 0x0004_0000; + /// - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, + /// you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. + /// - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. + /// This includes allocations created in custom_memory_pools. + /// + /// Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number, + /// never read or accessed randomly, so a memory type can be selected that is uncached and write-combined. + /// + /// Violating this declaration may work correctly, but will likely be very slow. + /// Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;` + /// Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once. + const HOST_ACCESS_SEQUENTIAL_WRITE = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT as u32; + + /// Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). + /// + /// - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, + /// you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. + /// - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. + /// This includes allocations created in custom_memory_pools. + /// + /// Declares that mapped memory can be read, written, and accessed in random order, + /// so a `HOST_CACHED` memory type is required. + const HOST_ACCESS_RANDOM = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT as u32; + + /// Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, + /// it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected + /// if it may improve performance. + /// + /// By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type + /// (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and + /// issue an explicit transfer to write/read your data. + /// To prepare for this possibility, don't forget to add appropriate flags like + /// `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image. + const HOST_ACCESS_ALLOW_TRANSFER_INSTEAD = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT as u32; + + /// Allocation strategy that chooses smallest possible free range for the allocation + /// to minimize memory usage and fragmentation, possibly at the expense of allocation time. + const STRATEGY_MIN_MEMORY = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32; - /// Allocation strategy that tries to minimize memory usage. - const STRATEGY_MIN_MEMORY = 0x0001_0000; + /// Alias to `STRATEGY_MIN_MEMORY`. + const STRATEGY_BEST_FIT = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32; - /// Allocation strategy that tries to minimize allocation time. - const STRATEGY_MIN_TIME = 0x0004_0000; + /// Allocation strategy that chooses first suitable free range for the allocation - + /// not necessarily in terms of the smallest offset but the one that is easiest and fastest to find + /// to minimize allocation time, possibly at the expense of allocation quality. + const STRATEGY_MIN_TIME = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32; - /// Allocation strategy that tries to minimize memory fragmentation. - const STRATEGY_MIN_FRAGMENTATION = 0x0002_0000; + /// Alias to `STRATEGY_MIN_TIME`. + const STRATEGY_FIRST_FIT = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32; - /// A bit mask to extract only `*_STRATEGY` bits from entire set of flags. - const STRATEGY_MASK = 0x0001_0000 | 0x0002_0000 | 0x0004_0000; + /// Allocation strategy that chooses always the lowest offset in available space. + /// This is not the most efficient strategy but achieves highly packed data. + /// Used internally by defragmentation, not recomended in typical usage. + const STRATEGY_MIN_OFFSET = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT as u32; } } diff --git a/tests/mod.rs b/tests/mod.rs index bf5a7a0..70e9377 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -160,7 +160,7 @@ fn create_allocator() { fn create_gpu_buffer() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); + let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::Auto); unsafe { let (buffer, allocation, allocation_info) = allocator @@ -251,7 +251,7 @@ fn create_gpu_buffer_pool() { fn test_gpu_stats() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::GpuOnly); + let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::Auto); unsafe { let stats_1 = allocator.calculate_statistics().unwrap(); From 9fa88a0b4bf338370ff791e34d78ad0289f0142d Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 23:41:44 -0700 Subject: [PATCH 12/23] refactor pools --- src/definitions.rs | 126 +++++++++--------- src/lib.rs | 262 ------------------------------------ src/pool.rs | 324 ++++++++++++++++++++++++++++++++++++++++++++- tests/mod.rs | 44 +++--- 4 files changed, 410 insertions(+), 346 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index 6c61ec6..ae21326 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -1,5 +1,5 @@ -use crate::ffi::VmaAllocationCreateInfo; -use crate::{ffi, AllocatorPool}; +use crate::ffi; +use ash::vk; use ash::vk::PhysicalDevice; use ash::{Device, Instance}; use bitflags::bitflags; @@ -337,8 +337,6 @@ bitflags! { bitflags! { /// Flags for configuring `AllocatorPool` construction. pub struct AllocatorPoolCreateFlags: u32 { - const NONE = 0; - /// Use this flag if you always allocate only buffers and linear images or only optimal images /// out of this pool and so buffer-image granularity can be ignored. /// @@ -522,35 +520,66 @@ impl<'a> PoolCreateInfo<'a> { } } -pub struct AllocationCreateInfo<'a> { - pub(crate) inner: ffi::VmaAllocationCreateInfo, - marker: ::std::marker::PhantomData<&'a ()>, +#[derive(Clone)] +pub struct AllocationCreateInfo { + pub flags: AllocationCreateFlags, + /// Intended usage of memory. + /// + /// You can leave `MemoryUsage::Unknown` if you specify memory requirements in other way. + /// + /// If `pool` is not null, this member is ignored. + pub usage: MemoryUsage, + /// Flags that must be set in a Memory Type chosen for an allocation. + /// + /// Leave 0 if you specify memory requirements in other way. + /// + /// If `pool` is not null, this member is ignored. + pub required_flags: vk::MemoryPropertyFlags, + /// Flags that preferably should be set in a memory type chosen for an allocation."] + /// + /// Set to 0 if no additional flags are preferred. + /// If `pool` is not null, this member is ignored. + pub preferred_flags: vk::MemoryPropertyFlags, + /// Bitmask containing one bit set for every memory type acceptable for this allocation. + /// + /// Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if + /// it meets other requirements specified by this structure, with no further + /// restrictions on memory type index. + /// + /// If `pool` is not null, this member is ignored. + pub memory_type_bits: u32, + /// Custom general-purpose pointer that will be stored in `Allocation`, + /// can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData(). + /// + /// If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either + /// null or pointer to a null-terminated string. The string will be then copied to + /// internal buffer, so it doesn't need to be valid after allocation call. + pub user_data: usize, + /// A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. + /// + /// It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object + /// and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + /// Otherwise, it has the priority of a memory block where it is placed and this variable is ignored. + pub priority: f32, } -impl<'a> AllocationCreateInfo<'a> { - pub fn new() -> AllocationCreateInfo<'a> { - AllocationCreateInfo { - inner: VmaAllocationCreateInfo { - flags: 0, - usage: ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN, - requiredFlags: Default::default(), - preferredFlags: Default::default(), - memoryTypeBits: 0, - pool: ptr::null_mut(), - pUserData: ptr::null_mut(), - priority: 0.0, - }, - marker: ::std::marker::PhantomData, +impl Default for AllocationCreateInfo { + fn default() -> Self { + Self { + flags: AllocationCreateFlags::empty(), + usage: MemoryUsage::Unknown, + required_flags: vk::MemoryPropertyFlags::empty(), + preferred_flags: vk::MemoryPropertyFlags::empty(), + memory_type_bits: 0, + user_data: 0, + priority: 0.0, } } +} - pub fn flags(mut self, flags: AllocationCreateFlags) -> Self { - self.inner.flags = flags.bits(); - self - } - - pub fn usage(mut self, usage: MemoryUsage) -> Self { - self.inner.usage = match usage { +impl From<&AllocationCreateInfo> for ffi::VmaAllocationCreateInfo { + fn from(info: &AllocationCreateInfo) -> Self { + let usage = match info.usage { MemoryUsage::Unknown => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN, #[allow(deprecated)] MemoryUsage::GpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_ONLY, @@ -569,36 +598,15 @@ impl<'a> AllocationCreateInfo<'a> { } MemoryUsage::AutoPreferHost => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_HOST, }; - self - } - - pub fn required_flags(mut self, flags: ash::vk::MemoryPropertyFlags) -> Self { - self.inner.requiredFlags = flags; - self - } - - pub fn preferred_flags(mut self, flags: ash::vk::MemoryPropertyFlags) -> Self { - self.inner.preferredFlags = flags; - self - } - - pub fn memory_type_bits(mut self, flags: u32) -> Self { - self.inner.memoryTypeBits = flags; - self - } - - pub fn pool(mut self, pool: &AllocatorPool) -> Self { - self.inner.pool = pool.raw; - self - } - - pub fn user_data(mut self, p_user_data: *mut ::std::os::raw::c_void) -> Self { - self.inner.pUserData = p_user_data; - self - } - - pub fn priority(mut self, priority: f32) -> Self { - self.inner.priority = priority; - self + ffi::VmaAllocationCreateInfo { + flags: info.flags.bits(), + usage, + requiredFlags: info.required_flags, + preferredFlags: info.preferred_flags, + memoryTypeBits: info.memory_type_bits, + pool: std::ptr::null_mut(), + pUserData: info.user_data as _, + priority: info.priority, + } } } diff --git a/src/lib.rs b/src/lib.rs index 7baed9b..1addd52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -270,196 +270,6 @@ impl Allocator { } } - /// Helps to find memory type index, given memory type bits and allocation info. - /// - /// This algorithm tries to find a memory type that: - /// - /// - Is allowed by memory type bits. - /// - Contains all the flags from `allocation_info.required_flags`. - /// - Matches intended usage. - /// - Has as many flags from `allocation_info.preferred_flags` as possible. - /// - /// Returns ash::vk::Result::ERROR_FEATURE_NOT_PRESENT if not found. Receiving such a result - /// from this function or any other allocating function probably means that your - /// device doesn't support any memory type with requested features for the specific - /// type of resource you want to use it for. Please check parameters of your - /// resource, like image layout (OPTIMAL versus LINEAR) or mip level count. - pub unsafe fn find_memory_type_index( - &self, - memory_type_bits: u32, - allocation_info: &AllocationCreateInfo, - ) -> VkResult { - let mut memory_type_index: u32 = 0; - ffi::vmaFindMemoryTypeIndex( - self.internal, - memory_type_bits, - &allocation_info.inner, - &mut memory_type_index, - ) - .result()?; - - Ok(memory_type_index) - } - - /// Helps to find memory type index, given buffer info and allocation info. - /// - /// It can be useful e.g. to determine value to be used as `AllocatorPoolCreateInfo::memory_type_index`. - /// It internally creates a temporary, dummy buffer that never has memory bound. - /// It is just a convenience function, equivalent to calling: - /// - /// - `ash::vk::Device::create_buffer` - /// - `ash::vk::Device::get_buffer_memory_requirements` - /// - `Allocator::find_memory_type_index` - /// - `ash::vk::Device::destroy_buffer` - pub unsafe fn find_memory_type_index_for_buffer_info( - &self, - buffer_info: &ash::vk::BufferCreateInfo, - allocation_info: &AllocationCreateInfo, - ) -> VkResult { - let mut memory_type_index: u32 = 0; - ffi::vmaFindMemoryTypeIndexForBufferInfo( - self.internal, - buffer_info, - &allocation_info.inner, - &mut memory_type_index, - ) - .result()?; - - Ok(memory_type_index) - } - - /// Helps to find memory type index, given image info and allocation info. - /// - /// It can be useful e.g. to determine value to be used as `AllocatorPoolCreateInfo::memory_type_index`. - /// It internally creates a temporary, dummy image that never has memory bound. - /// It is just a convenience function, equivalent to calling: - /// - /// - `ash::vk::Device::create_image` - /// - `ash::vk::Device::get_image_memory_requirements` - /// - `Allocator::find_memory_type_index` - /// - `ash::vk::Device::destroy_image` - pub unsafe fn find_memory_type_index_for_image_info( - &self, - image_info: ash::vk::ImageCreateInfo, - allocation_info: &AllocationCreateInfo, - ) -> VkResult { - let mut memory_type_index: u32 = 0; - ffi::vmaFindMemoryTypeIndexForImageInfo( - self.internal, - &image_info, - &allocation_info.inner, - &mut memory_type_index, - ) - .result()?; - - Ok(memory_type_index) - } - - /// General purpose memory allocation. - /// - /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. - /// - /// It is recommended to use `Allocator::allocate_memory_for_buffer`, `Allocator::allocate_memory_for_image`, - /// `Allocator::create_buffer`, `Allocator::create_image` instead whenever possible. - pub unsafe fn allocate_memory( - &self, - memory_requirements: &ash::vk::MemoryRequirements, - create_info: &AllocationCreateInfo, - ) -> VkResult<(Allocation, AllocationInfo)> { - let mut allocation: Allocation = mem::zeroed(); - let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi::vmaAllocateMemory( - self.internal, - memory_requirements, - &create_info.inner, - &mut allocation, - &mut allocation_info.internal, - ) - .result()?; - - Ok((allocation, allocation_info)) - } - - /// General purpose memory allocation for multiple allocation objects at once. - /// - /// You should free the memory using `Allocator::free_memory` or `Allocator::free_memory_pages`. - /// - /// Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. - /// It is just a general purpose allocation function able to make multiple allocations at once. - /// It may be internally optimized to be more efficient than calling `Allocator::allocate_memory` `allocations.len()` times. - /// - /// All allocations are made using same parameters. All of them are created out of the same memory pool and type. - pub unsafe fn allocate_memory_pages( - &self, - memory_requirements: &ash::vk::MemoryRequirements, - create_info: &AllocationCreateInfo, - allocation_count: usize, - ) -> VkResult> { - let mut allocations: Vec = vec![mem::zeroed(); allocation_count]; - let mut allocation_info: Vec = - vec![mem::zeroed(); allocation_count]; - ffi::vmaAllocateMemoryPages( - self.internal, - memory_requirements, - &create_info.inner, - allocation_count, - allocations.as_mut_ptr(), - allocation_info.as_mut_ptr(), - ) - .result()?; - - let it = allocations.iter().zip(allocation_info.iter()); - let allocations: Vec<(Allocation, AllocationInfo)> = it - .map(|(alloc, info)| (*alloc, AllocationInfo { internal: *info })) - .collect(); - - Ok(allocations) - } - - /// Buffer specialized memory allocation. - /// - /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. - pub unsafe fn allocate_memory_for_buffer( - &self, - buffer: ash::vk::Buffer, - create_info: &AllocationCreateInfo, - ) -> VkResult<(Allocation, AllocationInfo)> { - let mut allocation: Allocation = mem::zeroed(); - let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi::vmaAllocateMemoryForBuffer( - self.internal, - buffer, - &create_info.inner, - &mut allocation, - &mut allocation_info.internal, - ) - .result()?; - - Ok((allocation, allocation_info)) - } - - /// Image specialized memory allocation. - /// - /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. - pub unsafe fn allocate_memory_for_image( - &self, - image: ash::vk::Image, - create_info: &AllocationCreateInfo, - ) -> VkResult<(Allocation, AllocationInfo)> { - let mut allocation: Allocation = mem::zeroed(); - let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi::vmaAllocateMemoryForImage( - self.internal, - image, - &create_info.inner, - &mut allocation, - &mut allocation_info.internal, - ) - .result()?; - - Ok((allocation, allocation_info)) - } - /// Frees memory previously allocated using `Allocator::allocate_memory`, /// `Allocator::allocate_memory_for_buffer`, or `Allocator::allocate_memory_for_image`. pub unsafe fn free_memory(&self, allocation: Allocation) { @@ -678,40 +488,6 @@ impl Allocator { ffi::vmaBindImageMemory(self.internal, allocation, image).result() } - /// This function automatically creates a buffer, allocates appropriate memory - /// for it, and binds the buffer with the memory. - /// - /// If the function succeeded, you must destroy both buffer and allocation when you - /// no longer need them using either convenience function `Allocator::destroy_buffer` or - /// separately, using `ash::Device::destroy_buffer` and `Allocator::free_memory`. - /// - /// If `AllocatorCreateFlags::KHR_DEDICATED_ALLOCATION` flag was used, - /// VK_KHR_dedicated_allocation extension is used internally to query driver whether - /// it requires or prefers the new buffer to have dedicated allocation. If yes, - /// and if dedicated allocation is possible (AllocationCreateInfo::pool is null - /// and `AllocationCreateFlags::NEVER_ALLOCATE` is not used), it creates dedicated - /// allocation for this buffer, just like when using `AllocationCreateFlags::DEDICATED_MEMORY`. - pub unsafe fn create_buffer( - &self, - buffer_info: &ash::vk::BufferCreateInfo, - allocation_create_info: &AllocationCreateInfo, - ) -> VkResult<(ash::vk::Buffer, Allocation, AllocationInfo)> { - let mut buffer = vk::Buffer::null(); - let mut allocation: Allocation = mem::zeroed(); - let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi::vmaCreateBuffer( - self.internal, - &*buffer_info, - &allocation_create_info.inner, - &mut buffer, - &mut allocation, - &mut allocation_info.internal, - ) - .result()?; - - Ok((buffer, allocation, allocation_info)) - } - /// Destroys Vulkan buffer and frees allocated memory. /// /// This is just a convenience function equivalent to: @@ -726,44 +502,6 @@ impl Allocator { ffi::vmaDestroyBuffer(self.internal, buffer, allocation); } - /// This function automatically creates an image, allocates appropriate memory - /// for it, and binds the image with the memory. - /// - /// If the function succeeded, you must destroy both image and allocation when you - /// no longer need them using either convenience function `Allocator::destroy_image` or - /// separately, using `ash::Device::destroy_image` and `Allocator::free_memory`. - /// - /// If `AllocatorCreateFlags::KHR_DEDICATED_ALLOCATION` flag was used, - /// `VK_KHR_dedicated_allocation extension` is used internally to query driver whether - /// it requires or prefers the new image to have dedicated allocation. If yes, - /// and if dedicated allocation is possible (AllocationCreateInfo::pool is null - /// and `AllocationCreateFlags::NEVER_ALLOCATE` is not used), it creates dedicated - /// allocation for this image, just like when using `AllocationCreateFlags::DEDICATED_MEMORY`. - /// - /// If `VK_ERROR_VALIDAITON_FAILED_EXT` is returned, VMA may have encountered a problem - /// that is not caught by the validation layers. One example is if you try to create a 0x0 - /// image, a panic will occur and `VK_ERROR_VALIDAITON_FAILED_EXT` is thrown. - pub unsafe fn create_image( - &self, - image_info: &ash::vk::ImageCreateInfo, - allocation_create_info: &AllocationCreateInfo, - ) -> VkResult<(ash::vk::Image, Allocation, AllocationInfo)> { - let mut image = vk::Image::null(); - let mut allocation: Allocation = mem::zeroed(); - let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi::vmaCreateImage( - self.internal, - &*image_info, - &allocation_create_info.inner, - &mut image, - &mut allocation, - &mut allocation_info.internal, - ) - .result()?; - - Ok((image, allocation, allocation_info)) - } - /// Destroys Vulkan image and frees allocated memory. /// /// This is just a convenience function equivalent to: diff --git a/src/pool.rs b/src/pool.rs index 2b334f2..6b2d17f 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -1,15 +1,23 @@ use std::sync::Arc; use crate::ffi; +use crate::Allocation; +use crate::AllocationCreateInfo; +use crate::AllocationInfo; use crate::Allocator; use crate::PoolCreateInfo; use ash::prelude::VkResult; +use ash::vk; +#[derive(Clone, Copy)] +pub struct PoolHandle(ffi::VmaPool); /// Represents custom memory pool handle. pub struct AllocatorPool { allocator: Arc, - pub(crate) raw: ffi::VmaPool, + pub(crate) pool: PoolHandle, } +unsafe impl Send for AllocatorPool {} +unsafe impl Sync for AllocatorPool {} impl Allocator { /// Allocates Vulkan device memory and creates `AllocatorPool` object. @@ -18,7 +26,7 @@ impl Allocator { let mut ffi_pool: ffi::VmaPool = std::mem::zeroed(); ffi::vmaCreatePool(self.internal, &create_info.inner, &mut ffi_pool).result()?; Ok(AllocatorPool { - raw: ffi_pool, + pool: PoolHandle(ffi_pool), allocator: self.clone(), }) } @@ -28,7 +36,7 @@ impl Allocator { impl Drop for AllocatorPool { fn drop(&mut self) { unsafe { - ffi::vmaDestroyPool(self.allocator.internal, self.raw); + ffi::vmaDestroyPool(self.allocator.internal, self.pool.0); } } } @@ -38,7 +46,7 @@ impl AllocatorPool { pub fn get_statistics(&self) -> VkResult { unsafe { let mut pool_stats: ffi::VmaStatistics = std::mem::zeroed(); - ffi::vmaGetPoolStatistics(self.allocator.internal, self.raw, &mut pool_stats); + ffi::vmaGetPoolStatistics(self.allocator.internal, self.pool.0, &mut pool_stats); Ok(pool_stats) } } @@ -47,7 +55,7 @@ impl AllocatorPool { pub fn calculate_statistics(&self) -> VkResult { unsafe { let mut pool_stats: ffi::VmaDetailedStatistics = std::mem::zeroed(); - ffi::vmaCalculatePoolStatistics(self.allocator.internal, self.raw, &mut pool_stats); + ffi::vmaCalculatePoolStatistics(self.allocator.internal, self.pool.0, &mut pool_stats); Ok(pool_stats) } } @@ -64,7 +72,309 @@ impl AllocatorPool { /// - `ash::vk::Result::ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations. /// `VMA_ASSERT` is also fired in that case. /// - Other value: Error returned by Vulkan, e.g. memory mapping failure. - pub unsafe fn check_corruption(&self) -> VkResult<()> { - ffi::vmaCheckPoolCorruption(self.allocator.internal, self.raw).result() + pub fn check_corruption(&self) -> VkResult<()> { + unsafe { ffi::vmaCheckPoolCorruption(self.allocator.internal, self.pool.0).result() } + } +} + +pub trait Alloc { + fn allocator(&self) -> &Allocator; + fn pool(&self) -> PoolHandle; + /// Helps to find memory type index, given memory type bits and allocation info. + /// + /// This algorithm tries to find a memory type that: + /// + /// - Is allowed by memory type bits. + /// - Contains all the flags from `allocation_info.required_flags`. + /// - Matches intended usage. + /// - Has as many flags from `allocation_info.preferred_flags` as possible. + /// + /// Returns ash::vk::Result::ERROR_FEATURE_NOT_PRESENT if not found. Receiving such a result + /// from this function or any other allocating function probably means that your + /// device doesn't support any memory type with requested features for the specific + /// type of resource you want to use it for. Please check parameters of your + /// resource, like image layout (OPTIMAL versus LINEAR) or mip level count. + unsafe fn find_memory_type_index( + &self, + memory_type_bits: u32, + allocation_info: &AllocationCreateInfo, + ) -> VkResult { + let mut memory_type_index: u32 = 0; + let mut allocation_info: ffi::VmaAllocationCreateInfo = allocation_info.into(); + allocation_info.pool = self.pool().0; + ffi::vmaFindMemoryTypeIndex( + self.allocator().internal, + memory_type_bits, + &allocation_info, + &mut memory_type_index, + ) + .result()?; + + Ok(memory_type_index) + } + + /// Helps to find memory type index, given buffer info and allocation info. + /// + /// It can be useful e.g. to determine value to be used as `AllocatorPoolCreateInfo::memory_type_index`. + /// It internally creates a temporary, dummy buffer that never has memory bound. + /// It is just a convenience function, equivalent to calling: + /// + /// - `ash::vk::Device::create_buffer` + /// - `ash::vk::Device::get_buffer_memory_requirements` + /// - `Allocator::find_memory_type_index` + /// - `ash::vk::Device::destroy_buffer` + unsafe fn find_memory_type_index_for_buffer_info( + &self, + buffer_info: &ash::vk::BufferCreateInfo, + allocation_info: &AllocationCreateInfo, + ) -> VkResult { + let mut allocation_info: ffi::VmaAllocationCreateInfo = allocation_info.into(); + allocation_info.pool = self.pool().0; + let mut memory_type_index: u32 = 0; + ffi::vmaFindMemoryTypeIndexForBufferInfo( + self.allocator().internal, + buffer_info, + &allocation_info, + &mut memory_type_index, + ) + .result()?; + + Ok(memory_type_index) + } + + /// Helps to find memory type index, given image info and allocation info. + /// + /// It can be useful e.g. to determine value to be used as `AllocatorPoolCreateInfo::memory_type_index`. + /// It internally creates a temporary, dummy image that never has memory bound. + /// It is just a convenience function, equivalent to calling: + /// + /// - `ash::vk::Device::create_image` + /// - `ash::vk::Device::get_image_memory_requirements` + /// - `Allocator::find_memory_type_index` + /// - `ash::vk::Device::destroy_image` + unsafe fn find_memory_type_index_for_image_info( + &self, + image_info: ash::vk::ImageCreateInfo, + allocation_info: &AllocationCreateInfo, + ) -> VkResult { + let mut allocation_info: ffi::VmaAllocationCreateInfo = allocation_info.into(); + allocation_info.pool = self.pool().0; + let mut memory_type_index: u32 = 0; + ffi::vmaFindMemoryTypeIndexForImageInfo( + self.allocator().internal, + &image_info, + &allocation_info, + &mut memory_type_index, + ) + .result()?; + + Ok(memory_type_index) + } + + /// General purpose memory allocation. + /// + /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. + /// + /// It is recommended to use `Allocator::allocate_memory_for_buffer`, `Allocator::allocate_memory_for_image`, + /// `Allocator::create_buffer`, `Allocator::create_image` instead whenever possible. + unsafe fn allocate_memory( + &self, + memory_requirements: &ash::vk::MemoryRequirements, + create_info: &AllocationCreateInfo, + ) -> VkResult<(Allocation, AllocationInfo)> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut allocation: Allocation = std::mem::zeroed(); + let mut allocation_info: AllocationInfo = std::mem::zeroed(); + ffi::vmaAllocateMemory( + self.allocator().internal, + memory_requirements, + &create_info, + &mut allocation, + &mut allocation_info.internal, + ) + .result()?; + + Ok((allocation, allocation_info)) + } + + /// General purpose memory allocation for multiple allocation objects at once. + /// + /// You should free the memory using `Allocator::free_memory` or `Allocator::free_memory_pages`. + /// + /// Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. + /// It is just a general purpose allocation function able to make multiple allocations at once. + /// It may be internally optimized to be more efficient than calling `Allocator::allocate_memory` `allocations.len()` times. + /// + /// All allocations are made using same parameters. All of them are created out of the same memory pool and type. + unsafe fn allocate_memory_pages( + &self, + memory_requirements: &ash::vk::MemoryRequirements, + create_info: &AllocationCreateInfo, + allocation_count: usize, + ) -> VkResult> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut allocations: Vec = vec![std::mem::zeroed(); allocation_count]; + let mut allocation_info: Vec = + vec![std::mem::zeroed(); allocation_count]; + ffi::vmaAllocateMemoryPages( + self.allocator().internal, + memory_requirements, + &create_info, + allocation_count, + allocations.as_mut_ptr(), + allocation_info.as_mut_ptr(), + ) + .result()?; + + let it = allocations.iter().zip(allocation_info.iter()); + let allocations: Vec<(Allocation, AllocationInfo)> = it + .map(|(alloc, info)| (*alloc, AllocationInfo { internal: *info })) + .collect(); + + Ok(allocations) + } + + /// Buffer specialized memory allocation. + /// + /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. + unsafe fn allocate_memory_for_buffer( + &self, + buffer: ash::vk::Buffer, + create_info: &AllocationCreateInfo, + ) -> VkResult<(Allocation, AllocationInfo)> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut allocation: Allocation = std::mem::zeroed(); + let mut allocation_info: AllocationInfo = std::mem::zeroed(); + ffi::vmaAllocateMemoryForBuffer( + self.allocator().internal, + buffer, + &create_info, + &mut allocation, + &mut allocation_info.internal, + ) + .result()?; + + Ok((allocation, allocation_info)) + } + + /// Image specialized memory allocation. + /// + /// You should free the memory using `Allocator::free_memory` or 'Allocator::free_memory_pages'. + unsafe fn allocate_memory_for_image( + &self, + image: ash::vk::Image, + create_info: &AllocationCreateInfo, + ) -> VkResult<(Allocation, AllocationInfo)> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut allocation: Allocation = std::mem::zeroed(); + let mut allocation_info: AllocationInfo = std::mem::zeroed(); + ffi::vmaAllocateMemoryForImage( + self.allocator().internal, + image, + &create_info, + &mut allocation, + &mut allocation_info.internal, + ) + .result()?; + + Ok((allocation, allocation_info)) + } + + /// This function automatically creates a buffer, allocates appropriate memory + /// for it, and binds the buffer with the memory. + /// + /// If the function succeeded, you must destroy both buffer and allocation when you + /// no longer need them using either convenience function `Allocator::destroy_buffer` or + /// separately, using `ash::Device::destroy_buffer` and `Allocator::free_memory`. + /// + /// If `AllocatorCreateFlags::KHR_DEDICATED_ALLOCATION` flag was used, + /// VK_KHR_dedicated_allocation extension is used internally to query driver whether + /// it requires or prefers the new buffer to have dedicated allocation. If yes, + /// and if dedicated allocation is possible (AllocationCreateInfo::pool is null + /// and `AllocationCreateFlags::NEVER_ALLOCATE` is not used), it creates dedicated + /// allocation for this buffer, just like when using `AllocationCreateFlags::DEDICATED_MEMORY`. + unsafe fn create_buffer( + &self, + buffer_info: &ash::vk::BufferCreateInfo, + create_info: &AllocationCreateInfo, + ) -> VkResult<(ash::vk::Buffer, Allocation, AllocationInfo)> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut buffer = vk::Buffer::null(); + let mut allocation: Allocation = std::mem::zeroed(); + let mut allocation_info: AllocationInfo = std::mem::zeroed(); + ffi::vmaCreateBuffer( + self.allocator().internal, + &*buffer_info, + &create_info, + &mut buffer, + &mut allocation, + &mut allocation_info.internal, + ) + .result()?; + + Ok((buffer, allocation, allocation_info)) + } + /// This function automatically creates an image, allocates appropriate memory + /// for it, and binds the image with the memory. + /// + /// If the function succeeded, you must destroy both image and allocation when you + /// no longer need them using either convenience function `Allocator::destroy_image` or + /// separately, using `ash::Device::destroy_image` and `Allocator::free_memory`. + /// + /// If `AllocatorCreateFlags::KHR_DEDICATED_ALLOCATION` flag was used, + /// `VK_KHR_dedicated_allocation extension` is used internally to query driver whether + /// it requires or prefers the new image to have dedicated allocation. If yes, + /// and if dedicated allocation is possible (AllocationCreateInfo::pool is null + /// and `AllocationCreateFlags::NEVER_ALLOCATE` is not used), it creates dedicated + /// allocation for this image, just like when using `AllocationCreateFlags::DEDICATED_MEMORY`. + /// + /// If `VK_ERROR_VALIDAITON_FAILED_EXT` is returned, VMA may have encountered a problem + /// that is not caught by the validation layers. One example is if you try to create a 0x0 + /// image, a panic will occur and `VK_ERROR_VALIDAITON_FAILED_EXT` is thrown. + unsafe fn create_image( + &self, + image_info: &ash::vk::ImageCreateInfo, + create_info: &AllocationCreateInfo, + ) -> VkResult<(ash::vk::Image, Allocation, AllocationInfo)> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut image = vk::Image::null(); + let mut allocation: Allocation = std::mem::zeroed(); + let mut allocation_info: AllocationInfo = std::mem::zeroed(); + ffi::vmaCreateImage( + self.allocator().internal, + &*image_info, + &create_info, + &mut image, + &mut allocation, + &mut allocation_info.internal, + ) + .result()?; + + Ok((image, allocation, allocation_info)) + } +} + +impl Alloc for AllocatorPool { + fn allocator(&self) -> &Allocator { + self.allocator.as_ref() + } + + fn pool(&self) -> PoolHandle { + self.pool + } +} +impl Alloc for Allocator { + fn allocator(&self) -> &Allocator { + self + } + + fn pool(&self) -> PoolHandle { + PoolHandle(std::ptr::null_mut()) } } diff --git a/tests/mod.rs b/tests/mod.rs index 70e9377..066ea87 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -3,6 +3,7 @@ extern crate vk_mem; use ash::{extensions::ext::DebugUtils, vk}; use std::{os::raw::c_void, sync::Arc}; +use vk_mem::Alloc; fn extension_names() -> Vec<*const i8> { vec![DebugUtils::name().as_ptr()] @@ -160,7 +161,10 @@ fn create_allocator() { fn create_gpu_buffer() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::Auto); + let allocation_info = vk_mem::AllocationCreateInfo { + usage: vk_mem::MemoryUsage::Auto, + ..Default::default() + }; unsafe { let (buffer, allocation, allocation_info) = allocator @@ -184,12 +188,13 @@ fn create_gpu_buffer() { fn create_cpu_buffer_preferred() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new() - .required_flags(ash::vk::MemoryPropertyFlags::HOST_VISIBLE) - .preferred_flags( - ash::vk::MemoryPropertyFlags::HOST_COHERENT | ash::vk::MemoryPropertyFlags::HOST_CACHED, - ) - .flags(vk_mem::AllocationCreateFlags::MAPPED); + let allocation_info = vk_mem::AllocationCreateInfo { + required_flags: ash::vk::MemoryPropertyFlags::HOST_VISIBLE, + preferred_flags: ash::vk::MemoryPropertyFlags::HOST_COHERENT + | ash::vk::MemoryPropertyFlags::HOST_CACHED, + flags: vk_mem::AllocationCreateFlags::MAPPED, + ..Default::default() + }; unsafe { let (buffer, allocation, allocation_info) = allocator .create_buffer( @@ -219,12 +224,14 @@ fn create_gpu_buffer_pool() { .usage(ash::vk::BufferUsageFlags::UNIFORM_BUFFER | ash::vk::BufferUsageFlags::TRANSFER_DST) .build(); - let mut allocation_info = vk_mem::AllocationCreateInfo::new() - .required_flags(ash::vk::MemoryPropertyFlags::HOST_VISIBLE) - .preferred_flags( - ash::vk::MemoryPropertyFlags::HOST_COHERENT | ash::vk::MemoryPropertyFlags::HOST_CACHED, - ) - .flags(vk_mem::AllocationCreateFlags::MAPPED); + let allocation_info = vk_mem::AllocationCreateInfo { + required_flags: ash::vk::MemoryPropertyFlags::HOST_VISIBLE, + preferred_flags: ash::vk::MemoryPropertyFlags::HOST_COHERENT + | ash::vk::MemoryPropertyFlags::HOST_CACHED, + flags: vk_mem::AllocationCreateFlags::MAPPED, + + ..Default::default() + }; unsafe { let memory_type_index = allocator .find_memory_type_index_for_buffer_info(&buffer_info, &allocation_info) @@ -237,11 +244,9 @@ fn create_gpu_buffer_pool() { .max_block_count(2); let pool = allocator.create_pool(&pool_info).unwrap(); - allocation_info = allocation_info.pool(&pool); - let (buffer, allocation, allocation_info) = allocator - .create_buffer(&buffer_info, &allocation_info) - .unwrap(); + let (buffer, allocation, allocation_info) = + pool.create_buffer(&buffer_info, &allocation_info).unwrap(); assert_ne!(allocation_info.get_mapped_data(), std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } @@ -251,7 +256,10 @@ fn create_gpu_buffer_pool() { fn test_gpu_stats() { let harness = TestHarness::new(); let allocator = harness.create_allocator(); - let allocation_info = vk_mem::AllocationCreateInfo::new().usage(vk_mem::MemoryUsage::Auto); + let allocation_info = vk_mem::AllocationCreateInfo { + usage: vk_mem::MemoryUsage::Auto, + ..Default::default() + }; unsafe { let stats_1 = allocator.calculate_statistics().unwrap(); From d0f6b02614bfc3f4b3a3ddc31250186596848e68 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Wed, 11 May 2022 23:47:34 -0700 Subject: [PATCH 13/23] Add create buffer with alignment --- src/lib.rs | 2 +- src/pool.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 1addd52..c68b11a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ mod definitions; mod defragmentation; -pub mod ffi; +mod ffi; mod pool; pub use definitions::*; pub use defragmentation::*; diff --git a/src/pool.rs b/src/pool.rs index 6b2d17f..0a03bf8 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -319,6 +319,35 @@ pub trait Alloc { Ok((buffer, allocation, allocation_info)) } + /// brief Creates a buffer with additional minimum alignment. + /// + /// Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom, + /// minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g. + /// for interop with OpenGL. + unsafe fn create_buffer_with_alignment( + &self, + buffer_info: &ash::vk::BufferCreateInfo, + create_info: &AllocationCreateInfo, + min_alignment: vk::DeviceSize, + ) -> VkResult<(ash::vk::Buffer, Allocation, AllocationInfo)> { + let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); + create_info.pool = self.pool().0; + let mut buffer = vk::Buffer::null(); + let mut allocation: Allocation = std::mem::zeroed(); + let mut allocation_info: AllocationInfo = std::mem::zeroed(); + ffi::vmaCreateBufferWithAlignment( + self.allocator().internal, + &*buffer_info, + &create_info, + min_alignment, + &mut buffer, + &mut allocation, + &mut allocation_info.internal, + ) + .result()?; + + Ok((buffer, allocation, allocation_info)) + } /// This function automatically creates an image, allocates appropriate memory /// for it, and binds the image with the memory. /// From 8ac0080bf61fc05114361e7d8c6721b815245d1f Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Thu, 12 May 2022 00:21:16 -0700 Subject: [PATCH 14/23] Added a few more methods --- build.rs | 1 + src/ffi.rs | 1 + src/lib.rs | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/pool.rs | 35 ++++++++++++++++- 4 files changed, 141 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index 64bf762..0b37982 100644 --- a/build.rs +++ b/build.rs @@ -124,6 +124,7 @@ fn generate_bindings(output_file: &str) { .blocklist_type("PFN_vk.*") .raw_line("#![allow(non_camel_case_types)]") .raw_line("#![allow(non_snake_case)]") + .raw_line("#![allow(dead_code)]") .raw_line("use ash::vk::*;") .trust_clang_mangling(false) .layout_tests(false) diff --git a/src/ffi.rs b/src/ffi.rs index 537534b..28eb1be 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -2,6 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] +#![allow(dead_code)] use ash::vk::*; #[repr(i32)] diff --git a/src/lib.rs b/src/lib.rs index c68b11a..3092afa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -461,12 +461,40 @@ impl Allocator { /// It is recommended to use function `Allocator::create_buffer` instead of this one. pub unsafe fn bind_buffer_memory( &self, - buffer: ash::vk::Buffer, allocation: Allocation, + buffer: ash::vk::Buffer, ) -> VkResult<()> { ffi::vmaBindBufferMemory(self.internal, allocation, buffer).result() } + /// Binds buffer to allocation with additional parameters. + /// + /// * `allocation` + /// * `allocation_local_offset` - Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. + /// * `buffer` + /// * `next` - A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null. + /// + /// This function is similar to vmaBindImageMemory(), but it provides additional parameters. + /// + /// If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag + /// or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. + pub unsafe fn bind_buffer_memory2( + &self, + allocation: Allocation, + allocation_local_offset: vk::DeviceSize, + buffer: ash::vk::Buffer, + next: *const ::std::os::raw::c_void, + ) -> VkResult<()> { + ffi::vmaBindBufferMemory2( + self.internal, + allocation, + allocation_local_offset, + buffer, + next, + ) + .result() + } + /// Binds image to allocation. /// /// Binds specified image to region of memory represented by specified allocation. @@ -482,12 +510,40 @@ impl Allocator { /// It is recommended to use function `Allocator::create_image` instead of this one. pub unsafe fn bind_image_memory( &self, - image: ash::vk::Image, allocation: Allocation, + image: ash::vk::Image, ) -> VkResult<()> { ffi::vmaBindImageMemory(self.internal, allocation, image).result() } + /// Binds image to allocation with additional parameters. + /// + /// * `allocation` + /// * `allocation_local_offset` - Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. + /// * `image` + /// * `next` - A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null. + /// + /// This function is similar to vmaBindImageMemory(), but it provides additional parameters. + /// + /// If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag + /// or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. + pub unsafe fn bind_image_memory2( + &self, + allocation: Allocation, + allocation_local_offset: vk::DeviceSize, + image: ash::vk::Image, + next: *const ::std::os::raw::c_void, + ) -> VkResult<()> { + ffi::vmaBindImageMemory2( + self.internal, + allocation, + allocation_local_offset, + image, + next, + ) + .result() + } + /// Destroys Vulkan buffer and frees allocated memory. /// /// This is just a convenience function equivalent to: @@ -515,6 +571,53 @@ impl Allocator { pub unsafe fn destroy_image(&self, image: ash::vk::Image, allocation: Allocation) { ffi::vmaDestroyImage(self.internal, image, allocation); } + /// Flushes memory of given set of allocations."] + /// + /// Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations."] + /// For more information, see documentation of vmaFlushAllocation()."] + /// + /// * `allocations` + /// * `offsets` - If not None, it must be a slice of offsets of regions to flush, relative to the beginning of respective allocations. None means all ofsets are zero. + /// * `sizes` - If not None, it must be a slice of sizes of regions to flush in respective allocations. None means `VK_WHOLE_SIZE` for all allocations. + pub unsafe fn flush_allocations( + &self, + allocations: &[Allocation], + offsets: Option<&[vk::DeviceSize]>, + sizes: Option<&[vk::DeviceSize]>, + ) -> VkResult<()> { + ffi::vmaFlushAllocations( + self.internal, + allocations.len() as u32, + allocations.as_ptr() as *mut _, + offsets.map_or(std::ptr::null(), |offsets| offsets.as_ptr()), + sizes.map_or(std::ptr::null(), |sizes| sizes.as_ptr()), + ) + .result() + } + + /// Invalidates memory of given set of allocations."] + /// + /// Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations."] + /// For more information, see documentation of vmaInvalidateAllocation()."] + /// + /// * `allocations` + /// * `offsets` - If not None, it must be a slice of offsets of regions to flush, relative to the beginning of respective allocations. None means all ofsets are zero. + /// * `sizes` - If not None, it must be a slice of sizes of regions to flush in respective allocations. None means `VK_WHOLE_SIZE` for all allocations. + pub unsafe fn invalidate_allocations( + &self, + allocations: &[Allocation], + offsets: Option<&[vk::DeviceSize]>, + sizes: Option<&[vk::DeviceSize]>, + ) -> VkResult<()> { + ffi::vmaInvalidateAllocations( + self.internal, + allocations.len() as u32, + allocations.as_ptr() as *mut _, + offsets.map_or(std::ptr::null(), |offsets| offsets.as_ptr()), + sizes.map_or(std::ptr::null(), |sizes| sizes.as_ptr()), + ) + .result() + } } /// Custom `Drop` implementation to clean up internal allocation instance diff --git a/src/pool.rs b/src/pool.rs index 0a03bf8..acf03b5 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -1,3 +1,4 @@ +use std::ffi::CStr; use std::sync::Arc; use crate::ffi; @@ -31,6 +32,13 @@ impl Allocator { }) } } + + pub fn default_pool(self: &Arc) -> AllocatorPool { + AllocatorPool { + pool: PoolHandle(std::ptr::null_mut()), + allocator: self.clone(), + } + } } impl Drop for AllocatorPool { @@ -42,6 +50,31 @@ impl Drop for AllocatorPool { } impl AllocatorPool { + pub fn set_name(&self, name: Option<&CStr>) { + if self.pool.0.is_null() { + return; + } + unsafe { + ffi::vmaSetPoolName( + self.allocator.internal, + self.pool.0, + name.map_or(std::ptr::null(), CStr::as_ptr), + ); + } + } + pub fn name(&self) -> Option<&CStr> { + if self.pool.0.is_null() { + return None; + } + let mut ptr: *const ::std::os::raw::c_char = std::ptr::null(); + unsafe { + ffi::vmaGetPoolName(self.allocator.internal, self.pool.0, &mut ptr); + if ptr.is_null() { + return None; + } + Some(CStr::from_ptr(ptr)) + } + } /// Retrieves statistics of existing `AllocatorPool` object. pub fn get_statistics(&self) -> VkResult { unsafe { @@ -320,7 +353,7 @@ pub trait Alloc { Ok((buffer, allocation, allocation_info)) } /// brief Creates a buffer with additional minimum alignment. - /// + /// /// Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom, /// minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g. /// for interop with OpenGL. From bc0541832f54bfd8573c81f71c8f26531b20747e Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Thu, 12 May 2022 00:38:29 -0700 Subject: [PATCH 15/23] More refactors --- src/definitions.rs | 75 ++++++++++++++++++++++++++++ src/lib.rs | 118 ++++++--------------------------------------- src/pool.rs | 50 +++++++++---------- tests/mod.rs | 6 +-- 4 files changed, 119 insertions(+), 130 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index ae21326..a26f467 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -3,6 +3,7 @@ use ash::vk; use ash::vk::PhysicalDevice; use ash::{Device, Instance}; use bitflags::bitflags; +use std::ffi::CStr; use std::ptr; /// Intended usage of memory. @@ -610,3 +611,77 @@ impl From<&AllocationCreateInfo> for ffi::VmaAllocationCreateInfo { } } } + +/// Parameters of `Allocation` objects, that can be retrieved using `Allocator::get_allocation_info`. +#[derive(Debug, Clone)] +pub struct AllocationInfo<'a> { + /// Memory type index that this allocation was allocated from. It never changes. + pub memory_type: u32, + /// Handle to Vulkan memory object. + /// + /// Same memory object can be shared by multiple allocations. + /// + /// It can change after the allocation is moved during \\ref defragmentation. + pub device_memory: vk::DeviceMemory, + /// Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation. + /// + /// You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function + /// vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image, + /// not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation + /// and apply this offset automatically. + /// + /// It can change after the allocation is moved during \\ref defragmentation. + pub offset: vk::DeviceSize, + /// Size of this allocation, in bytes. It never changes. + /// + /// Allocation size returned in this variable may be greater than the size + /// requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the + /// allocation is accessible for operations on memory e.g. using a pointer after + /// mapping with vmaMapMemory(), but operations on the resource e.g. using + /// `vkCmdCopyBuffer` must be limited to the size of the resource. + pub size: vk::DeviceSize, + /// Pointer to the beginning of this allocation as mapped data. + /// + /// If the allocation hasn't been mapped using vmaMapMemory() and hasn't been + /// created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null. + /// + /// It can change after call to vmaMapMemory(), vmaUnmapMemory(). + /// It can also change after the allocation is moved during defragmentation. + pub mapped_data: *mut ::std::os::raw::c_void, + /// Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData(). + /// + /// It can change after call to vmaSetAllocationUserData() for this allocation. + pub user_data: usize, + /// Custom allocation name that was set with vmaSetAllocationName(). + /// + /// It can change after call to vmaSetAllocationName() for this allocation. + /// + /// Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with + /// additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. + pub name: Option<&'a CStr>, +} + +impl<'a> From<&ffi::VmaAllocationInfo> for AllocationInfo<'a> { + fn from(info: &ffi::VmaAllocationInfo) -> Self { + Self { + memory_type: info.memoryType, + device_memory: info.deviceMemory, + offset: info.offset, + size: info.size, + mapped_data: info.pMappedData, + user_data: info.pUserData as _, + name: unsafe { + if info.pName.is_null() { + None + } else { + Some(CStr::from_ptr(info.pName)) + } + }, + } + } +} +impl<'a> From for AllocationInfo<'a> { + fn from(info: ffi::VmaAllocationInfo) -> Self { + (&info).into() + } +} diff --git a/src/lib.rs b/src/lib.rs index 3092afa..e3e1811 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,93 +38,7 @@ unsafe impl Sync for Allocator {} /// use `Allocator::get_allocation_info`. /// /// Some kinds allocations can be in lost state. -pub type Allocation = ffi::VmaAllocation; - -/// Parameters of `Allocation` objects, that can be retrieved using `Allocator::get_allocation_info`. -#[derive(Debug, Clone)] -pub struct AllocationInfo { - /// Pointer to internal VmaAllocationInfo instance - internal: ffi::VmaAllocationInfo, -} - -unsafe impl Send for AllocationInfo {} -unsafe impl Sync for AllocationInfo {} - -impl AllocationInfo { - #[inline(always)] - // Gets the memory type index that this allocation was allocated from. (Never changes) - pub fn get_memory_type(&self) -> u32 { - self.internal.memoryType - } - - /// Handle to Vulkan memory object. - /// - /// Same memory object can be shared by multiple allocations. - /// - /// It can change after call to `Allocator::defragment` if this allocation is passed - /// to the function, or if allocation is lost. - /// - /// If the allocation is lost, it is equal to `ash::vk::DeviceMemory::null()`. - #[inline(always)] - pub fn get_device_memory(&self) -> ash::vk::DeviceMemory { - self.internal.deviceMemory - } - - /// Offset into device memory object to the beginning of this allocation, in bytes. - /// (`self.get_device_memory()`, `self.get_offset()`) pair is unique to this allocation. - /// - /// It can change after call to `Allocator::defragment` if this allocation is passed - /// to the function, or if allocation is lost. - #[inline(always)] - pub fn get_offset(&self) -> usize { - self.internal.offset as usize - } - - /// Size of this allocation, in bytes. - /// - /// It never changes, unless allocation is lost. - #[inline(always)] - pub fn get_size(&self) -> usize { - self.internal.size as usize - } - - /// Pointer to the beginning of this allocation as mapped data. - /// - /// If the allocation hasn't been mapped using `Allocator::map_memory` and hasn't been - /// created with `AllocationCreateFlags::MAPPED` flag, this value is null. - /// - /// It can change after call to `Allocator::map_memory`, `Allocator::unmap_memory`. - /// It can also change after call to `Allocator::defragment` if this allocation is - /// passed to the function. - #[inline(always)] - pub fn get_mapped_data(&self) -> *mut u8 { - self.internal.pMappedData as *mut u8 - } - - /*#[inline(always)] - pub fn get_mapped_slice(&self) -> Option<&mut &[u8]> { - if self.internal.pMappedData.is_null() { - None - } else { - Some(unsafe { &mut ::std::slice::from_raw_parts(self.internal.pMappedData as *mut u8, self.get_size()) }) - } - }*/ - - /// Custom general-purpose pointer that was passed as `AllocationCreateInfo::user_data` or set using `Allocator::set_allocation_user_data`. - /// - /// It can change after a call to `Allocator::set_allocation_user_data` for this allocation. - #[inline(always)] - pub fn get_user_data(&self) -> *mut ::std::os::raw::c_void { - self.internal.pUserData - } -} - -/// Construct `AllocatorCreateFlags` with default values -impl Default for AllocatorCreateFlags { - fn default() -> Self { - AllocatorCreateFlags::NONE - } -} +pub struct Allocation(ffi::VmaAllocation); impl Allocator { /// Constructor a new `Allocator` using the provided options. @@ -273,7 +187,7 @@ impl Allocator { /// Frees memory previously allocated using `Allocator::allocate_memory`, /// `Allocator::allocate_memory_for_buffer`, or `Allocator::allocate_memory_for_image`. pub unsafe fn free_memory(&self, allocation: Allocation) { - ffi::vmaFreeMemory(self.internal, allocation); + ffi::vmaFreeMemory(self.internal, allocation.0); } /// Frees memory and destroys multiple allocations. @@ -307,9 +221,9 @@ impl Allocator { /// /// If you just want to check if allocation is not lost, `Allocator::touch_allocation` will work faster. pub unsafe fn get_allocation_info(&self, allocation: Allocation) -> VkResult { - let mut allocation_info: AllocationInfo = mem::zeroed(); - ffi::vmaGetAllocationInfo(self.internal, allocation, &mut allocation_info.internal); - Ok(allocation_info) + let mut allocation_info: ffi::VmaAllocationInfo = mem::zeroed(); + ffi::vmaGetAllocationInfo(self.internal, allocation.0, &mut allocation_info); + Ok(allocation_info.into()) } /// Sets user data in given allocation to new value. @@ -329,7 +243,7 @@ impl Allocator { allocation: Allocation, user_data: *mut ::std::os::raw::c_void, ) { - ffi::vmaSetAllocationUserData(self.internal, allocation, user_data); + ffi::vmaSetAllocationUserData(self.internal, allocation.0, user_data); } /// Maps memory represented by given allocation and returns pointer to it. @@ -368,14 +282,14 @@ impl Allocator { /// `AllocationCreateFlags::CAN_BECOME_LOST` flag. Such allocations cannot be mapped. pub unsafe fn map_memory(&self, allocation: Allocation) -> VkResult<*mut u8> { let mut mapped_data: *mut ::std::os::raw::c_void = ::std::ptr::null_mut(); - ffi::vmaMapMemory(self.internal, allocation, &mut mapped_data).result()?; + ffi::vmaMapMemory(self.internal, allocation.0, &mut mapped_data).result()?; Ok(mapped_data as *mut u8) } /// Unmaps memory represented by given allocation, mapped previously using `Allocator::map_memory`. pub unsafe fn unmap_memory(&self, allocation: Allocation) { - ffi::vmaUnmapMemory(self.internal, allocation); + ffi::vmaUnmapMemory(self.internal, allocation.0); } /// Flushes memory of given allocation. @@ -395,7 +309,7 @@ impl Allocator { ) -> VkResult<()> { ffi::vmaFlushAllocation( self.internal, - allocation, + allocation.0, offset as vk::DeviceSize, size as vk::DeviceSize, ) @@ -419,7 +333,7 @@ impl Allocator { ) -> VkResult<()> { ffi::vmaInvalidateAllocation( self.internal, - allocation, + allocation.0, offset as vk::DeviceSize, size as vk::DeviceSize, ) @@ -464,7 +378,7 @@ impl Allocator { allocation: Allocation, buffer: ash::vk::Buffer, ) -> VkResult<()> { - ffi::vmaBindBufferMemory(self.internal, allocation, buffer).result() + ffi::vmaBindBufferMemory(self.internal, allocation.0, buffer).result() } /// Binds buffer to allocation with additional parameters. @@ -487,7 +401,7 @@ impl Allocator { ) -> VkResult<()> { ffi::vmaBindBufferMemory2( self.internal, - allocation, + allocation.0, allocation_local_offset, buffer, next, @@ -513,7 +427,7 @@ impl Allocator { allocation: Allocation, image: ash::vk::Image, ) -> VkResult<()> { - ffi::vmaBindImageMemory(self.internal, allocation, image).result() + ffi::vmaBindImageMemory(self.internal, allocation.0, image).result() } /// Binds image to allocation with additional parameters. @@ -536,7 +450,7 @@ impl Allocator { ) -> VkResult<()> { ffi::vmaBindImageMemory2( self.internal, - allocation, + allocation.0, allocation_local_offset, image, next, @@ -555,7 +469,7 @@ impl Allocator { /// /// It it safe to pass null as `buffer` and/or `allocation`. pub unsafe fn destroy_buffer(&self, buffer: ash::vk::Buffer, allocation: Allocation) { - ffi::vmaDestroyBuffer(self.internal, buffer, allocation); + ffi::vmaDestroyBuffer(self.internal, buffer, allocation.0); } /// Destroys Vulkan image and frees allocated memory. @@ -569,7 +483,7 @@ impl Allocator { /// /// It it safe to pass null as `image` and/or `allocation`. pub unsafe fn destroy_image(&self, image: ash::vk::Image, allocation: Allocation) { - ffi::vmaDestroyImage(self.internal, image, allocation); + ffi::vmaDestroyImage(self.internal, image, allocation.0); } /// Flushes memory of given set of allocations."] /// diff --git a/src/pool.rs b/src/pool.rs index acf03b5..b325ce3 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -217,18 +217,18 @@ pub trait Alloc { ) -> VkResult<(Allocation, AllocationInfo)> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; - let mut allocation: Allocation = std::mem::zeroed(); - let mut allocation_info: AllocationInfo = std::mem::zeroed(); + let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); + let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaAllocateMemory( self.allocator().internal, memory_requirements, &create_info, &mut allocation, - &mut allocation_info.internal, + &mut allocation_info, ) .result()?; - Ok((allocation, allocation_info)) + Ok((Allocation(allocation), allocation_info.into())) } /// General purpose memory allocation for multiple allocation objects at once. @@ -263,7 +263,7 @@ pub trait Alloc { let it = allocations.iter().zip(allocation_info.iter()); let allocations: Vec<(Allocation, AllocationInfo)> = it - .map(|(alloc, info)| (*alloc, AllocationInfo { internal: *info })) + .map(|(alloc, info)| (Allocation(*alloc), info.into())) .collect(); Ok(allocations) @@ -279,18 +279,18 @@ pub trait Alloc { ) -> VkResult<(Allocation, AllocationInfo)> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; - let mut allocation: Allocation = std::mem::zeroed(); - let mut allocation_info: AllocationInfo = std::mem::zeroed(); + let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); + let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaAllocateMemoryForBuffer( self.allocator().internal, buffer, &create_info, &mut allocation, - &mut allocation_info.internal, + &mut allocation_info, ) .result()?; - Ok((allocation, allocation_info)) + Ok((Allocation(allocation), allocation_info.into())) } /// Image specialized memory allocation. @@ -303,18 +303,18 @@ pub trait Alloc { ) -> VkResult<(Allocation, AllocationInfo)> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; - let mut allocation: Allocation = std::mem::zeroed(); - let mut allocation_info: AllocationInfo = std::mem::zeroed(); + let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); + let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaAllocateMemoryForImage( self.allocator().internal, image, &create_info, &mut allocation, - &mut allocation_info.internal, + &mut allocation_info, ) .result()?; - Ok((allocation, allocation_info)) + Ok((Allocation(allocation), allocation_info.into())) } /// This function automatically creates a buffer, allocates appropriate memory @@ -338,19 +338,19 @@ pub trait Alloc { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut buffer = vk::Buffer::null(); - let mut allocation: Allocation = std::mem::zeroed(); - let mut allocation_info: AllocationInfo = std::mem::zeroed(); + let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); + let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaCreateBuffer( self.allocator().internal, &*buffer_info, &create_info, &mut buffer, &mut allocation, - &mut allocation_info.internal, + &mut allocation_info, ) .result()?; - Ok((buffer, allocation, allocation_info)) + Ok((buffer, Allocation(allocation), allocation_info.into())) } /// brief Creates a buffer with additional minimum alignment. /// @@ -366,8 +366,8 @@ pub trait Alloc { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut buffer = vk::Buffer::null(); - let mut allocation: Allocation = std::mem::zeroed(); - let mut allocation_info: AllocationInfo = std::mem::zeroed(); + let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); + let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaCreateBufferWithAlignment( self.allocator().internal, &*buffer_info, @@ -375,11 +375,11 @@ pub trait Alloc { min_alignment, &mut buffer, &mut allocation, - &mut allocation_info.internal, + &mut allocation_info, ) .result()?; - Ok((buffer, allocation, allocation_info)) + Ok((buffer, Allocation(allocation), allocation_info.into())) } /// This function automatically creates an image, allocates appropriate memory /// for it, and binds the image with the memory. @@ -406,19 +406,19 @@ pub trait Alloc { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut image = vk::Image::null(); - let mut allocation: Allocation = std::mem::zeroed(); - let mut allocation_info: AllocationInfo = std::mem::zeroed(); + let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); + let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaCreateImage( self.allocator().internal, &*image_info, &create_info, &mut image, &mut allocation, - &mut allocation_info.internal, + &mut allocation_info, ) .result()?; - Ok((image, allocation, allocation_info)) + Ok((image, Allocation(allocation), allocation_info.into())) } } diff --git a/tests/mod.rs b/tests/mod.rs index 066ea87..f2d5e5e 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -179,7 +179,7 @@ fn create_gpu_buffer() { &allocation_info, ) .unwrap(); - assert_eq!(allocation_info.get_mapped_data(), std::ptr::null_mut()); + assert_eq!(allocation_info.mapped_data, std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } } @@ -208,7 +208,7 @@ fn create_cpu_buffer_preferred() { &allocation_info, ) .unwrap(); - assert_ne!(allocation_info.get_mapped_data(), std::ptr::null_mut()); + assert_ne!(allocation_info.mapped_data, std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } } @@ -247,7 +247,7 @@ fn create_gpu_buffer_pool() { let (buffer, allocation, allocation_info) = pool.create_buffer(&buffer_info, &allocation_info).unwrap(); - assert_ne!(allocation_info.get_mapped_data(), std::ptr::null_mut()); + assert_ne!(allocation_info.mapped_data, std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } } From bc394b14e60ce5b5cf5f0b81bb6fdef51cd3e01c Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Thu, 12 May 2022 00:55:54 -0700 Subject: [PATCH 16/23] Implement Send for allocation --- src/definitions.rs | 21 +++------------------ src/lib.rs | 1 + 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index a26f467..cda3cc1 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -3,7 +3,6 @@ use ash::vk; use ash::vk::PhysicalDevice; use ash::{Device, Instance}; use bitflags::bitflags; -use std::ffi::CStr; use std::ptr; /// Intended usage of memory. @@ -614,7 +613,7 @@ impl From<&AllocationCreateInfo> for ffi::VmaAllocationCreateInfo { /// Parameters of `Allocation` objects, that can be retrieved using `Allocator::get_allocation_info`. #[derive(Debug, Clone)] -pub struct AllocationInfo<'a> { +pub struct AllocationInfo { /// Memory type index that this allocation was allocated from. It never changes. pub memory_type: u32, /// Handle to Vulkan memory object. @@ -652,16 +651,9 @@ pub struct AllocationInfo<'a> { /// /// It can change after call to vmaSetAllocationUserData() for this allocation. pub user_data: usize, - /// Custom allocation name that was set with vmaSetAllocationName(). - /// - /// It can change after call to vmaSetAllocationName() for this allocation. - /// - /// Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with - /// additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. - pub name: Option<&'a CStr>, } -impl<'a> From<&ffi::VmaAllocationInfo> for AllocationInfo<'a> { +impl From<&ffi::VmaAllocationInfo> for AllocationInfo { fn from(info: &ffi::VmaAllocationInfo) -> Self { Self { memory_type: info.memoryType, @@ -670,17 +662,10 @@ impl<'a> From<&ffi::VmaAllocationInfo> for AllocationInfo<'a> { size: info.size, mapped_data: info.pMappedData, user_data: info.pUserData as _, - name: unsafe { - if info.pName.is_null() { - None - } else { - Some(CStr::from_ptr(info.pName)) - } - }, } } } -impl<'a> From for AllocationInfo<'a> { +impl From for AllocationInfo { fn from(info: ffi::VmaAllocationInfo) -> Self { (&info).into() } diff --git a/src/lib.rs b/src/lib.rs index e3e1811..a9233de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ unsafe impl Sync for Allocator {} /// /// Some kinds allocations can be in lost state. pub struct Allocation(ffi::VmaAllocation); +unsafe impl Send for Allocation{} impl Allocator { /// Constructor a new `Allocator` using the provided options. From bbf5bb371ae8fde01ab96d7deb4802cc2d3f0ac9 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Thu, 12 May 2022 03:00:51 -0700 Subject: [PATCH 17/23] Pass Allocation by reference --- src/definitions.rs | 2 +- src/lib.rs | 69 +++++++++++++++++++++++++--------------------- src/pool.rs | 52 +++++++++++++++------------------- tests/mod.rs | 12 ++++---- 4 files changed, 68 insertions(+), 67 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index cda3cc1..7bde40c 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -84,7 +84,7 @@ pub enum MemoryUsage { /// and not with generic memory allocation functions. Auto, - /// Selects best memory type automatically with preference for CPU (host) memory. + /// Selects best memory type automatically with preference for GPU (device) memory. /// /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT diff --git a/src/lib.rs b/src/lib.rs index a9233de..648f5ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,8 @@ unsafe impl Sync for Allocator {} /// /// Some kinds allocations can be in lost state. pub struct Allocation(ffi::VmaAllocation); -unsafe impl Send for Allocation{} +unsafe impl Send for Allocation {} +unsafe impl Sync for Allocation {} impl Allocator { /// Constructor a new `Allocator` using the provided options. @@ -221,7 +222,7 @@ impl Allocator { /// you can avoid calling it too often. /// /// If you just want to check if allocation is not lost, `Allocator::touch_allocation` will work faster. - pub unsafe fn get_allocation_info(&self, allocation: Allocation) -> VkResult { + pub unsafe fn get_allocation_info(&self, allocation: &Allocation) -> VkResult { let mut allocation_info: ffi::VmaAllocationInfo = mem::zeroed(); ffi::vmaGetAllocationInfo(self.internal, allocation.0, &mut allocation_info); Ok(allocation_info.into()) @@ -241,7 +242,7 @@ impl Allocator { /// as a pointer, ordinal number or some handle to you own data. pub unsafe fn set_allocation_user_data( &self, - allocation: Allocation, + allocation: &mut Allocation, user_data: *mut ::std::os::raw::c_void, ) { ffi::vmaSetAllocationUserData(self.internal, allocation.0, user_data); @@ -281,7 +282,7 @@ impl Allocator { /// /// This function always fails when called for allocation that was created with /// `AllocationCreateFlags::CAN_BECOME_LOST` flag. Such allocations cannot be mapped. - pub unsafe fn map_memory(&self, allocation: Allocation) -> VkResult<*mut u8> { + pub unsafe fn map_memory(&self, allocation: &mut Allocation) -> VkResult<*mut u8> { let mut mapped_data: *mut ::std::os::raw::c_void = ::std::ptr::null_mut(); ffi::vmaMapMemory(self.internal, allocation.0, &mut mapped_data).result()?; @@ -289,7 +290,7 @@ impl Allocator { } /// Unmaps memory represented by given allocation, mapped previously using `Allocator::map_memory`. - pub unsafe fn unmap_memory(&self, allocation: Allocation) { + pub unsafe fn unmap_memory(&self, allocation: &mut Allocation) { ffi::vmaUnmapMemory(self.internal, allocation.0); } @@ -302,19 +303,21 @@ impl Allocator { /// - `offset` and `size` don't have to be aligned; hey are internally rounded down/up to multiple of `nonCoherentAtomSize`. /// - If `size` is 0, this call is ignored. /// - If memory type that the `allocation` belongs to is not `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` or it is `ash::vk::MemoryPropertyFlags::HOST_COHERENT`, this call is ignored. - pub unsafe fn flush_allocation( + pub fn flush_allocation( &self, - allocation: Allocation, + allocation: &Allocation, offset: usize, size: usize, ) -> VkResult<()> { - ffi::vmaFlushAllocation( - self.internal, - allocation.0, - offset as vk::DeviceSize, - size as vk::DeviceSize, - ) - .result() + unsafe { + ffi::vmaFlushAllocation( + self.internal, + allocation.0, + offset as vk::DeviceSize, + size as vk::DeviceSize, + ) + .result() + } } /// Invalidates memory of given allocation. @@ -326,19 +329,21 @@ impl Allocator { /// - `offset` and `size` don't have to be aligned. They are internally rounded down/up to multiple of `nonCoherentAtomSize`. /// - If `size` is 0, this call is ignored. /// - If memory type that the `allocation` belongs to is not `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` or it is `ash::vk::MemoryPropertyFlags::HOST_COHERENT`, this call is ignored. - pub unsafe fn invalidate_allocation( + pub fn invalidate_allocation( &self, - allocation: Allocation, + allocation: &Allocation, offset: usize, size: usize, ) -> VkResult<()> { - ffi::vmaInvalidateAllocation( - self.internal, - allocation.0, - offset as vk::DeviceSize, - size as vk::DeviceSize, - ) - .result() + unsafe { + ffi::vmaInvalidateAllocation( + self.internal, + allocation.0, + offset as vk::DeviceSize, + size as vk::DeviceSize, + ) + .result() + } } /// Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. @@ -376,7 +381,7 @@ impl Allocator { /// It is recommended to use function `Allocator::create_buffer` instead of this one. pub unsafe fn bind_buffer_memory( &self, - allocation: Allocation, + allocation: &Allocation, buffer: ash::vk::Buffer, ) -> VkResult<()> { ffi::vmaBindBufferMemory(self.internal, allocation.0, buffer).result() @@ -395,7 +400,7 @@ impl Allocator { /// or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. pub unsafe fn bind_buffer_memory2( &self, - allocation: Allocation, + allocation: &Allocation, allocation_local_offset: vk::DeviceSize, buffer: ash::vk::Buffer, next: *const ::std::os::raw::c_void, @@ -425,7 +430,7 @@ impl Allocator { /// It is recommended to use function `Allocator::create_image` instead of this one. pub unsafe fn bind_image_memory( &self, - allocation: Allocation, + allocation: &Allocation, image: ash::vk::Image, ) -> VkResult<()> { ffi::vmaBindImageMemory(self.internal, allocation.0, image).result() @@ -444,7 +449,7 @@ impl Allocator { /// or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. pub unsafe fn bind_image_memory2( &self, - allocation: Allocation, + allocation: &Allocation, allocation_local_offset: vk::DeviceSize, image: ash::vk::Image, next: *const ::std::os::raw::c_void, @@ -494,12 +499,13 @@ impl Allocator { /// * `allocations` /// * `offsets` - If not None, it must be a slice of offsets of regions to flush, relative to the beginning of respective allocations. None means all ofsets are zero. /// * `sizes` - If not None, it must be a slice of sizes of regions to flush in respective allocations. None means `VK_WHOLE_SIZE` for all allocations. - pub unsafe fn flush_allocations( + pub unsafe fn flush_allocations<'a>( &self, - allocations: &[Allocation], + allocations: impl IntoIterator, offsets: Option<&[vk::DeviceSize]>, sizes: Option<&[vk::DeviceSize]>, ) -> VkResult<()> { + let allocations: Vec = allocations.into_iter().map(|a| a.0).collect(); ffi::vmaFlushAllocations( self.internal, allocations.len() as u32, @@ -518,12 +524,13 @@ impl Allocator { /// * `allocations` /// * `offsets` - If not None, it must be a slice of offsets of regions to flush, relative to the beginning of respective allocations. None means all ofsets are zero. /// * `sizes` - If not None, it must be a slice of sizes of regions to flush in respective allocations. None means `VK_WHOLE_SIZE` for all allocations. - pub unsafe fn invalidate_allocations( + pub unsafe fn invalidate_allocations<'a>( &self, - allocations: &[Allocation], + allocations: impl IntoIterator, offsets: Option<&[vk::DeviceSize]>, sizes: Option<&[vk::DeviceSize]>, ) -> VkResult<()> { + let allocations: Vec = allocations.into_iter().map(|a| a.0).collect(); ffi::vmaInvalidateAllocations( self.internal, allocations.len() as u32, diff --git a/src/pool.rs b/src/pool.rs index b325ce3..a3b6cce 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use crate::ffi; use crate::Allocation; use crate::AllocationCreateInfo; -use crate::AllocationInfo; use crate::Allocator; use crate::PoolCreateInfo; use ash::prelude::VkResult; @@ -214,21 +213,20 @@ pub trait Alloc { &self, memory_requirements: &ash::vk::MemoryRequirements, create_info: &AllocationCreateInfo, - ) -> VkResult<(Allocation, AllocationInfo)> { + ) -> VkResult { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); - let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaAllocateMemory( self.allocator().internal, memory_requirements, &create_info, &mut allocation, - &mut allocation_info, + std::ptr::null_mut(), ) .result()?; - Ok((Allocation(allocation), allocation_info.into())) + Ok(Allocation(allocation)) } /// General purpose memory allocation for multiple allocation objects at once. @@ -245,25 +243,23 @@ pub trait Alloc { memory_requirements: &ash::vk::MemoryRequirements, create_info: &AllocationCreateInfo, allocation_count: usize, - ) -> VkResult> { + ) -> VkResult> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut allocations: Vec = vec![std::mem::zeroed(); allocation_count]; - let mut allocation_info: Vec = - vec![std::mem::zeroed(); allocation_count]; ffi::vmaAllocateMemoryPages( self.allocator().internal, memory_requirements, &create_info, allocation_count, allocations.as_mut_ptr(), - allocation_info.as_mut_ptr(), + std::ptr::null_mut(), ) .result()?; - let it = allocations.iter().zip(allocation_info.iter()); - let allocations: Vec<(Allocation, AllocationInfo)> = it - .map(|(alloc, info)| (Allocation(*alloc), info.into())) + let allocations: Vec = allocations + .into_iter() + .map(|alloc| Allocation(alloc)) .collect(); Ok(allocations) @@ -276,7 +272,7 @@ pub trait Alloc { &self, buffer: ash::vk::Buffer, create_info: &AllocationCreateInfo, - ) -> VkResult<(Allocation, AllocationInfo)> { + ) -> VkResult { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); @@ -290,7 +286,7 @@ pub trait Alloc { ) .result()?; - Ok((Allocation(allocation), allocation_info.into())) + Ok(Allocation(allocation)) } /// Image specialized memory allocation. @@ -300,21 +296,20 @@ pub trait Alloc { &self, image: ash::vk::Image, create_info: &AllocationCreateInfo, - ) -> VkResult<(Allocation, AllocationInfo)> { + ) -> VkResult { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); - let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaAllocateMemoryForImage( self.allocator().internal, image, &create_info, &mut allocation, - &mut allocation_info, + std::ptr::null_mut(), ) .result()?; - Ok((Allocation(allocation), allocation_info.into())) + Ok(Allocation(allocation)) } /// This function automatically creates a buffer, allocates appropriate memory @@ -334,23 +329,22 @@ pub trait Alloc { &self, buffer_info: &ash::vk::BufferCreateInfo, create_info: &AllocationCreateInfo, - ) -> VkResult<(ash::vk::Buffer, Allocation, AllocationInfo)> { + ) -> VkResult<(ash::vk::Buffer, Allocation)> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut buffer = vk::Buffer::null(); let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); - let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaCreateBuffer( self.allocator().internal, &*buffer_info, &create_info, &mut buffer, &mut allocation, - &mut allocation_info, + std::ptr::null_mut(), ) .result()?; - Ok((buffer, Allocation(allocation), allocation_info.into())) + Ok((buffer, Allocation(allocation))) } /// brief Creates a buffer with additional minimum alignment. /// @@ -362,12 +356,11 @@ pub trait Alloc { buffer_info: &ash::vk::BufferCreateInfo, create_info: &AllocationCreateInfo, min_alignment: vk::DeviceSize, - ) -> VkResult<(ash::vk::Buffer, Allocation, AllocationInfo)> { + ) -> VkResult<(ash::vk::Buffer, Allocation)> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut buffer = vk::Buffer::null(); let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); - let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaCreateBufferWithAlignment( self.allocator().internal, &*buffer_info, @@ -375,11 +368,11 @@ pub trait Alloc { min_alignment, &mut buffer, &mut allocation, - &mut allocation_info, + std::ptr::null_mut(), ) .result()?; - Ok((buffer, Allocation(allocation), allocation_info.into())) + Ok((buffer, Allocation(allocation))) } /// This function automatically creates an image, allocates appropriate memory /// for it, and binds the image with the memory. @@ -402,23 +395,22 @@ pub trait Alloc { &self, image_info: &ash::vk::ImageCreateInfo, create_info: &AllocationCreateInfo, - ) -> VkResult<(ash::vk::Image, Allocation, AllocationInfo)> { + ) -> VkResult<(ash::vk::Image, Allocation)> { let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into(); create_info.pool = self.pool().0; let mut image = vk::Image::null(); let mut allocation: ffi::VmaAllocation = std::mem::zeroed(); - let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed(); ffi::vmaCreateImage( self.allocator().internal, &*image_info, &create_info, &mut image, &mut allocation, - &mut allocation_info, + std::ptr::null_mut(), ) .result()?; - Ok((image, Allocation(allocation), allocation_info.into())) + Ok((image, Allocation(allocation))) } } diff --git a/tests/mod.rs b/tests/mod.rs index f2d5e5e..6a74656 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -167,7 +167,7 @@ fn create_gpu_buffer() { }; unsafe { - let (buffer, allocation, allocation_info) = allocator + let (buffer, allocation) = allocator .create_buffer( &ash::vk::BufferCreateInfo::builder() .size(16 * 1024) @@ -179,6 +179,7 @@ fn create_gpu_buffer() { &allocation_info, ) .unwrap(); + let allocation_info = allocator.get_allocation_info(&allocation).unwrap(); assert_eq!(allocation_info.mapped_data, std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } @@ -196,7 +197,7 @@ fn create_cpu_buffer_preferred() { ..Default::default() }; unsafe { - let (buffer, allocation, allocation_info) = allocator + let (buffer, allocation) = allocator .create_buffer( &ash::vk::BufferCreateInfo::builder() .size(16 * 1024) @@ -208,6 +209,7 @@ fn create_cpu_buffer_preferred() { &allocation_info, ) .unwrap(); + let allocation_info = allocator.get_allocation_info(&allocation).unwrap(); assert_ne!(allocation_info.mapped_data, std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } @@ -245,8 +247,8 @@ fn create_gpu_buffer_pool() { let pool = allocator.create_pool(&pool_info).unwrap(); - let (buffer, allocation, allocation_info) = - pool.create_buffer(&buffer_info, &allocation_info).unwrap(); + let (buffer, allocation) = pool.create_buffer(&buffer_info, &allocation_info).unwrap(); + let allocation_info = allocator.get_allocation_info(&allocation).unwrap(); assert_ne!(allocation_info.mapped_data, std::ptr::null_mut()); allocator.destroy_buffer(buffer, allocation); } @@ -267,7 +269,7 @@ fn test_gpu_stats() { assert_eq!(stats_1.total.statistics.allocationCount, 0); assert_eq!(stats_1.total.statistics.allocationBytes, 0); - let (buffer, allocation, _allocation_info) = allocator + let (buffer, allocation) = allocator .create_buffer( &ash::vk::BufferCreateInfo::builder() .size(16 * 1024) From 9f63215fde428be22a06766af8afc02700b130f4 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Fri, 13 May 2022 22:52:47 -0700 Subject: [PATCH 18/23] Use own fork --- .gitmodules | 2 +- src/definitions.rs | 5 +++++ src/ffi.rs | 7 ++++++- vendor/VulkanMemoryAllocator | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index c31bc35..543741b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "vendor/VulkanMemoryAllocator"] path = vendor/VulkanMemoryAllocator - url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git + url = https://github.com/dust-engine/VulkanMemoryAllocator.git [submodule "vendor/Vulkan-Headers"] path = vendor/Vulkan-Headers url = https://github.com/KhronosGroup/Vulkan-Headers diff --git a/src/definitions.rs b/src/definitions.rs index 7bde40c..cbd1e6a 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -540,6 +540,11 @@ pub struct AllocationCreateInfo { /// Set to 0 if no additional flags are preferred. /// If `pool` is not null, this member is ignored. pub preferred_flags: vk::MemoryPropertyFlags, + /// Flags that preferably should be not set in a memory type chosen for an allocation."] + /// + /// Set to 0 if no additional flags are undesired. + /// If `pool` is not null, this member is ignored. + pub not_preferred_flags: vk::MemoryPropertyFlags, /// Bitmask containing one bit set for every memory type acceptable for this allocation. /// /// Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if diff --git a/src/ffi.rs b/src/ffi.rs index 28eb1be..baaee43 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -531,7 +531,7 @@ pub struct VmaVulkanFunctions { pub vkCmdCopyBuffer: PFN_vkCmdCopyBuffer, #[doc = " Fetch \"vkGetBufferMemoryRequirements2\" on Vulkan >= 1.1, fetch \"vkGetBufferMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] pub vkGetBufferMemoryRequirements2KHR: PFN_vkGetBufferMemoryRequirements2, - #[doc = " Fetch \"vkGetImageMemoryRequirements 2\" on Vulkan >= 1.1, fetch \"vkGetImageMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] + #[doc = " Fetch \"vkGetImageMemoryRequirements2\" on Vulkan >= 1.1, fetch \"vkGetImageMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension."] pub vkGetImageMemoryRequirements2KHR: PFN_vkGetImageMemoryRequirements2, #[doc = " Fetch \"vkBindBufferMemory2\" on Vulkan >= 1.1, fetch \"vkBindBufferMemory2KHR\" when using VK_KHR_bind_memory2 extension."] pub vkBindBufferMemory2KHR: PFN_vkBindBufferMemory2, @@ -741,6 +741,11 @@ pub struct VmaAllocationCreateInfo { #[doc = "Set to 0 if no additional flags are preferred. \\n"] #[doc = "If `pool` is not null, this member is ignored."] pub preferredFlags: MemoryPropertyFlags, + #[doc = " \\brief Flags that preferably should not be set in a memory type chosen for an allocation."] + #[doc = ""] + #[doc = "Set to 0 if no flags are undesired. \\n"] + #[doc = "If `pool` is not null, this member is ignored."] + pub notPreferredFlags: MemoryPropertyFlags, #[doc = " \\brief Bitmask containing one bit set for every memory type acceptable for this allocation."] #[doc = ""] #[doc = "Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if"] diff --git a/vendor/VulkanMemoryAllocator b/vendor/VulkanMemoryAllocator index 5ab8c17..2dee818 160000 --- a/vendor/VulkanMemoryAllocator +++ b/vendor/VulkanMemoryAllocator @@ -1 +1 @@ -Subproject commit 5ab8c1752ab9720b7a38a3bc72ebcf17ef3ce6f1 +Subproject commit 2dee8184021afd7941a437879e7a2058037f287a From 420c53c045689c6182247edc91cebe777b560425 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Sat, 14 May 2022 01:32:54 -0700 Subject: [PATCH 19/23] fixes --- src/definitions.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/definitions.rs b/src/definitions.rs index cbd1e6a..707ce6c 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -412,7 +412,7 @@ impl<'a> AllocatorCreateInfo<'a> { self } - pub fn flags(mut self, flags: AllocationCreateFlags) -> Self { + pub fn flags(mut self, flags: AllocatorCreateFlags) -> Self { self.inner.flags = flags.bits; self } @@ -575,6 +575,7 @@ impl Default for AllocationCreateInfo { usage: MemoryUsage::Unknown, required_flags: vk::MemoryPropertyFlags::empty(), preferred_flags: vk::MemoryPropertyFlags::empty(), + not_preferred_flags: vk::MemoryPropertyFlags::empty(), memory_type_bits: 0, user_data: 0, priority: 0.0, @@ -608,6 +609,7 @@ impl From<&AllocationCreateInfo> for ffi::VmaAllocationCreateInfo { usage, requiredFlags: info.required_flags, preferredFlags: info.preferred_flags, + notPreferredFlags: info.not_preferred_flags, memoryTypeBits: info.memory_type_bits, pool: std::ptr::null_mut(), pUserData: info.user_data as _, From ba3bd98990a603594d3f3b2d13a60082ee4708f7 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Tue, 24 May 2022 21:08:02 -0700 Subject: [PATCH 20/23] fix segfault in prod --- src/lib.rs | 117 +++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 648f5ff..da199b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,66 +59,67 @@ impl Allocator { panic!("VMA_DYNAMIC_VULKAN_FUNCTIONS is unsupported") } + #[cfg(feature = "loaded")] + let routed_functions = ffi::VmaVulkanFunctions { + vkGetInstanceProcAddr: get_instance_proc_addr_stub, + vkGetDeviceProcAddr: get_get_device_proc_stub, + vkGetPhysicalDeviceProperties: create_info + .instance + .fp_v1_0() + .get_physical_device_properties, + vkGetPhysicalDeviceMemoryProperties: create_info + .instance + .fp_v1_0() + .get_physical_device_memory_properties, + vkAllocateMemory: create_info.device.fp_v1_0().allocate_memory, + vkFreeMemory: create_info.device.fp_v1_0().free_memory, + vkMapMemory: create_info.device.fp_v1_0().map_memory, + vkUnmapMemory: create_info.device.fp_v1_0().unmap_memory, + vkFlushMappedMemoryRanges: create_info.device.fp_v1_0().flush_mapped_memory_ranges, + vkInvalidateMappedMemoryRanges: create_info + .device + .fp_v1_0() + .invalidate_mapped_memory_ranges, + vkBindBufferMemory: create_info.device.fp_v1_0().bind_buffer_memory, + vkBindImageMemory: create_info.device.fp_v1_0().bind_image_memory, + vkGetBufferMemoryRequirements: create_info + .device + .fp_v1_0() + .get_buffer_memory_requirements, + vkGetImageMemoryRequirements: create_info + .device + .fp_v1_0() + .get_image_memory_requirements, + vkCreateBuffer: create_info.device.fp_v1_0().create_buffer, + vkDestroyBuffer: create_info.device.fp_v1_0().destroy_buffer, + vkCreateImage: create_info.device.fp_v1_0().create_image, + vkDestroyImage: create_info.device.fp_v1_0().destroy_image, + vkCmdCopyBuffer: create_info.device.fp_v1_0().cmd_copy_buffer, + vkGetBufferMemoryRequirements2KHR: create_info + .device + .fp_v1_1() + .get_buffer_memory_requirements2, + vkGetImageMemoryRequirements2KHR: create_info + .device + .fp_v1_1() + .get_image_memory_requirements2, + vkBindBufferMemory2KHR: create_info.device.fp_v1_1().bind_buffer_memory2, + vkBindImageMemory2KHR: create_info.device.fp_v1_1().bind_image_memory2, + vkGetPhysicalDeviceMemoryProperties2KHR: create_info + .instance + .fp_v1_1() + .get_physical_device_memory_properties2, + vkGetDeviceBufferMemoryRequirements: create_info + .device + .fp_v1_3() + .get_device_buffer_memory_requirements, + vkGetDeviceImageMemoryRequirements: create_info + .device + .fp_v1_3() + .get_device_image_memory_requirements, + }; #[cfg(feature = "loaded")] { - let routed_functions = ffi::VmaVulkanFunctions { - vkGetInstanceProcAddr: get_instance_proc_addr_stub, - vkGetDeviceProcAddr: get_get_device_proc_stub, - vkGetPhysicalDeviceProperties: create_info - .instance - .fp_v1_0() - .get_physical_device_properties, - vkGetPhysicalDeviceMemoryProperties: create_info - .instance - .fp_v1_0() - .get_physical_device_memory_properties, - vkAllocateMemory: create_info.device.fp_v1_0().allocate_memory, - vkFreeMemory: create_info.device.fp_v1_0().free_memory, - vkMapMemory: create_info.device.fp_v1_0().map_memory, - vkUnmapMemory: create_info.device.fp_v1_0().unmap_memory, - vkFlushMappedMemoryRanges: create_info.device.fp_v1_0().flush_mapped_memory_ranges, - vkInvalidateMappedMemoryRanges: create_info - .device - .fp_v1_0() - .invalidate_mapped_memory_ranges, - vkBindBufferMemory: create_info.device.fp_v1_0().bind_buffer_memory, - vkBindImageMemory: create_info.device.fp_v1_0().bind_image_memory, - vkGetBufferMemoryRequirements: create_info - .device - .fp_v1_0() - .get_buffer_memory_requirements, - vkGetImageMemoryRequirements: create_info - .device - .fp_v1_0() - .get_image_memory_requirements, - vkCreateBuffer: create_info.device.fp_v1_0().create_buffer, - vkDestroyBuffer: create_info.device.fp_v1_0().destroy_buffer, - vkCreateImage: create_info.device.fp_v1_0().create_image, - vkDestroyImage: create_info.device.fp_v1_0().destroy_image, - vkCmdCopyBuffer: create_info.device.fp_v1_0().cmd_copy_buffer, - vkGetBufferMemoryRequirements2KHR: create_info - .device - .fp_v1_1() - .get_buffer_memory_requirements2, - vkGetImageMemoryRequirements2KHR: create_info - .device - .fp_v1_1() - .get_image_memory_requirements2, - vkBindBufferMemory2KHR: create_info.device.fp_v1_1().bind_buffer_memory2, - vkBindImageMemory2KHR: create_info.device.fp_v1_1().bind_image_memory2, - vkGetPhysicalDeviceMemoryProperties2KHR: create_info - .instance - .fp_v1_1() - .get_physical_device_memory_properties2, - vkGetDeviceBufferMemoryRequirements: create_info - .device - .fp_v1_3() - .get_device_buffer_memory_requirements, - vkGetDeviceImageMemoryRequirements: create_info - .device - .fp_v1_3() - .get_device_image_memory_requirements, - }; create_info.inner.pVulkanFunctions = &routed_functions; } unsafe { From 3b2ac31cde41e1d909f2e98e39fa76253779b499 Mon Sep 17 00:00:00 2001 From: Michael Mestnik Date: Wed, 3 Aug 2022 11:54:09 -0500 Subject: [PATCH 21/23] Make more generic, for and to replace . --- Cargo.toml | 2 +- src/definitions.rs | 25 ++++++++++++++----------- src/lib.rs | 7 ++++++- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 10356b8..00ac7e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ bitflags = "1.2.1" cc = "1.0" [build-dependencies.bindgen] -version = "0.59" +version = "0.60" optional = true [profile.release] diff --git a/src/definitions.rs b/src/definitions.rs index 707ce6c..0d868eb 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -1,8 +1,9 @@ use crate::ffi; use ash::vk; use ash::vk::PhysicalDevice; -use ash::{Device, Instance}; use bitflags::bitflags; +use std::marker::PhantomData; +use std::ops::Deref; use std::ptr; /// Intended usage of memory. @@ -374,20 +375,21 @@ bitflags! { } } -pub struct AllocatorCreateInfo<'a> { +pub struct AllocatorCreateInfo<'a, I, D> { pub(crate) inner: ffi::VmaAllocatorCreateInfo, pub(crate) physical_device: PhysicalDevice, - pub(crate) device: &'a Device, - pub(crate) instance: &'a Instance, + pub(crate) instance: I, + pub(crate) device: D, + pub(crate) _phantom_data: PhantomData<&'a u8>, } -impl<'a> AllocatorCreateInfo<'a> { - pub fn new( - instance: &'a ash::Instance, - device: &'a ash::Device, - physical_device: ash::vk::PhysicalDevice, - ) -> AllocatorCreateInfo<'a> { - AllocatorCreateInfo { +impl<'a, I, D> AllocatorCreateInfo<'a, I, D> +where + I: Deref, + D: Deref, +{ + pub fn new(instance: I, device: D, physical_device: ash::vk::PhysicalDevice) -> Self { + Self { inner: ffi::VmaAllocatorCreateInfo { flags: 0, physicalDevice: physical_device, @@ -404,6 +406,7 @@ impl<'a> AllocatorCreateInfo<'a> { physical_device, device, instance, + _phantom_data: Default::default(), } } diff --git a/src/lib.rs b/src/lib.rs index da199b0..af11a3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub use pool::*; use ash::prelude::VkResult; use ash::vk; use std::mem; +use std::ops::Deref; /// Main allocator object pub struct Allocator { @@ -44,7 +45,11 @@ unsafe impl Sync for Allocation {} impl Allocator { /// Constructor a new `Allocator` using the provided options. - pub fn new(mut create_info: AllocatorCreateInfo) -> VkResult { + pub fn new<'a, I, D>(mut create_info: AllocatorCreateInfo<'a, I, D>) -> VkResult + where + I: Deref, + D: Deref, + { unsafe extern "system" fn get_instance_proc_addr_stub( _instance: ash::vk::Instance, _p_name: *const ::std::os::raw::c_char, From 61112ecd94701ace75c76a540fa6169df666474b Mon Sep 17 00:00:00 2001 From: Michael Mestnik Date: Thu, 4 Aug 2022 12:56:25 -0500 Subject: [PATCH 22/23] Foo bar --- src/definitions.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/definitions.rs b/src/definitions.rs index 0d868eb..c9b19c1 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -5,6 +5,7 @@ use bitflags::bitflags; use std::marker::PhantomData; use std::ops::Deref; use std::ptr; +use std::rc::Rc; /// Intended usage of memory. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)] @@ -378,8 +379,8 @@ bitflags! { pub struct AllocatorCreateInfo<'a, I, D> { pub(crate) inner: ffi::VmaAllocatorCreateInfo, pub(crate) physical_device: PhysicalDevice, - pub(crate) instance: I, - pub(crate) device: D, + pub(crate) instance: Rc, + pub(crate) device: Rc, pub(crate) _phantom_data: PhantomData<&'a u8>, } @@ -388,7 +389,7 @@ where I: Deref, D: Deref, { - pub fn new(instance: I, device: D, physical_device: ash::vk::PhysicalDevice) -> Self { + pub fn new(instance: Rc, device: Rc, physical_device: ash::vk::PhysicalDevice) -> Self { Self { inner: ffi::VmaAllocatorCreateInfo { flags: 0, From 98f21207dea6337d5db76c1016846bd93b1dcecb Mon Sep 17 00:00:00 2001 From: Michael Mestnik Date: Thu, 4 Aug 2022 13:07:09 -0500 Subject: [PATCH 23/23] Derive debug --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index af11a3a..e6246c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ unsafe impl Sync for Allocator {} /// use `Allocator::get_allocation_info`. /// /// Some kinds allocations can be in lost state. +#[derive(Debug)] pub struct Allocation(ffi::VmaAllocation); unsafe impl Send for Allocation {} unsafe impl Sync for Allocation {}