在 Java/OpenGL 下激活 nVIDIA Optimus?

Posted

技术标签:

【中文标题】在 Java/OpenGL 下激活 nVIDIA Optimus?【英文标题】:Activate nVIDIA Optimus under Java/OpenGL? 【发布时间】:2014-10-11 15:14:08 【问题描述】:

我知道它已经被问了好几次都没有明确的答案,而且我已经向 nVIDIA 提交了一个错误。但是,我仍然在寻找比在 Prism-D3D 引擎中启动 JavaFX 更好的解决方法(它立即允许通过 nVIDIA 创建后续的 OpenGL 上下文)。

环境:

nVIDIA 860m,驱动 337.88、340.43、340.66(四驱) Java 8u11(也测试了 x86/x64 和 Java 7)

测试失败:

nVIDIA 配置文件 NvOptimusEnablement(用 C 编写的自定义启动器) 首先调用 OpenCL(用 C 编写的自定义启动器) 首先调用 Cuda(JCuda,它实际上显示 nVIDIA 名称,但 OpenGL 不受影响)

失败的 API:

JavaFX8 ES2 管道(它确实起作用,请参阅https://github.com/AqD/JOGL-FX) JOGL 2.1.5

解决方法:

JavaFX8 D3D 管道。在 D3D 初始化工作后创建的所有 GLContext。

我将问题归结为一个非常简单的示例,调用 realtech-vr OpenGL Extension Viewer(用 .NET 编写)。里面有一个原生的“infogl.dll”,它读取 GL 信息,显然在 oevClientInitialize 之后立即激活 Optimus。

奇怪的是,调用 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();

但是 JNA 编写的 Java 中的相同代码没有

    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 解决方案不合适,因为它在 AMD Radeon 芯片上将 OpenGL FPS 降低了一半 - 我认为这在 nVIDIA 芯片上肯定同样糟糕,这就是为什么我试图让它与 ES2 管道一起使用。

【问题讨论】:

回答我自己:将 Windows 从 8 升级到 8.1,或从 2012 升级到 2012 R2 立即解决问题,无论使用的硬件或 nVIDIA 驱动程序版本或 Intel GFX 驱动程序版本如何。 【参考方案1】:

从 .NET 启动 JVM 显然可行(通过 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!
    

我还没有找到在.NET下激活Optimus的真正原因......但是很可能相同代码的C / C ++不起作用,因为它正是Java版本所做的(JNI调用)

PS:我刚刚验证了“OpenTK”(OpenGL 的.NET 包装器)也无法激活 Optimus。我完全糊涂了.....

【讨论】:

以上是关于在 Java/OpenGL 下激活 nVIDIA Optimus?的主要内容,如果未能解决你的问题,请参考以下文章

在Windows 10(Win10)下安装“NVIDIA图形驱动程序”“NVIDIA控制面板”CUDA ToolkitcuDNN Archive的详细过程记录

可以在没有 GPU 的情况下运行 nvidia-docker 吗?

Linux下监视NVIDIA的GPU使用情况(转)

Linux下如何查看NVIDIA显卡信息

在没有 NVIDIA GPU 的情况下使用 CUDA? [复制]

Ubuntu下apt工具包安装NVIDIA driver