GithubHelp home page GithubHelp logo

gpuopen-librariesandsdks / vulkanmemoryallocator Goto Github PK

View Code? Open in Web Editor NEW
2.4K 84.0 327.0 26.9 MB

Easy to integrate Vulkan memory allocation library

License: MIT License

Batchfile 0.02% GLSL 0.26% C++ 39.35% C 58.59% Python 1.20% CMake 0.58%
vulkan memory-management

vulkanmemoryallocator's Introduction

Vulkan Memory Allocator

Easy to integrate Vulkan memory allocation library.

Documentation: Browse online: Vulkan Memory Allocator (generated from Doxygen-style comments in include/vk_mem_alloc.h)

License: MIT. See LICENSE.txt

Changelog: See CHANGELOG.md

Product page: Vulkan Memory Allocator on GPUOpen

Build status:

  • Windows: Build status
  • Linux: Build Status

Average time to resolve an issue

Problem

Memory allocation and resource (buffer and image) creation in Vulkan is difficult (comparing to older graphics APIs, like D3D11 or OpenGL) for several reasons:

  • It requires a lot of boilerplate code, just like everything else in Vulkan, because it is a low-level and high-performance API.
  • There is additional level of indirection: VkDeviceMemory is allocated separately from creating VkBuffer/VkImage and they must be bound together.
  • Driver must be queried for supported memory heaps and memory types. Different GPU vendors provide different types of it.
  • It is recommended to allocate bigger chunks of memory and assign parts of them to particular resources, as there is a limit on maximum number of memory blocks that can be allocated.

Features

This library can help game developers to manage memory allocations and resource creation by offering some higher-level functions:

  1. Functions that help to choose correct and optimal memory type based on intended usage of the memory.
    • Required or preferred traits of the memory are expressed using higher-level description comparing to Vulkan flags.
  2. Functions that allocate memory blocks, reserve and return parts of them (VkDeviceMemory + offset + size) to the user.
    • Library keeps track of allocated memory blocks, used and unused ranges inside them, finds best matching unused ranges for new allocations, respects all the rules of alignment and buffer/image granularity.
  3. Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.

Additional features:

  • Well-documented - description of all functions and structures provided, along with chapters that contain general description and example code.
  • Thread-safety: Library is designed to be used in multithreaded code. Access to a single device memory block referred by different buffers and textures (binding, mapping) is synchronized internally. Memory mapping is reference-counted.
  • Configuration: Fill optional members of VmaAllocatorCreateInfo structure to provide custom CPU memory allocator, pointers to Vulkan functions and other parameters.
  • Customization and integration with custom engines: Predefine appropriate macros to provide your own implementation of all external facilities used by the library like assert, mutex, atomic.
  • Support for memory mapping, reference-counted internally. Support for persistently mapped memory: Just allocate with appropriate flag and access the pointer to already mapped memory.
  • Support for non-coherent memory. Functions that flush/invalidate memory. nonCoherentAtomSize is respected automatically.
  • Support for resource aliasing (overlap).
  • Support for sparse binding and sparse residency: Convenience functions that allocate or free multiple memory pages at once.
  • Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size) and allocate memory out of it.
  • Linear allocator: Create a pool with linear algorithm and use it for much faster allocations and deallocations in free-at-once, stack, double stack, or ring buffer fashion.
  • Support for Vulkan 1.0, 1.1, 1.2, 1.3.
  • Support for extensions (and equivalent functionality included in new Vulkan versions):
    • VK_KHR_dedicated_allocation: Just enable it and it will be used automatically by the library.
    • VK_KHR_bind_memory2.
    • VK_KHR_maintenance4.
    • VK_KHR_maintenance5, including VkBufferUsageFlags2CreateInfoKHR.
    • VK_EXT_memory_budget: Used internally if available to query for current usage and budget. If not available, it falls back to an estimation based on memory heap sizes.
    • VK_KHR_buffer_device_address: Flag VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR is automatically added to memory allocations where needed.
    • VK_EXT_memory_priority: Set priority of allocations or custom pools and it will be set automatically using this extension.
    • VK_AMD_device_coherent_memory.
  • Defragmentation of GPU and CPU memory: Let the library move data around to free some memory blocks and make your allocations better compacted.
  • Statistics: Obtain brief or detailed statistics about the amount of memory used, unused, number of allocated blocks, number of allocations etc. - globally, per memory heap, and per memory type.
  • Debug annotations: Associate custom void* pUserData and debug char* pName with each allocation.
  • JSON dump: Obtain a string in JSON format with detailed map of internal state, including list of allocations, their string names, and gaps between them.
  • Convert this JSON dump into a picture to visualize your memory. See tools/GpuMemDumpVis.
  • Debugging incorrect memory usage: Enable initialization of all allocated memory with a bit pattern to detect usage of uninitialized or freed memory. Enable validation of a magic number after every allocation to detect out-of-bounds memory corruption.
  • Support for interoperability with OpenGL.
  • Virtual allocator: Interface for using core allocation algorithm to allocate any custom data, e.g. pieces of one large buffer.

Prerequisites

  • Self-contained C++ library in single header file. No external dependencies other than standard C and C++ library and of course Vulkan. Some features of C++14 used. STL containers, RTTI, or C++ exceptions are not used.
  • Public interface in C, in same convention as Vulkan API. Implementation in C++.
  • Error handling implemented by returning VkResult error codes - same way as in Vulkan.
  • Interface documented using Doxygen-style comments.
  • Platform-independent, but developed and tested on Windows using Visual Studio. Continuous integration setup for Windows and Linux. Used also on Android, MacOS, and other platforms.

Example

Basic usage of this library is very simple. Advanced features are optional. After you created global VmaAllocator object, a complete code needed to create a buffer may look like this:

VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = 65536;
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;

VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_AUTO;

VkBuffer buffer;
VmaAllocation allocation;
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);

With this one function call:

  1. VkBuffer is created.
  2. VkDeviceMemory block is allocated if needed.
  3. An unused region of the memory block is bound to this buffer.

VmaAllocation is an object that represents memory assigned to this buffer. It can be queried for parameters like VkDeviceMemory handle and offset.

How to build

On Windows it is recommended to use CMake GUI.

Alternatively you can generate/open a Visual Studio from the command line:

# By default CMake picks the newest version of Visual Studio it can use
cmake -S .  -B build -D VMA_BUILD_SAMPLES=ON
cmake --open build

On Linux:

cmake -S . -B build
# Since VMA has no source files, you can skip to installation immediately
cmake --install build --prefix build/install

How to use

After calling either find_package or add_subdirectory simply link the library. This automatically handles configuring the include directory. Example:

find_package(VulkanMemoryAllocator CONFIG REQUIRED)
target_link_libraries(YourGameEngine PRIVATE GPUOpen::VulkanMemoryAllocator)

For more info on using CMake visit the official CMake documentation.

Building using vcpkg

You can download and install VulkanMemoryAllocator using the vcpkg dependency manager:

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install vulkan-memory-allocator

The VulkanMemoryAllocator port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Binaries

The release comes with precompiled binary executable for "VulkanSample" application which contains test suite. It is compiled using Visual Studio 2019, so it requires appropriate libraries to work, including "MSVCP140.dll", "VCRUNTIME140.dll", "VCRUNTIME140_1.dll". If the launch fails with error message telling about those files missing, please download and install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019, "x64" version.

Read more

See Documentation.

Software using this library

Many other projects on GitHub and some game development studios that use Vulkan in their games.

See also

  • D3D12 Memory Allocator - equivalent library for Direct3D 12. License: MIT.
  • Awesome Vulkan - a curated list of awesome Vulkan libraries, debuggers and resources.
  • vcpkg dependency manager from Microsoft also offers a port of this library.
  • VulkanMemoryAllocator-Hpp - C++ binding for this library. License: CC0-1.0.
  • PyVMA - Python wrapper for this library. Author: Jean-Sébastien B. (@realitix). License: Apache 2.0.
  • vk-mem - Rust binding for this library. Author: Graham Wihlidal. License: Apache 2.0 or MIT.
  • Haskell bindings, github - Haskell bindings for this library. Author: Ellie Hermaszewska (@expipiplus1). License BSD-3-Clause.
  • vma_sample_sdl - SDL port of the sample app of this library (with the goal of running it on multiple platforms, including MacOS). Author: @rextimmy. License: MIT.
  • vulkan-malloc - Vulkan memory allocation library for Rust. Based on version 1 of this library. Author: Dylan Ede (@dylanede). License: MIT / Apache 2.0.

vulkanmemoryallocator's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vulkanmemoryallocator's Issues

-Wunused-private-field (Clang / Xcode)

Working on a project with many warnings enabled (and treated as errors). Here is the -Wunused-private-field that shows up with the current master branch.

vk_mem_alloc.h:6434:20: error: private field 'm_AlgorithmFlags' is not used [-Werror,-Wunused-private-field]
    const uint32_t m_AlgorithmFlags;

Docs issue with vmaUnmapPersistentlyMappedMemory

The comment/docs for vmaUnmapPersistentlyMappedMemory() reads;

Unmaps persistently mapped memory of types that is HOST_COHERENT and DEVICE_LOCAL.
This is optional performance optimization. You should call it on Windows for time of call to vkQueueSubmit and vkQueuePresent, for performance reasons, because of the internal behavior of WDDM.

The second half of that isn't particularly clear as to what you should and shouldn't do on Windows.

I'm torn between "don't unmap something between it being used in vkQueueSubmit and the following vkQueuePresent" and "only unmap/unmap persistently between where it is used and the following vkQueuePresent".

how should I update a uniform buffer

In my engine, there are many uniform buffer. But i don't update these every frame.
When I update uniform buffer by Stage buffer, it work well. But update uniform buffer by getting pMappedData through vmaMapMemory, the result will flicker.
BTW, In a simple demo as vulkan-tutorial, vmaMapMemory work well.
This is how I create Buffer.

VmaAllocationCreateInfo allocInfo{};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
VkBuffer buffer;
auto & LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
vmaCreateBuffer(LogicalDevice.GetVmaAlloctor(), &VkBuffCI, &allocInfo, &buffer, &m_GPUMemory, &info);

I want to know what may happened, when I update uniform buffer.
What interesting is that not flicker launched by renderdoc.

error uniform buffer.
0 3: MaterialUniforms ResourceId::447 0 - 448 81 Variables, 452 bytes needed, 448 provided

The bad result:
image
image

Unable to build on Clang 8.0.0

In file included from src/p3d-vma.cpp:9:                                                                                                                                           
ext/VulkanMemoryAllocator/src\vk_mem_alloc.h:4441:47: error: call to implicitly-deleted default constructor of 'VmaPoolAllocator<VmaAllocation_T>::Item'                           
        vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity),                                                                                                             
                                              ^                                                                                                                                    
ext/VulkanMemoryAllocator/src\vk_mem_alloc.h:4404:27: note: in instantiation of member function 'VmaPoolAllocator<VmaAllocation_T>::CreateNewBlock' requested here                 
    ItemBlock& newBlock = CreateNewBlock();                                                                                                                                        
                          ^                                                                                                                                                        
ext/VulkanMemoryAllocator/src\vk_mem_alloc.h:14113:24: note: in instantiation of member function 'VmaPoolAllocator<VmaAllocation_T>::Alloc' requested here                         
    return m_Allocator.Alloc();                                                                                                                                                    
                       ^                                                                                                                                                           
ext/VulkanMemoryAllocator/src\vk_mem_alloc.h:4348:11: note: default constructor of 'Item' is implicitly deleted because variant field 'Value' has a non-trivial default constructor
        T Value;                                                                                                                                                                   
          ^                                                                                                                                                                        
1 error generated.       

I am not exactly sure what is going on, but I suspect the error is caused by the member VmaAllocation_T::m_LastUseFrameIndex; Its type is std::atomic<uint32_t> which does have a constructor. VmaPoolAllocator places one of those inside an union.

My build command is:

$ clang++.exe src/p3d-vma.cpp -Iinclude -Iext/VulkanMemoryAllocator/src -Iext/Vulkan-1.1.97.0/include

Contents of p3d-vma.cpp:

#define VMA_IMPLEMENTATION
#include <vk_mem_alloc.h>

clang++ --version:

$ clang++.exe --version
clang version 8.0.0 (tags/RELEASE_800/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

Trying to compile in C project

Hi,
I tried including VMA in my C project using:

#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"

but when I compile with gcc (-std=c11) I get this error:

In file included from src/vulkan.c:11:0:
src/vk_mem_alloc.h:2616:10: fatal error: cstdint: No such file or directory
 #include <cstdint>
          ^~~~~~~~~
compilation terminated.

I wouldn't be surprised if I'm just missing something obvious, but I can't figure out what.

Any help would be much appreciated.
Thank you.

Fails to compile on Android

VmaDefragmentationAlgorithm_Generic constructor initializer list should be reversed for
m_AllocationCount and m_AllAllocations to fix the "m_AllAllocations field will be initialized after m_AllocationCount field" compiler error on Android.

-Wmissing-field-initializers (Clang / Xcode / GCC)

Working on a project with many warnings enabled (and treated as errors). Here are the -Wmissing-field-initializers that show up with the current master branch.

Clang / Xcode:

vk_mem_alloc.h:12122:79: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
                                                                              ^
vk_mem_alloc.h:12211:80: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
                                                                               ^
vk_mem_alloc.h:14560:79: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
                                                                              ^
vk_mem_alloc.h:14565:114: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
    VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
                                                                                                                 ^
vk_mem_alloc.h:14704:115: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };
                                                                                                                  ^
vk_mem_alloc.h:14707:114: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
                                                                                                                 ^
vk_mem_alloc.h:14709:90: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
                                                                                         ^
vk_mem_alloc.h:14736:113: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };
                                                                                                                ^
vk_mem_alloc.h:14739:114: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
                                                                                                                 ^
vk_mem_alloc.h:14741:90: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
                                                                                         ^
vk_mem_alloc.h:15502:80: error: missing field 'pNext' initializer [-Werror,-Wmissing-field-initializers]
        VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
                                                                               ^

GCC 9:

vk_mem_alloc.h: In member function 'VkResult VmaBlockVector::CreateBlock(VkDeviceSize, size_t*)':
vk_mem_alloc.h:12122:79: error: missing initializer for member 'VkMemoryAllocateInfo::pNext' [-Werror=missing-field-initializers]
12122 |     VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
      |                                                                               ^
vk_mem_alloc.h:12122:79: error: missing initializer for member 'VkMemoryAllocateInfo::allocationSize' [-Werror=missing-field-initializers]
vk_mem_alloc.h:12122:79: error: missing initializer for member 'VkMemoryAllocateInfo::memoryTypeIndex' [-Werror=missing-field-initializers]
vk_mem_alloc.h: In member function 'void VmaBlockVector::ApplyDefragmentationMovesCpu(VmaBlockVectorDefragmentationContext*, const VmaVector<VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >&)':
vk_mem_alloc.h:12211:80: error: missing initializer for member 'VkMappedMemoryRange::pNext' [-Werror=missing-field-initializers]
12211 |         VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
      |                                                                                ^
vk_mem_alloc.h:12211:80: error: missing initializer for member 'VkMappedMemoryRange::memory' [-Werror=missing-field-initializers]
vk_mem_alloc.h:12211:80: error: missing initializer for member 'VkMappedMemoryRange::offset' [-Werror=missing-field-initializers]
vk_mem_alloc.h:12211:80: error: missing initializer for member 'VkMappedMemoryRange::size' [-Werror=missing-field-initializers]
vk_mem_alloc.h: In member function 'VkResult VmaAllocator_T::AllocateDedicatedMemory(VkDeviceSize, VmaSuballocationType, uint32_t, bool, bool, void*, VkBuffer, VkImage, size_t, VmaAllocation_T**)':
vk_mem_alloc.h:14560:79: error: missing initializer for member 'VkMemoryAllocateInfo::pNext' [-Werror=missing-field-initializers]
14560 |     VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
      |                                                                               ^
vk_mem_alloc.h:14560:79: error: missing initializer for member 'VkMemoryAllocateInfo::allocationSize' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14560:79: error: missing initializer for member 'VkMemoryAllocateInfo::memoryTypeIndex' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14565:114: error: missing initializer for member 'VkMemoryDedicatedAllocateInfo::pNext' [-Werror=missing-field-initializers]
14565 |     VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
      |                                                                                                                  ^
vk_mem_alloc.h:14565:114: error: missing initializer for member 'VkMemoryDedicatedAllocateInfo::image' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14565:114: error: missing initializer for member 'VkMemoryDedicatedAllocateInfo::buffer' [-Werror=missing-field-initializers]
vk_mem_alloc.h: In member function 'void VmaAllocator_T::GetBufferMemoryRequirements(VkBuffer, VkMemoryRequirements&, bool&, bool&) const':
vk_mem_alloc.h:14704:115: error: missing initializer for member 'VkBufferMemoryRequirementsInfo2::pNext' [-Werror=missing-field-initializers]
14704 |         VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };
      |                                                                                                                   ^
vk_mem_alloc.h:14704:115: error: missing initializer for member 'VkBufferMemoryRequirementsInfo2::buffer' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14707:114: error: missing initializer for member 'VkMemoryDedicatedRequirements::pNext' [-Werror=missing-field-initializers]
14707 |         VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
      |                                                                                                                  ^
vk_mem_alloc.h:14707:114: error: missing initializer for member 'VkMemoryDedicatedRequirements::prefersDedicatedAllocation' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14707:114: error: missing initializer for member 'VkMemoryDedicatedRequirements::requiresDedicatedAllocation' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14709:90: error: missing initializer for member 'VkMemoryRequirements2::pNext' [-Werror=missing-field-initializers]
14709 |         VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
      |                                                                                          ^
vk_mem_alloc.h:14709:90: error: missing initializer for member 'VkMemoryRequirements2::memoryRequirements' [-Werror=missing-field-initializers]
vk_mem_alloc.h: In member function 'void VmaAllocator_T::GetImageMemoryRequirements(VkImage, VkMemoryRequirements&, bool&, bool&) const':
vk_mem_alloc.h:14736:113: error: missing initializer for member 'VkImageMemoryRequirementsInfo2::pNext' [-Werror=missing-field-initializers]
14736 |         VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };
      |                                                                                                                 ^
vk_mem_alloc.h:14736:113: error: missing initializer for member 'VkImageMemoryRequirementsInfo2::image' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14739:114: error: missing initializer for member 'VkMemoryDedicatedRequirements::pNext' [-Werror=missing-field-initializers]
14739 |         VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
      |                                                                                                                  ^
vk_mem_alloc.h:14739:114: error: missing initializer for member 'VkMemoryDedicatedRequirements::prefersDedicatedAllocation' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14739:114: error: missing initializer for member 'VkMemoryDedicatedRequirements::requiresDedicatedAllocation' [-Werror=missing-field-initializers]
vk_mem_alloc.h:14741:90: error: missing initializer for member 'VkMemoryRequirements2::pNext' [-Werror=missing-field-initializers]
14741 |         VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
      |                                                                                          ^
vk_mem_alloc.h:14741:90: error: missing initializer for member 'VkMemoryRequirements2::memoryRequirements' [-Werror=missing-field-initializers]
vk_mem_alloc.h: In member function 'void VmaAllocator_T::FlushOrInvalidateAllocation(VmaAllocation, VkDeviceSize, VkDeviceSize, VMA_CACHE_OPERATION)':
vk_mem_alloc.h:15502:80: error: missing initializer for member 'VkMappedMemoryRange::pNext' [-Werror=missing-field-initializers]
15502 |         VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
      |                                                                                ^
vk_mem_alloc.h:15502:80: error: missing initializer for member 'VkMappedMemoryRange::memory' [-Werror=missing-field-initializers]
vk_mem_alloc.h:15502:80: error: missing initializer for member 'VkMappedMemoryRange::offset' [-Werror=missing-field-initializers]
vk_mem_alloc.h:15502:80: error: missing initializer for member 'VkMappedMemoryRange::size' [-Werror=missing-field-initializers]

Add xml description file in Vulkan style

Hello,

I'm the author of the Vulkan wrapper for Python https://github.com/realitix/vulkan. It works by parsing the vk.xml file. Lot of wrappers are generated this way.

Proposal

Adding an XML file that follows the vk.xml format would allow to easily write a wrapper for your library. @Berserker66 requested a wrapper for your library and I think that lot of people could be interested in.
Your library is becoming the reference as Vulkan memory allocator.

What do you think about this idea ?

Option to avoid including vulkan.h

Hey, in my codebase I avoid external dependencies where possible, and the #include <vulkan/vulkan.h> means search paths must be set up to point to locate it.

Would it be possible to have a VMA_NO_INCLUDE_VULKAN_H or similar option, where I could include vulkan.h myself before including vk_mem_alloc.h, and then vk_mem_alloc.h wouldn't include vulkan.h itself at all?

[Improvement] Allow several ways to retrieve Vulkan functions

Hi @adam-sawicki-amd,

As a result of our email conversation, I open this issue to keep track of the changes and to talk about the best way to do it.

Context

In the LunarG documentation, it's explicitly written that in order to maximize performance, Vulkan functions should be retrieved from vkGetDeviceProcAddr.

So there are 4 ways to retrieve Vulkan functions:

1 - statically linked with the SDK
2 - dynamically linked during linktime with the SDK
3 - dynamically linked during runtime with the SDK
4 - retrieved from vkGetDeviceProcAddr

Current state

Currently, with your library, the 2 last options are unavailable.
Theses 2 last options are the most common ways to use Vulkan SDK because (3) allows to gracefully exit if SDK is unavailable and (4) allows for the best performance.

Improvement

Add in VmaAllocatorCreateInfo an optional field for each Vulkan function used in the library.
These fields have to be optional for people who wants to link during linktime.
This change would allow to use your library in the 4 modes listed above.

Let's do it !

[Improvement] Allow new (and future) extensions when allocating memory

Hi Adam,

I was wondering if you had any plan to expose the possibility to add more extensions when allocating the memory (other than the dedicated memory one).

My use case as of right now is to create memory that will be able to be exported (by using VkExportMemoryAllocateInfoKHR) so it can be used in OpenGL. But a more "general" mechanism could probably be used to expose current and future extensions as well.

Let me know what you think !
Cheers

Remove dependency on windows.h

#include <vulkan/vulkan.h>

For those who want to use VMA without pulling windows.h or having Vulkan already included, it would be nice to remove this line and replace it with this:

#ifndef VULKAN_H_
#	ifdef VK_USE_PLATFORM_WIN32_KHR
#		include <vulkan/vk_platform.h>
#		include <vulkan/vulkan_core.h>

		typedef unsigned long DWORD;
		typedef const wchar_t* LPCWSTR;
		typedef void* HANDLE;
		typedef struct HINSTANCE__* HINSTANCE;
		typedef struct HWND__* HWND;
		typedef struct HMONITOR__* HMONITOR;
		typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;

#		include <vulkan/vulkan_win32.h>
#	else
#		include <vulkan/vulkan.h>
#	endif
#endif

Then in the implementation part, either include windows.h or even better, only use the necessary win32 stuff.

This saves ~200ms when parsing.

size_t value passed to fprintf with formatted %llu

In VmaRecorder::RecordCreatePool there's a fprintf call which uses %llu to print createInfo.minBlockCount and createInfo.maxBlockCount which are both of type size_t. This will fail on 32-bit platforms.

I think some printf implementations support %zu but I don't think that's standard, so it might be better to just cast those values up to uint64_t.

-Wunused-variable (Clang / Xcode / GCC)

Working on a project with many warnings enabled (and treated as errors). Here are the -Wunused-variable warnings that show up with the current master branch.

vk_mem_alloc.h:10344:38: error: unused variable 'suballocations1st' [-Werror,-Wunused-variable]
            SuballocationVectorType& suballocations1st = AccessSuballocations1st();
                                     ^
vk_mem_alloc.h:11910:34: error: unused variable 'res' [-Werror,-Wunused-variable]
                        VkResult res = pBestRequestBlock->WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);
                                 ^
vk_mem_alloc.h:11948:22: error: unused variable 'res' [-Werror,-Wunused-variable]
            VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
                     ^
vk_mem_alloc.h:12112:22: error: unused variable 'res' [-Werror,-Wunused-variable]
            VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);
                     ^
vk_mem_alloc.h:12452:16: error: unused variable 'isHostCoherent' [-Werror,-Wunused-variable]
    const bool isHostCoherent = (memPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
               ^
vk_mem_alloc.h:15252:14: error: unused variable 'success' [-Werror,-Wunused-variable]
        bool success = VmaVectorRemoveSorted<VmaPointerLess>(m_Pools, pool);
             ^
vk_mem_alloc.h:15574:14: error: unused variable 'success' [-Werror,-Wunused-variable]
        bool success = VmaVectorRemoveSorted<VmaPointerLess>(*pDedicatedAllocations, allocation);

Few unused variables.

You have few unused variables:
vk_mem_alloc.h(12288): warning : unused variable 'nonCoherentAtomSize' [-Wunused-variable] vk_mem_alloc.h(12289): warning : unused variable 'memRange' [-Wunused-variable] vk_mem_alloc.h(12423): warning : unused variable 'isHostCoherent' [-Wunused-variable] vk_mem_alloc.h(6414): warning : private field 'm_AlgorithmFlags' is not used [-Wunused-private-field]
I opened issue instead pull request because I'm not sure if you left them intentionally, or not.

vmaFreeMemory generate a assert

When vmaFreeMemory got called, it's generate a assert, I've tried to remove it but another assert tell me that I must free the allocations with it.. I don't know what to do

Unreferenced variable warning

I'd like to make a suggestion to suppress warning C4100 (unreferenced variable) for microsoft compiler or to update code correspondingly. We build our project with 'treat warnings as errors' and to fix build error we have to add #pragma warning( disable : 4100 ) to vk_mem_alloc.h.

VmaAllocation::Free does the same thing regardless of forwardDirection

VmaAllocation::Free looks like this:

void VmaAllocation::Free(const VkMappedMemoryRange* pMemory)
{
    // If suballocation to free has offset smaller than half of allocation size, search forward.
    // Otherwise search backward.
    const bool forwardDirection = pMemory->offset < (m_Size / 2);
    if(forwardDirection)
    {
        for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
            suballocItem != m_Suballocations.end();
            ++suballocItem)
        {
            VmaSuballocation& suballoc = *suballocItem;
            if(suballoc.offset == pMemory->offset)
            {
                FreeSuballocation(suballocItem);
                VMA_HEAVY_ASSERT(Validate());
                return;
            }
        }
        VMA_ASSERT(0 && "Not found!");
    }
    else
    {
        for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
            suballocItem != m_Suballocations.end();
            ++suballocItem)
        {
            VmaSuballocation& suballoc = *suballocItem;
            if(suballoc.offset == pMemory->offset)
            {
                FreeSuballocation(suballocItem);
                VMA_HEAVY_ASSERT(Validate());
                return;
            }
        }
        VMA_ASSERT(0 && "Not found!");
    }
}

Both branches are identical. Presumably the second branch is meant to iterate through the suballocation list in reverse?

vmaCreateAllocator() crashes on Android

I have a simple Vulkan app which renders a single triangle, and I'm trying to use vma to allocate the vertex buffer. This works fine on Windows, but crashes with a segmentation fault on Andoid, as soon as I try to create the allocator like this:

VmaAllocator allocator;
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.physicalDevice = gpu;
allocatorInfo.device = device;
vmaCreateAllocator(&allocatorInfo, &allocator);  // CRASH

The error is:
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 20779 (window.Example3)

If I try to debug, the debugger gets stuck at line 14187:
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);

error: use of undeclared identifier 'LARGE_INTEGER' on Windows clang 6.0

Hi, I'm getting this error when building a 2.1.0-beta.1 with this configuration:

#define VMA_IMPLEMENTATION
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#include "vk_mem_alloc.h"

When using clang version:

clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

I traced this problem to the new recording functionality, adding #define VMA_RECORDING_ENABLED 0 takes care of the problem.

Full output from clang:

>clang++ --std=c++14 amd_alloc.cc -c -o amd_alloc.o -g -IC:\VulkanSDK\1.1.82.0\Include
In file included from amd_alloc.cc:4:
In file included from ./wrapper.h:1:
./vendor/VulkanMemoryAllocator/src/vk_mem_alloc.h:10470:32: error: use of undeclared identifier 'LARGE_INTEGER'
    QueryPerformanceFrequency((LARGE_INTEGER*)&m_Freq);
                               ^
./vendor/VulkanMemoryAllocator/src/vk_mem_alloc.h:10470:46: error: expected expression
    QueryPerformanceFrequency((LARGE_INTEGER*)&m_Freq);
                                             ^
./vendor/VulkanMemoryAllocator/src/vk_mem_alloc.h:10471:30: error: use of undeclared identifier 'LARGE_INTEGER'
    QueryPerformanceCounter((LARGE_INTEGER*)&m_StartCounter);
                             ^
./vendor/VulkanMemoryAllocator/src/vk_mem_alloc.h:10471:44: error: expected expression
    QueryPerformanceCounter((LARGE_INTEGER*)&m_StartCounter);
                                           ^
./vendor/VulkanMemoryAllocator/src/vk_mem_alloc.h:10908:26: error: use of undeclared identifier 'GetCurrentThreadId'
    outParams.threadId = GetCurrentThreadId();
                         ^
./vendor/VulkanMemoryAllocator/src/vk_mem_alloc.h:10910:5: error: unknown type name 'LARGE_INTEGER'
    LARGE_INTEGER counter;
    ^
6 errors generated.

-Wclass-memaccess (GCC)

Working on a project with many warnings enabled (and treated as errors). Here is the -Wclass-memaccess warning that shows up with the current master branch.

GCC 9:

vk_mem_alloc.h: In member function 'void VmaBlockVector::ApplyDefragmentationMovesGpu(VmaBlockVectorDefragmentationContext*, const VmaVector<VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >&, VkCommandBuffer)':
vk_mem_alloc.h:12281:100: error: 'void* memset(void*, int, size_t)' clearing an object of non-trivial type 'struct VmaBlockDefragmentationContext'; use assignment or value-initialization instead [-Werror=class-memaccess]
12281 |     memset(pDefragCtx->blockContexts.data(), 0, blockCount * sizeof(VmaBlockDefragmentationContext));
      |                                                                                                    ^
vk_mem_alloc.h:6386:8: note: 'struct VmaBlockDefragmentationContext' declared here
 6386 | struct VmaBlockDefragmentationContext
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Portability issues

If you are compiling with GCC, it doesn't allow anonymous unions to have static data members, these structs need to be declared outside of the anonymous union https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/src/vk_mem_alloc.h#L2303-L2316 .

Also on 64bit linux, uint64_t is an unsigned long int not a unsigned long long int so you get a warning here https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/src/vk_mem_alloc.h#L843

-Wtautological-compare (Clang / Xcode)

Working on a project with many warnings enabled (and treated as errors). Here are the -Wtautological-compare warnings that show up with the current master branch.

vk_mem_alloc.h:3730:25: error: comparison of unsigned expression < 0 is always false [-Werror,-Wtautological-compare]
    for(size_t i = 0; i < numberCount; ++i, ++pDst)
                      ~ ^ ~~~~~~~~~~~
vk_mem_alloc.h:3740:25: error: comparison of unsigned expression < 0 is always false [-Werror,-Wtautological-compare]
    for(size_t i = 0; i < numberCount; ++i, ++pSrc)
                      ~ ^ ~~~~~~~~~~~

VMA_DEBUG_MARGIN (which defaults to 0) is used to calculate numberCount.

how to manage buffer memory for `VK_NV_RAY_TRACING` AccelerationStructure

AccelerationStructureMemory uses vkGetAccelerationStructureMemoryRequirementsNV to get VkMemoryRequirements2 and uses vkBindAccelerationStructureMemoryNV to bind memory. Allocating memory is the same as usual by calling vkAllocateMemory.
I want to let vma to manage the memory for me, but apparently I cannot just vmaCreateBuffer() as before. vkGetAccelerationStructureMemoryRequirementsNV and vkBindAccelerationStructureMemoryNV should be involved somewhere where I don't know.
I can manually create buffer, allocate memory and bind memory, but I hope vma will choose the memoryType for me and destory the buffer when it is no longer referenced. What are the necessary functions that must be called to achieve this?

Defragmentation relies on undefined memory aliasing behavior

I don't have a reproducer for this, it is just from code inspection.

Defragmentation works by binding a buffer to a block of memory and using that buffer to read the contents originally written through other resources. But if the data was written through an image, then this buffer has undefined contents according to the "Memory Aliasing" section of the Resources chapter, so it may write garbage. It may not even be valid to bind a buffer to this memory, if the buffer doesn't include the memory type in its memoryTypeBits.

This isn't just a theoretical problem, I don't expect these copies to work on NVIDIA's implementation. It may happen to work in some simple cases, but not in general.

Make reliance of extensions optional

The code uses structures and prototypes from these extensions:

VK_KHR_get_memory_requirements2
VK_KHR_dedicated_allocation

On Android, they are not supported and not defined in vulkan.h. For the most part it can be work around by defining them locally in the cpp file including vk_mem_alloc.h however it's not possible to redefine VkStructureType to include a couple missing ones being used.

fails to compile when target android api level < 16 because of 'posix_memalign' undefined

posix_memalign is not available before android api 16, so I use memalign as a replacement.

void *aligned_alloc(size_t alignment, size_t size)
{
    // alignment must be >= sizeof(void*)
    if(alignment < sizeof(void*))
    {
        alignment = sizeof(void*);
    }

#if (defined(__ANDROID_API__) && (__ANDROID_API__ < 16))
	return memalign(alignment, size);
#else
    void *pointer;
    if(posix_memalign(&pointer, alignment, size) == 0)
        return pointer;
    return VMA_NULL;
#endif
}

MSVC: Type "VmaAllocation_T" not defined

Visual Studio prompt me that error when I compile my program, I get no link error just that.
I have a .cpp file with the VMA_IMPLEMENTATION define and included the header file after it

Windows + NOMINMAX

This isn't a real issue, but I got caught by not having NOMINMAX defined on Windows and got a bunch of compiler errors. Soft suggestion to maybe document this somewhere?

Change ifdef guard for VMA_USE_STL_SHARED_MUTEX to use __cplusplus version?

Hi,

Could the following ifdef guard for determining whether to use std::shared_mutex i.e. features of c++17 be determined using something more generic like "#if __cplusplus >= 201403L"?

"
// Minimum Visual Studio 2015 Update 2
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918
#define VMA_USE_STL_SHARED_MUTEX 1
#endif
"

I can see two problems this causes:

  • Support for VMA_USE_STL_SHARED_MUTEX is currently limited to MSC only.
  • We're using Visual Studio 2017 supporting up to c++14 but with the current ifdef guard (shown above) we're getting VMA_USE_STL_SHARED_MUTEX defined and then attempting and failing to use std::shared_mutex.

With VS 2017 and c++14 if I switch to use #if __cplusplus >= 201403L we do not get VMA_USE_STL_SHARED_MUTEX defined and fallback to using VmaRWMutex appropriately.

We're currently using Version 2.1 and can't move to Version 2.2 due to the above.

FYI I'm one of the developers working on the PowerVR SDK and we've been using VMA since Version 2.0.0-alpha.4 - we love it.

Is possible to destroy the VmaAllocator without it trying to make any Vulkan calls.

For our rendering engine, the client supplies us with the VkDevice that they want us to use for drawing. We support an API to abandon our rendering context which essentially means we will clean up all our internal memory, but will not make calls to the underlying graphics api (GL, Vulkan). This is needed in case the client deletes the VkDevice or decided it wasn't trustworthy anymore to call into the driver etc. Obviously this leaks GPU objects, but we're fine with that.

So this leads to the question, is it possible for us to destroy the VmaAllocator in a way that will free its local memory, but not make any Vulkan calls since the VkDevice may no longer be valid?

Persistently Mapped Buffer is Causing Bad VK_IMAGE_TILING_LINEAR Temporary Image

I tried to create a simple example. It just attempts to load a texture and present it on the screen. The example also maps a persistent buffer. The texture pixels are initially copied to a host visible and coherent linear tiling VKImage, and then copied to a device local optimal tiling VKImage. If the persistently mapped buffer is not actually mapped or it is mapped without the use of VMA, then the example works as expected. If the persistently mapped data is mapped with VMA, then the image data is somehow incorrect and not shown correctly. Also, if the texture is initially copied to a temporary buffer instead of a temporary image, then the example works as expected regardless of how the persistently mapped data is setup.

I'm developing on a Mac (Radeon Pro 570 4096 MB) using MoltenVK.

VMA_Test.zip

Functions use MS specific functions

Functions VmaUint32ToStr and VmaUint64ToStr use the Microsoft specific functions _ultoa_s and _ui64toa_s. These can be replaced with calls to snprintf to keep the reliance only on the standard libraries.

Premake configuration not working on Ubuntu16.04

Hi,
I'm trying to use premake5 to generate the makefile on Linux but I encounter a problem.

When I run premake5 gmake, it generates the build configuration files in ../build, this is working.
But when I go into the build folder and I run make, I get:

==== Building VulkanSample (debug_x64) ====
Creating Desktop_gmake2/x64/Debug
VulkanSample.cpp
g++: error: /MDd: Aucun fichier ou dossier de ce type
VulkanSample_gmake2.make:155 : la recette pour la cible « Desktop_gmake2/x64/Debug/VulkanSample.o » a échouée

(In french sorry).

I tried with premake5 --os=linux gmake or premake5 --os=linux gmake2 and the problem persists.
make is trying to add the /MDd flag which is a Windows flag.
I am not familiar with premake so maybe you could find a way.

I have to use premake to compile because I am writing a script that automates the process and it must work on Windows and Linux.

Thanks,
Jean-Sébastien

C++ bindings à la Vulkan-Hpp

I think it would be great to have C++ bindings for VMA that incorporate the types defined in vulkan.hpp (e.g. functions return a vk::Result, not a VkResult). At the moment, you constantly have to switch between the C/C++ types when using this library with Vulkan-Hpp. I find it really inconsistent and annoying to work with. Type-safe bindings would most probably make many C++ programmers happy!

Combining buffers into one large buffer - still necessary?

Hello. Apologies if this isn't the right place to ask such questions, but I've not seen links to any kind of support area.

The Nvidia documentation suggests that it's preferable to to combine buffers into one large buffer and use offsets/ranges within that large buffer to get the best performance. Is this still necessary and/or possible with vma? I'm not sure from the documentation if vma handles this kind of suballocation for me or not.

Questions about Non-Coherent memory and nonCoherentAtomSize

First question is about thread safety of vmaMapMemory(). In the docs it says calls to this need to be externally synchronized for a given VmaAllocation. I assume this means it is safe to call vmaMapMemory on different VmaAllocation objects that have the same VkDeviceMemory from different threads?

Given that, my main questions revolve around VkPhysicalDeviceLimits::nonCoherentAtomSize. Scanning the src code I don't see any reference to this value. I feel like this could have issues for non-coherent VkDeviceMemory that is sub allocated. For vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges the take a VkMappedMemoryRange object. Part of the requirements for this are:

  • If size is equal to VK_WHOLE_SIZE, the end of the current mapping of memory must be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize bytes from the beginning of the memory object.
  • offset must be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize
  • If size is not equal to VK_WHOLE_SIZE, size must either be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize, or offset plus size must equal the size of memory.

So first, are there are guarantees of the offset and size of a VmaAllocation to align those to nonCoherentAtomSize? I assume not since I don't see it referenced in the code.

Therefore if I map and write to a non-coherent VmaAllocation, I may need to pad out the beginning offset and size of the VmaAllocation to meet the alignment requirements stated above. This means I may be padding into neighboring VmaAllocations.

In general this can be okay. If I have two threads each with a neighboring VmaAllocation, and the two VmaAllocations share a "nonCoherentAtomSize block", then at worst I flush that block twice, but as long as I don't ever write into the pad regions I don't think this has an issue (assuming that multiple flushes can't overwrite each other if I'm writing to distinct mapped memory within the shared block).

The one problem I can think of is if my VmaAllocation just happens to be the last sub allocation of the VkDeviceMemory, however I have no way to know this. So if the size is not a multiple of nonCoherentAtomSize I would try to pad the end, but then this is an error cause I'm now flushing/invalidation passed the size of the VkDeviceMemory.

So how is it suggested that this is handled? Should I always make preferredLargeHeapBlockSize of the allocator be a multiple of nonCoherentAtomSize so that I know the padding will always fit? Does setting preferredLargeHeapBlockSize actually mean you guarantee a block of that size?

Thanks for the help!

How to use in C projects

I made multiple attempts at using VMA as-is in a C project with both Visual Studio and CMake without success.

As soon as I define VMA_IMPLEMENTATION and include vk_mem_alloc.h, it breaks the std lib (basic types like size_t are no longer recognized), and I see a lot of errors in the implementation part of VMA.

To bypass this, I usually create a separate C++ lib for VMA, but it's not ideal. I usually only work with C so maybe I'm missing something obvious.

vmaMapMemory triggers validation layer warning on Intel HD 620

When mapping a buffer with vmaMapMemory, a validation layer warning is triggered:

validation layer: Object: 0xb (Type = 8) | Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.

The buffer is created with vmaCreateBuffer:

VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;

auto result = vmaCreateBuffer(_allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);

Then I map the memory with vmaMapMemory:

void* data;
vmaMapMemory(_device.GetAllocator(), allocation, &data);
memcpy(data, RenderMesh::GetVertices().data(), (size_t)bufferSize);
vmaUnmapMemory(_device.GetAllocator(), allocation);

When vmaMapMemory is called, the validation layer warning is triggered 3 times. The call to vmaMapMemory succeeds and works as expected, it just triggers validation warnings every time its called.

When I use vkCreateBuffer, vkAllocateMemory, and vkMapMemory to handle the buffer creation and memory mapping instead of the vma library, the warning is not triggered.

This happens on a Surface Laptop with Intel HD Graphics 620.
Windows 10 Pro x64
Driver version: 24.20.100.6136
Also tried driver: 24.20.100.6229

This does not happen on my discrete NVIDIA GPU, so probably related to the Intel HD 620? I'm still new to Vulkan, so I apologize if I missed something.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.