Hi I relatively recently started upgraded to lwjgl3 and I am not quite sure what is the difference between
try(MemoryStack stack=stackPush()){
doSmth(stack.mallocInt(foo));
doSmthElse(stack.mallocInt(bar));
}
and
IntBuffer fooBuf=MemoryUtil.memAllocInt(foo);
doSmth(fooBuf);
fooBuf.free();
IntBuffer barBuf=MemoryUtil.memAllocInt(foo);
doSmthElse(barBuf);
barBuf.free();
From my understanding they are the same except the second one causes a memory leak in a case of exception.
Also is it a good idea to wrap native buffers in my class that on finalize makes sure that the free function is called on buffer?
Automatic cleanup is one difference, indeed. We cannot add AutoCloseable to the NIO buffer classes, so they can't be used with try-with-resources.
But the major difference is performance:
The MemoryUtil methods call the native memory allocator and each allocation & deallocation has considerable overhead, depending on the implementation. LWJGL provides bindings to 3 allocators: system default, jemalloc (faster on Linux & macOS), rpmalloc (fastest, but requires per-thread setup).
The MemoryStack is pure Java code that returns slices out of a pre-allocated, thread-local, fixed-size memory block. A stack allocation simply increments a pointer, with proper alignment, and returns a buffer object. Popping the stack is basically two instructions (happens automatically at the end of the try-with-resources block). The drawback? The stack size cannot grow (defaults to 64kb, can be statically changed with Configuration.STACK_SIZE), so it's only good for small, short-lived buffers (which are very common actually).
Read the Memory FAQ (https://github.com/LWJGL/lwjgl3-wiki/wiki/1.3.-Memory-FAQ) for more information.
Ooooh! That explains a lot!
So basically, I should use stacks for simple things like getting a value from functions (aka replacement for c++ pointers) but not for things like handling high poly model data or data that I want to keep around after the function call.
Yes, exactly.