vulkano
vulkano copied to clipboard
PushConstants causes ram usage to increase every command buffer
Using a very slightly modified version of triangle example from latest repo (and vulkano 0.10.0 and 0.11.0). Cause ram usage to seemingly infinity increase ram usage.
By pushing a simple identity matrix into the vs shader as a pushconstant https://github.com/lilith645/vulkano/commit/20c7fb0ae766eb51f5723f844d958759eea5d3a7
This has happened on all computers i have been able to test (Both debug and release modes) Ubuntu 18.10 GTX 950m Nvidia Driver 387.92 and 290.87 Ubuntu 18.10 GTX 770oc Nvidia Drive 390 Windows 10 AMD R280
It will fill the ram until system freezes/crashes from running out of ram (Tested up to 12GB).
That is if that my understanding on how to use push_constants should be used, that they are similar to uniform but are allocated every commandbuffer so is good for data that will change every frame such as a transformation matrix and that you are limited to (~128 bytes, approx 32 floats) but has much faster transfer rate than an ordinary uniform buffer.
Thus leading me to believe that the increase in ram usage is unintended.
The validation layers under release spam this output
Validation(ERROR): msg_code: 618662080: [ VUID-vkDestroyFence-fence-01120 ] Object: 0x1e (Type = 7) | Fence 0x1e is in use. The spec valid usage text states 'All queue submission commands that refer to fence must have completed execution' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkDestroyFence-fence-01120)
I cant reproduce on Linux + Nvidia GTX 960, Linux + AMD or Windows + AMD. I left it for at least 5 minutes on all and didnt notice an increase in memory usage. How long does it take to OoM?
Could you possibly be encountering https://github.com/vulkano-rs/vulkano/issues/923 ?
The work around for that, which you could try is adding future.wait(None).unwrap like this https://github.com/rukai/incipisphere_renderer/blob/d8c06451e8dc1c4b63ea4c7fdf682270d16f4cbd/src/render.rs#L309
tldr: future.wait(None).unwrap() with push constants enhances the issues with push_constants
I thought "future.wait(None).unwrap()" was in examples by default for some reason xD
I first experienced this in my own project, which does incorporate future.wait(None).unwrap() work around, as i needed it long time ago vulkano 0.7.0 or something.
Once i remove the push constants it stops leaking (in my project). The rate of the leak is a connected to how many frames you are rendering per second.
Ok so far trial and error with triangle and project it seems the combination of
- Using Push Constants
- Having future.wait(None).unwrap()
On both tests (push constants with future.wait and just push constants) ram usage starts at approximately 20.3mb
Push Constants + future.wait(None).unwrap()
Causes it to leak substantially (5gb in 4min, 20mb/s) https://user-images.githubusercontent.com/11486093/48981153-b7839680-f11d-11e8-95e1-e75128265103.png
As can be seen after approximately 4min it was still running and had taken up 4GB of ram memory.
Push Constants
However without the future.wait(None).unwrap() It does still leak just so much slower here it memory after 4min also (30mb in 4min, 0.12mb/s) https://user-images.githubusercontent.com/11486093/48981210-5a3c1500-f11e-11e8-830d-d6f9350a72cf.png with the version without future.wait(None).unwrap() it seems to take a variable amount of time before it starts leaking, sometimes it as soon as its run, other times after 30seconds, another run was after 5 seconds.
Another note when i had a look at the memory maps, there was a singular anonymous mapped region that had a VM size of 6gb.
Don't have access to other computers to test currently.
Edit: Same across PresentModes Immediate, Fifo and Relaxed (Mailbox not supported) so i don't think its related directly to #923 And I haven't seen and kind of Oom errors. other than pc coming to standstill once all ram is used --release mode is where the leak happens consistently without fail
Edit 2: I just tested on my desktop with fresh install of Ubuntu 18.10 GTX 770, I didn't see any leak with push constants alone with the modified triangle, but when it was run with future.wait(None).unwrap() the issue was present.
I was testing with future.wait(None).unwrap() before and couldn't reproduce it.
After further testing, and thought
I do believe it is part of issue #923 but because my laptop has the Nvidia optimus technology that forces Nvidia to go through the Intel gpu, vulkan believes its using the INTEL-MESA driver, but then picks the GTX770 card for vulkan rendering (only one available with the optimus workaround), so that the memory checks don't apply correctly, thus leading no Oom errors etc. With the main difference being that is still leaks on Immediate mode, but im going to chalk that up to the optimus driver issue.
Output at launch:
INTEL-MESA: warning: Haswell Vulkan support is incomplete
Using device: GeForce GTX 950M (type: DiscreteGpu)
future.wait(None).unwrap(), does fix the issue when no pushconstants are used. But for some reason using push constants breaks the future fix.
Although I do still get a memory leak on my desktop when using both (future.wait(None).unwrap() + PushConstants), where it just uses the standard Nvidia setup provided by Ubuntu 18.10.
I can test later tonight if removing future.wait(None).unwrap(), with the push constants on my desktop still causes the leak.
I'm also running into host memory leaks (~1mb/s) on my GTX 1070 (notably no Optimus) using only a storage CpuAccessibleBuffer, an ImmutableImage and push constants. Valgrind reports memory allocated via push constants as definitely lost:
==70200== 1,015,036 bytes in 187 blocks are definitely lost in loss record 1,455 of 1,455
==70200== at 0x483CB65: calloc (vg_replace_malloc.c:760)
==70200== by 0x633A043: ??? (in /usr/lib/libnvidia-glcore.so.460.32.03)
==70200== by 0x66CC961: ??? (in /usr/lib/libnvidia-glcore.so.460.32.03)
==70200== by 0x66F1433: ??? (in /usr/lib/libnvidia-glcore.so.460.32.03)
==70200== by 0x42423C: vk_sys::DevicePointers::CmdPushConstants (lib.rs:2848)
==70200== by 0x41F0EA: vulkano::command_buffer::sys::UnsafeCommandBufferBuilder<P>::push_constants (sys.rs:1316)
==70200== by 0x2F0EB7: <vulkano::command_buffer::synced::commands::<impl vulkano::command_buffer::synced::base::SyncCommandBufferBuilder<P>>::push_constants::Cmd<Pl> as vulkano::command_buffer::synced::base::Command<P>>::send (commands.rs:1735)
==70200== by 0x28835D: vulkano::command_buffer::synced::base::SyncCommandBufferBuilder<P>::build (base.rs:760)
==70200== by 0x3B0E6E: vulkano::command_buffer::auto::AutoCommandBufferBuilder<P>::build (auto.rs:575)
Using future.wait(None).unwrap() only causes memory to leak more slowly and doesn't seem to fix underlying issues as far as I can tell. Present modes also don't make a difference.
Edit: I replaced the push constants with () and used a CpuBufferPool instead and there are no more leaks. I can also now confirm that push constant leaks do not occur when running on an integrated Intel HD chip
I also found that the pushconstants examples from this repository doesn't leak on my machine
also running into this issue on windows 10 with nvidia rtx 2070 mobile. (intel gpu doesnt leak tho)
this will happen when i add a push constant into triangle example's vertex shader, no matter what i passed to draw().
i tried to play with runtime-shader example with the push constant added into vertex shader same as above and got some results
- add below code only for
VertLayout, no leak.
https://github.com/xyning/vulkano/blob/4c4a6878c8a11ee4bfa5331b3a7a59948a36b415/examples/src/bin/runtime-shader/main.rs#L285-L299 - add them for both
VertLayoutandFragLayout, still no leak but a validation error occurs. - replace both
stages: self.0withstages: ShaderStages::all()(seems this is what vulkano-shader did), the validation error stops and memory starts leaking. - change both
ShaderStages::all()toShaderStages::all_graphics()the leaking stopped for me.
not sure whether this is a nvidia driver bug but i think we need some workarounds as currently push constants is just unusable..
edit: confirmed changing this solved the issue on triangle example for me, but then compute shaders are just broken... https://github.com/vulkano-rs/vulkano/blob/e66e9a1fa21ddc9dde8ddf7a503f64c84cecd7b8/vulkano-shaders/src/descriptor_sets.rs#L123
Tried to reproduce on Windows 10 with NV 1080 Ti (driver 527.56), added push constants as illustrated by https://github.com/lilith645/vulkano/commit/20c7fb0ae766eb51f5723f844d958759eea5d3a7 (using https://github.com/vulkano-rs/vulkano/commit/10d734955633aad8fe816d5cd12e6f3728749539) , but can not observe a memory leak.