Активировать nVIDIA Optimus под Java/OpenGL?

Я знаю, что его уже несколько раз спрашивали без четкого ответа, и я уже подал ошибку в nVIDIA. Однако я все еще ищу лучший обходной путь, чем запуск JavaFX в движке Prism-D3D (который сразу же позволяет создавать последующий контекст OpenGL через nVIDIA).

Среда:

  • nVIDIA 860m, ​​драйвер 337,88, 340,43, 340,66 (драйвер Quadro)
  • Java 8u11 (также протестированы x86/x64 и Java 7)

Проверено и не удалось:

  • Профиль nVIDIA
  • NvOptimusEnablement (пользовательский модуль запуска, написанный на C)
  • Сначала вызов OpenCL (пользовательский модуль запуска, написанный на C)
  • Сначала вызываю Cuda (JCuda, фактически он показывает имя nVIDIA, но OpenGL остается неизменным)

Неудачные API:

обходные:

  • JavaFX8 D3D конвейер. Весь GLContext создан после инициализации D3D.

Я прибил проблему к очень простому образцу, назвав realtech-vr OpenGL Extension Viewer (написанный на.NET). Внутри есть собственный "infogl.dll", который читает информацию GL и, очевидно, активирует Optimus сразу после oevClientInitialize.

Странность в том, что самая простая консольная программа, вызывающая infogl.dll, работает:

    Win32.oevSetDriverVersion("10.18.10.3621", 2176);
    Win32.oevClientLoadDatabase(File.ReadAllText("C:\\Program Files (x86)\\realtech VR\\OpenGL Extensions Viewer 4.1\\extensions.xml"));
    Win32.oevClientInitialize();
    for (var i = 0; i <= 9; i++)
    {
        var tree = Marshal.PtrToStringAnsi(Win32.oevClientGetCapsAndExtTree(i));
        Console.WriteLine(tree.Split('\n').First(ln => ln.Contains("text_id=\"357\"")));
    }
    Console.ReadLine();

Но тот же код в Java от JNA не делает:

    infogl.INSTANCE.oevSetDriverVersion("10.18.10.3621", 2176);
    String extXml = null;
    try {
        extXml = new String(
                Files.readAllBytes(Paths.get("C:\\Program Files (x86)\\realtech VR\\OpenGL Extensions Viewer 4.1\\extensions.xml")),
                "UTF-8");
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    infogl.INSTANCE.oevClientLoadDatabase(extXml);
    infogl.INSTANCE.oevClientInitialize();
    for (int i = 0; i <= 9; i++)
    {
        String tree = infogl.INSTANCE.oevClientGetCapsAndExtTree(i);
        System.out.println(Arrays.asList(tree.split("\\n")).first(ln -> ln.contains("text_id=\"357\"")));
    }

И это не связано с исполняемым именем "Java" - я пробовал.

Решение JavaFX D3D не подходит, потому что оно вдвое снижает FPS OpenGL на чипах AMD Radeon - я полагаю, что это должно быть так же плохо на чипах nVIDIA, и поэтому я стремлюсь заставить его работать с конвейером ES2.

1 ответ

Запуск JVM из.NET, очевидно, работает (через jni4net). В конце завершения JavaFX происходит сбой в nvoglv64.dll.

using net.sf.jni4net;
using net.sf.jni4net.utils;
...

    public static void Main(string[] args)
    {
        InitializeOpenGL();
        var setup = new BridgeSetup();
        setup.AddClassPath(@"C:\Program Files\Java\jdk1.8.0_11\demo\javafx_samples\Modena.jar");
        setup.AddJVMOption("-Dprism.order=es2");
        setup.AddJVMOption("-Dprism.verbose=true");
        var env = Bridge.CreateJVM(setup);
        java.lang.System.@out.println("Greetings from C# to Java world!");
        Console.WriteLine("Initializing...");
        var klass = env.FindClass("modena/Modena");
        Console.WriteLine("Finding main()...");
        var mainMethodId = klass.getMethods().First(m => m.getName().Equals("main")).GetMethodId();
        Console.WriteLine("Calling main()...");
        env.CallStaticVoidMethod(klass, mainMethodId, Convertor.ParArrayStrongC2JString(env, new string[0]));
        Console.WriteLine("Ended, press enter");
        Console.ReadLine();
    }

    protected static void InitializeOpenGL()
    {
        Win32.oevSetDriverVersion("10.18.10.3621", 2176);
        Win32.oevClientLoadDatabase(File.ReadAllText("C:\\Program Files (x86)\\realtech VR\\OpenGL Extensions Viewer 4.1\\extensions.xml"));
        Win32.oevClientInitialize();
        for (var i = 0; i <= 9; i++)
        {
            var tree = Marshal.PtrToStringAnsi(Win32.oevClientGetCapsAndExtTree(i));
            Console.WriteLine(tree.Split('\n').First(ln => ln.Contains("text_id=\"357\"")));
        }
        // Optimus should be activated by now!
    }

Я еще не нашел реальную причину, по которой Optimus активируется в.NET...... Но вполне вероятно, что C/C++ из того же кода не будет работать, так как это именно то, что делает версия Java (вызывает JNI).

PS: я только что проверил, что "OpenTK" (.NET-оболочка OpenGL) не может активировать Optimus. Я в полном замешательстве.....

Другие вопросы по тегам