gpuopen-librariesandsdks / vulkanmemoryallocator Goto Github PK
View Code? Open in Web Editor NEWEasy to integrate Vulkan memory allocation library
License: MIT License
Easy to integrate Vulkan memory allocation library
License: MIT License
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!
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);
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 ?
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.
This will enable use of the allocated memory for sharing across apis / processes. Especially important for VR projects
vk_mem_alloc.h:3306:28: error: 'InitializeSRWLock' was not declared in this scope
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
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.
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
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
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]
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.
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
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.
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 !
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;
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);
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.
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.
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.
The document says the buffer and/or allocation can be null but null allocation will trigger assert when the function calls allocator->FreeMemory(allocation);
I used C++ Vulkan bindings on our project. VulkanMemoryAllocator planned to support of official C++ bindings support?
https://github.com/KhronosGroup/Vulkan-Hpp
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
.
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.
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?
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.
VulkanMemoryAllocator/src/vk_mem_alloc.h
Line 1698 in 195016b
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.
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
https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/memory_mapping.html
The first code example says: VmaBuffer
instead of VkBuffer
.
This sentence should start with "The" instead of "They":
They way it's implemented is that the library always maps entire memory block, not just region of the allocation. For further details, see description of vmaMapMemory() function
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?
VMA doesn't seem to compile under Ubuntu, when VMA_USE_STL_CONTAINERS is defined as 1. The compiler complains about the member 'remove' being unknown for std::vector.
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
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
.
In the "Memory Mapping" section of the documentation it says:
TODO update this...
For a newcomer to this library this is intimidating because I'm not sure if the documentation is correct.
Thank you.
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?
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
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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
}
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?
As of today VK9 uses the VulkanMemoryAllocator. I wasn't sure if you preferred issues or PRs for new items on the list of projects that use the allocator.
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".
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
Does the vulkan memory allocator support device to device memory transfers. We would like to to go GPU to FPGA without going through host memory.
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.
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?
I am getting this warning when running on Intel IGP (issue filled originally for validation layers here):
KhronosGroup/Vulkan-ValidationLayers#990
Still, I think I am doing nothing wrong. It seems this is due to the AMD memory allocator using the same memory for images (where I specify GPU as a hint) as the staging buffer.
I had to harcode disabling this warning, but I think this situation should be resolved.
Source includes Windows.h
with upper case first letter. On Linux mingw64 calls the header windows.h
with lower case first letter. This fails to compile because Linux is case sensitive. Please use lower case letters for windows header names.
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:
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.
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.
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
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.
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:
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!
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.