Активировать 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 ES2 (он работает, см. https://github.com/AqD/JOGL-FX)
- JOGL 2.1.5
обходные:
- 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. Я в полном замешательстве.....