Search code examples
javaintellij-ideaopencllwjgl

LWJGL finding different OpenCL installation when runing outside of IDE


I've been using java in IntelliJ as a hobby for quite some time and have decided to start using OpenCL for parallel computing. I'm pretty sure that I've made no mistake downloading and adding the LWJGL library to my project, since it does always compile. The problem is that when I run the program, it produces this output:

Platforms found: 1
Treating platform 140038554960288
    Platform name: Clover 
    Platform vendor: Mesa 
    Platform version: OpenCL 1.1 Mesa 20.1.5 
Error: -1
Exception in thread "main" java.lang.AssertionError: -1
    at ch.test.Test1.devices_gpu(Test1.java:71)
    at ch.test.Test1.treatPlatform(Test1.java:22)
    at ch.test.Test1.main(Test1.java:94)

The program checks each return of the OpenCL functions using assert and crashes when one does not return CL_SUCCESS. The error here is CL_DEVICE_NOT_FOUND.

When I export the project as a jar and run it inside my IDE, it produces the same output. However, if I copy the command issued (/home/user/Downloads/jdk-14.0.2/bin/java -ea -Dfile.encoding=UTF-8 -jar /home/user/IdeaProjects/LWJGLTest/out/artifacts/LWJGLTest_jar/LWJGLTest.jar) to the console and run the jar there, it gives me the following (expected) output:

user@user-desktop:~$ /home/user/Downloads/jdk-14.0.2/bin/java -ea -Dfile.encoding=UTF-8 -jar /home/user/IdeaProjects/LWJGLTest/out/artifacts/LWJGLTest_jar/LWJGLTest.jar
Platforms found: 1
Treating platform 140169617041680
    Platform name: NVIDIA CUDA
    Platform vendor: NVIDIA Corporation
    Platform version: OpenCL 1.2 CUDA 10.2.178
Error: 0
1
    Devices found: 1
        Name: GeForce GTX 1080

I used the clinfo to see which OpenCL platforms my computer finds:

user@user-desktop:~$ clinfo
Number of platforms                               1
  Platform Name                                   NVIDIA CUDA
  Platform Vendor                                 NVIDIA Corporation
  Platform Version                                OpenCL 1.2 CUDA 11.0.228
  Platform Profile                                FULL_PROFILE
  Platform Extensions                             cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll cl_nv_copy_opts cl_nv_create_buffer cl_khr_int64_base_atomics cl_khr_int64_extended_atomics
  Platform Extensions function suffix             NV

  Platform Name                                   NVIDIA CUDA
Number of devices                                 1
  Device Name                                     GeForce GTX 1080
...

Interestingly, when I change drivers (from the opensource to the proprietary and vice-versa), the clinfo temporarily finds no platforms (until I reboot of course), but in IntelliJ, the code produces the same output (and finds a platform when none is installed!), while when run in a jar no platform is found.

I have tried several different JRE, but none work in IntelliJ. I have also tried changing the classpath, but nothing seems to work.

This is all under Linux Mint 19. When I do the same on my Laptop with Windows, there are no issues and everything works fine. The code used to test:

package ch.test;

import org.lwjgl.PointerBuffer;
import org.lwjgl.opencl.CL22;

import java.nio.ByteBuffer;

public class Test1 {

    static int getNumOfPlatforms() {
        int[] buffer = new int[1];
        int error = CL22.clGetPlatformIDs(null, buffer);
        assert error == CL22.CL_SUCCESS;
        return buffer[0];
    }

    static void treatPlatform(long plat) {
        System.out.println("\tPlatform name: " + getPlatformParam(plat, CL22.CL_PLATFORM_NAME));
        System.out.println("\tPlatform vendor: " + getPlatformParam(plat, CL22.CL_PLATFORM_VENDOR));
        System.out.println("\tPlatform version: " + getPlatformParam(plat, CL22.CL_PLATFORM_VERSION));

        PointerBuffer devices = devices_gpu(plat);
        System.out.println("\tDevices found: " + devices.capacity());
        while(devices.hasRemaining()) {
            treatDevice(devices.get());
        }
    }


    static void treatDevice(long device) {
        System.out.println("\t\tName: " + deviceProperty(device, CL22.CL_DEVICE_NAME));
    }

    static String deviceProperty(long device, int prop) {
        PointerBuffer length = PointerBuffer.allocateDirect(1);
        CL22.clGetDeviceInfo(device, prop, (long[])null, length);

        ByteBuffer value = ByteBuffer.allocateDirect((int)length.get());
        CL22.clGetDeviceInfo(device, prop, value, null);
        StringBuilder builder = new StringBuilder(value.capacity());

        for(int i = 0; i < builder.capacity(); i++){
            builder.append((char)value.get());
        }

        return builder.toString();
    }

    static String getPlatformParam(long plat, int attr) {
        PointerBuffer length = PointerBuffer.allocateDirect(1);
        CL22.clGetPlatformInfo(plat, attr, (long[])null, length);

        ByteBuffer value = ByteBuffer.allocateDirect((int)length.get());
        CL22.clGetPlatformInfo(plat, attr, value, null);
        StringBuilder builder = new StringBuilder(value.capacity());

        for(int i = 0; i < builder.capacity(); i++){
            builder.append((char)value.get());
        }

        return builder.toString();
    }

    static PointerBuffer devices_gpu(long plat) {
        int error;
        int[] amount = new int[]{-1};
        error = CL22.clGetDeviceIDs(plat, CL22.CL_DEVICE_TYPE_ALL, null, amount);
        System.out.println("Error: " + error);
        assert error == CL22.CL_SUCCESS: error;
        
        System.out.println(amount[0]);

        PointerBuffer devices = PointerBuffer.allocateDirect(amount[0]);
        error = CL22.clGetDeviceIDs(plat, CL22.CL_DEVICE_TYPE_ALL, devices, (int[])null);
        assert error == CL22.CL_SUCCESS: error;

        return devices;
    }

    public static void main(String[] args) {
        int error;

        int amountOfPlatforms = getNumOfPlatforms();
        System.out.println("Platforms found: " + amountOfPlatforms);
        PointerBuffer platforms = PointerBuffer.allocateDirect(amountOfPlatforms);
        error = CL22.clGetPlatformIDs(platforms, (int[])null);
        assert error == CL22.CL_SUCCESS;

        while(platforms.hasRemaining()) {
            long plat = platforms.get();
            System.out.println("Treating platform " + plat);
            treatPlatform(plat);
        }
    }
}

Solution

  • While I did not find the exact problem, I solved it by reinstalling IntelliJ from their website. It seems that my previous installation done by the Linux Mint Software Manager was faulty. Everything is showing up fine now Thanks for reading and helping though