Create buffer on GPU

Hello jmonkeys,

i recently stumbled upon OpenCL and read that i can bind vertex buffers so i can write into them via opencl kernels.
this all works and seriously is totally awesome but i cannot figure out one last thing that could improve performance quite a bit.

The data i need in my index and vertex buffers will be calculated in an opencl kernel. i know their sizes already and since openCL requires them to exist on GPU already, i need to create those vertexbuffers and use them in a geometry that i can render then. this however means that all those 0’s get send to GPU just so in the next frame i can run my kernel and write the actual data into them.

all i want to do is tell openGL to create some buffers of specific size without sending that amount of data. is this possible or would i need to fork the engine because some stuff is hidden?

in case i can tell openGL to create buffers without sending all that data, can i ensure the buffers are actually created when i want to use them in the kernel? i guess the drawcalls etc are non blocking, could i just call that buffer generation at the start of a frame in a blocking way and that would not result in waiting for all drawcalls?

Thanks in advance and many greetings from the shire,
samwise

Yes you are right, jme doesn’t expose it… but it’s actually pretty easy to obtain access to the gl apis

 // In your SimpleApplication
     try{
            // Get GL apis from the GLRenderer
            Field gl_f=getRenderer().getClass().getDeclaredField("gl");
            gl_f.setAccessible(true);
            GL gl= (GL) gl_f.get(getRenderer());

            // Create new buffer
            IntBuffer ib=BufferUtils.createIntBuffer(1);
            gl.glGenBuffers(ib);

            int bufId=ib.get(0);
            System.out.println("Buffer id "+bufId);

            // Bind buffer
            gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId);

            // Reserve 100 bytes of data
            gl.glBufferData(GL.GL_ARRAY_BUFFER, 100, GL.GL_DYNAMIC_DRAW);

        }catch(Exception e){
            e.printStackTrace();
        }

Just be sure to know what you are doing, because it’s easy to break the engine in this way.

2 Likes

You can do what @RiccardoBlb said, but also consider that if the buffers are not too large and if you can keep them around for many frames (buffers are rarely created), then the performance impact of using jME’s API to create zeroed buffers should be negligible. Creating them will be slower (probably by a lot) compared to creating them with OpenGL directly, so this is a classic performance-vs-maintainability design question. I personally tend to favor maintainability.

thanks both for your answers!
the reason i want to do this is i create my geometry procedurally (chunks etc) and not having those index and vertex buffers in memory at all, only on GPU might reduce memory footprint by quite a bit and considering i somewhen usually need to send all chunks to GPU, i now can skip sending quite a lot alltogether
no im not using collideWith etc, but i realized i also have to set needUpdate to false (otherwise the data will be send nontheless and i also need to set the 0-sized index buffers limit to whatever my indexCount is so GLRenderers drawTriangleList can actually draw something (it calls gl.glDrawRangeElements with indexBuf.getData().limit() to tell how many to draw)
also, that buffer is not registered with the nativeObjectManager, but i can do that via reflection too i guess

It looks super hacky currently but it works, i can create buffers without sending the actual data, fill it via a openCL kernel and then see it on screen (takes like 150ms to mesh a 256x256x256 region including everything)
whats also awesome about this is that i can do it in one frame, like i dont have to wait for the renderer to render it and thus send the data (ofc 150ms is too much for a frame but im still playing around with it)

i didnt actually do it for the performance or anything, more for practice, and now im wondering a little more about the backgrounds:
i know the basic update loop, but when issuing all those drawcalls etc, i assume its all non blocking? then at the end of a frame we swap buffers and this method blocks until all drawcalls that were issued for that buffer (like those from the last frame actually) are done, then swaps the buffers, shows the finished buffer on screen and starts working on the current frame, while the updateloop starts from the beginning and sends the drawcalls for the 3rd frame. is this correct?

does it mean there is no best time to run the kernel? or would it be reasonable to start the kernel at the very beginning of a frame because the GPU might be not that busy then?
or in other words, what are the tools i have to control what runs when on the GPU? is there something for OpenGL like the CommandQueue in OpenCL?

thanks again a lot for your answers, its always enlightening

I haven’t personally done anything with OpenCL + OpenGL running together, but I’ve heard that getting them to play nicely (utilize the GPU without contention) can be pretty tricky. Newer versions of OpenGL (I’m the OpenGL 4+ family) do have command queues and things of that nature, but I couldn’t tell you exactly which version added support for that sort of thing. If you’re on new OpenGL, you’ll likely be far better off doing what you described with OpenGL compute shaders than with mixing OpenGL + OpenCL.

roflmaocopterlol
does jme support compute shaders? like i found the tessellation shader test, played around with it and now use this for my terrain, found out about geometry shaders, use them for my grass approach and then read in the internet about compute shaders but couldnt the heck find any examples for jme, only openCL kernels so i thought jme only supports that.
is there some super basic matdef and compute shader example around that i missed? i would be super happy to absorb that too

well if the engine lacks it and i could think of a usage i might as well just do it in a jme-like design and contribute it. ill read some about this and play around, in case you have any design in mind id be happy to hear about it otherwise ill see what i can make :smiley:

1 Like

So far as I know, jME currently does not support compute shaders. Some time ago I looked into what it would take to add them, and my recollection is that adding new shader types is pretty straightforward. My guess is you wouldn’t have a hard time coming up with a contribution that the core devs would accept, if you’re so inclined. :smiley: