vulkan-renderer
vulkan-renderer copied to clipboard
Create the next generation of memory management code based on Vulkan Memory Allocator.
VMA is a great library in my opinion because it abstracts memory management in Vulkan. I don't think we invest the time to develop our own memory management library since VMA is battle tested (it is used in some AAA titles).
However, I think we're not using VMA correctly. Adam Sawicki suggests to manage memory by allocating blocks of e.g. 256 MB and then to sub-allocate from it. I think VMA can already do this for us, but I'm not sure we're telling VMA to do so correctly. Maybe we need to specify memory pools for certain resources like textures, meshes and so on.
Memory recycling
Memory allocation/freeing is a very expensive operation! The best practise is to allocate all memory required upfront, during the initialisation routine. I think we do a good job so far with that. However, we don't have any plan on how to recycle memory correctly!
Imagine we're loading a big mesh into video memory. We need to allocate a big block of memory for this mesh. Now imagine we're not using it anymore. Should we free the memory? No! Use it for other resources! What is we're loding another mesh now which is smaller (or of equal size) compared with the initial resource? We can just use the memory that has is no longer used for the old mesh.
If we really need to allocate memory at runtime we should do so in a separate thread. The same goes for stuff like command buffer recording btw.
I really like NVidia's resource Vulkan Dos and Don’ts as a reference.
Centralizing buffer management
So far, every manager class has it's own create_buffer method. I didn't want to refer to a manager class for bufer creation in every manager class until now. But we really should centralize memory management in the engine. This would make memory recycling easier.
Memory aliasing
Another interesting topic is to use the same memory for 2 resources if their lifetime doesn't overlap. I don't think we're at this stage yet, but in theory we could send a texture for rendering to the GPU and then we could use the same memory for sending some data back from GPU to CPU or something like that.
It would be very interesting in how far a frame graph could automate this memory aliasing as it could take a look at resource lifetime automatically. But that is another topic for the future.
Memory defragmentation
Another topic for the future is buffer fragmentation. VMA comes with defragmentation functionality which help to clean this up.
Memory mapping
Do we need to keep memory mapped all the time? Are there benefits from unmapping it?
https://www.youtube.com/watch?v=ifmW3lOA6CA
https://www.youtube.com/watch?v=6NWfznwFnMs
https://www.youtube.com/watch?v=zSG6dPq57P8
We could consider using a frame graph. This would let us see which resources can be aliased (recycled), and insert an optimal amount of barriers. It would also work very well with the job system.
Anoher thing I noticed is that on some systems there are special memory regions which we could use explicitely. I'm not sure in how far VMA does this by default, but I would guess it surely does, given the fact it's developed my AMD mainly.
So AMD usually has 256 MB which is both DEVICE_LOCAL and HOST_VISIBLE:
https://youtu.be/rXSdDE7NWmA?t=322
"Good for resource supdated freuently by CPU (dynamic), read by GPU."
Also, some platforms have completely unified memory: https://youtu.be/rXSdDE7NWmA?t=437 https://community.khronos.org/t/feature-matching-with-vulkan/106113/2
I will close this issue for several reasons. First, I think we are doing a good job by using VMA in the first place. Second, the scope of this issue is much too wide. Third, I believe advanced memory techniques such as aliasing is something for the far future.