Fix: EEVEE renders with CPU instead of GPU in Linux clients (#229)

* Fix: EEVEE renders with CPU instead of GPU in Linux clients

In Linux systems, setting the env LD_LIBRARY_PATH var to point the /lib folder included in the sheepit binary compressed .zip, mandates Blender to swap whatever openGL library is already in use by the OS. Modern GPU drivers install their own optimised version of the OpenGL library and replacing it creates incompatibilities that avoid EEVEE to run.

To detect if Blender already uses the standard OS provided OpenGL library is via _ldd_ Linux command. The execution in a system with OpenGL libraries already in use delivers an output similar to this:

ldd rend.exe
	linux-vdso.so.1 (0x00007ffda6bf9000)
	...
	libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007fefefe3a000)
	libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007fefefc30000)
	libGL.so.1 => /lib/x86_64-linux-gnu/libGL.so.1 (0x00007fefefb9c000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fefefa4d000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fefef85c000)
	...
	libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fefef6e7000)

While a system with no OS OpenGL libraries that requires the shipped default OpenGL lib to work returns this instead:

ldd rend.exe
	linux-vdso.so.1 (0x00007ffda6bf9000)
	...
	libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007fefefe3a000)
	libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007fefefc30000)
	libGL.so.1 => not found
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fefefa4d000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fefef85c000)
	...
	libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fefef6e7000)

In the former case, the SheepIt client will set the LD_LIBRARY_PATH env var to point the /lib folder to allow Blender to execute properly.
This commit is contained in:
Luis Uguina
2020-05-25 06:12:02 +10:00
committed by GitHub
parent 90651fafe8
commit 1dc865a979

View File

@@ -18,7 +18,9 @@
*/
package com.sheepit.client.os;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
@@ -152,11 +154,13 @@ public class Linux extends OS {
@Override
public Process exec(List<String> command, Map<String, String> env_overight) throws IOException {
// the renderer have a lib directory so add to the LD_LIBRARY_PATH
// (even if we are not sure that it is the renderer who is launch
Map<String, String> new_env = new HashMap<String, String>();
new_env.putAll(java.lang.System.getenv()); // clone the env
// if Blender is already loading an OpenGL library, don't need to load Blender's default one (it will
// create system incompatibilities). If no OpenGL library is found, then load the one included in the binary
// zip file
if (isOpenGLAreadyInstalled(command.get(0)) == false) {
Boolean has_ld_library_path = new_env.containsKey("LD_LIBRARY_PATH");
String lib_dir = (new File(command.get(0))).getParent() + File.separator + "lib";
@@ -166,6 +170,7 @@ public class Linux extends OS {
else {
new_env.put("LD_LIBRARY_PATH", new_env.get("LD_LIBRARY_PATH") + ":" + lib_dir);
}
}
List<String> actual_command = command;
if (this.hasNiceBinary == null) {
@@ -228,4 +233,45 @@ public class Linux extends OS {
}
}
}
protected boolean isOpenGLAreadyInstalled(String pathToRendEXE) {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("bash", "-c", "ldd '" + pathToRendEXE + "'"); // support for paths with an space
processBuilder.redirectErrorStream(true);
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
StringBuilder screenOutput = new StringBuilder();
while ((line = reader.readLine()) != null) {
// check the shared libraries that Blender is loading at run time. If it already loads an existing
// version of OpenGL (ie the one shipped with NVIDIA drivers) then return false to avoid the client
// replacing them (and glitching the EEVEE render). Otherwise return true and load the /lib folder
// to ensure that Blender works correctly
if (line.toLowerCase().contains("libgl.so")) {
return !line.toLowerCase().contains("not found");
}
// In case of error we can later check the screen output from ldd
screenOutput.append(line);
}
int exitCode = process.waitFor();
if (exitCode != 0) {
System.err.println(String.format("ERROR Linux::isOpenGLAreadyInstalled Unable to execute ldd command. Exit code %d", exitCode));
System.err.println(String.format("Screen output from ldd execution: %s", screenOutput.toString()));
}
}
catch (IOException e) {
System.err.println(String.format("ERROR Linux::isOpenGLAreadyInstalled Unable to execute ldd command. IOException %s", e.getMessage()));
}
catch (InterruptedException e) {
System.err.println(String.format("ERROR Linux::isOpenGLAreadyInstalled Unable to execute ldd command. InterruptedException %s", e.getMessage()));
}
return false;
}
}