[SOLVED] OpenCL context for LwjglCanvas is always null

Hello to the great JmonkeyEngine community. I noticed that LwjglCanvas does not create OpenCL context based on the settings (it is always null) and it never even checks the appSettings to create one in the source code.
In the LwjglDisplay class, there is this line:

At line 150:

        if (settings.isOpenCLSupport()) {
            initOpenCL();
        }

But in LwjglCanvas, it’s missing:

So I added the three lines of OpenCL above to the line 480 in “createContext(AppSettings settings)” function, inside the try/catch after the “Display.create” call.

My Question: Since I’m an utter beginner in OpenCL, I wanted to know if there was a reason for not putting the OpenCL in LwjglCanvas or it was just a mistake.

I haven’t tested an actual OpenCL code but after the fix, it does make OpenCL context when embeded inside a Java Swing (not null anymore).

Thank you again for the awesome engine.

EDIT: The problem is solved! Look at my reply to understand how the fix worked.

1 Like

@shamanDevel Do you have an answer for Amir?

I could fix the problem. The solution is to add the settings check to the LwjglCanvas class on the createContext function:

if (settings.isOpenCLSupport()) {
      initOpenCL();
}

But the key point is that Canvas starts with a pbuffer instead of a direct Drawable. This means that “createContext” is called more than once. That’s why it takes time for the canvas to appear in the Swing UI (there is also some manual delays too which I don’t know why it exists). When the canvas becomes visible, then the OpenCL context should be made because the OpenCL context will require the OpenGL context ID to communicate with (which is taken from “Display.getDrawable()”). Therefore, the small code has to be added after “Display.create” which means at line 480 in LwjglCanvas in function createContext. If the “initOpenCL()” be called before “Display.create”, then OpenCL won’t be connected to OpenGL.

                if (USE_SHARED_CONTEXT){
                    Display.create(acquirePixelFormat(false), pbuffer);
                }else{
                    Display.create(acquirePixelFormat(false));
                }
                //THE CODE HAS TO BE ADDED HERE
                renderer.invalidateState();

IMPORTANT NOTE
Since the OpenCL context will be created after the canvas is visible in Swing UI, it is impossible to work with OpenCL in the “simpleInitApp” function (unless you severely hack through the code. For instance, you can make the “drawable” in LWJGL public and force equal pbuffer to Display.drawable. Then initialize OpenCL on the first call of “createContext”. Display.drawable is set only in “create” function in Display class. This means hacking through LWJGL itself which can make a lot of problems).

Now, the solution is to simply use a boolean in you app and check in the “simpleUpdate” loop if the “context.getOpenCLContext()” is null or not. When it is not null, then do your initialization of OpenCL.

Refer to sample example “TestVertexBufferSharing”, if you start your OpenGL in window or full screen, you can use “initOpenCL1();” in “simpleInitApp” but if you start OpenGL in canvas in Swing, you need to apply the hack to the source code of LwjglCanvas and use “initOpenCL1();” in the “simpleUpdate” loop with a boolean for initialization.

Side note
Of course if you don’t want to use OpenCL to edit OpenGL data and stuff, you can do the hack in the LwjglCanvas class “At The End Of” function createContext. In this case, your OpenCL won’t be connected to OpenGL and you can use it in “simpleInitApp”. Or you can make OpenCL from scratch in “simpleInitApp”. The whole point of this post was that OpenCL be connected to OpenGL when using canvas and Java Swing.

1 Like

I recently ran into having to add such delays on a jogl project. Apparently some of the operations take some time, and are fire-and-forget, that is the java method returns before the native code gets around to doing it’s job and setting the newly initialized (whatever) back through the callback mechanism.

I believe that the fix should be merged into the source code so I made a pull request. Although as it was discussed here, OpenCL won’t be available in the “simpleInitApp”, this fix is the best I could come up with. If you have a better fix please let me know.
Thank you.

I had similar experience for embedding Java Processing (unfolding maps) into the Java Swing application. It required some delays starting by JavaFX window ending with Swing jPanel in a few seconds. Such delays and hacks usually make the code in renderer initialization functions useless and most of the initializations must be pushed into the rendering loop with a simple boolean variable.