-->

dimanche 20 juillet 2014

vendredi 11 juillet 2014

Linux Hybrid Graphics : INTEL HDGraphics Display and AMD Radeon Headless OpenCL

My goal is to run xorg on my integrated INTEL HD200 card, wired to a monitor, while running OpenCL applications on my PCIe AMD Radeon HD6670, whith no monitor attached.
I am writing this post while I am testing.

Setup:


Debian wheezy amd64

Kernel : 3.15.5

Card0: Intel HDGraphics 2000
Driver : from Wheezy

Card1 : Radeon HD 6770
Driver : Catalyst 14.4

I use Lightdm as my DisplayManager

AMD APP SDK not installed, Catalyst provides libOpenCL, clinfo, libamdocl64, ...

Preambule :


Ensure my software installation is OK :
  • ensure I can have xorg running on Card0
  • ensure I can have xorg running on Card1
For this, I need to have 2 xorg.conf files, one per card. 

From this point I have interesting results :
  • xorg on Card0 : from an xterm, clinfo sees only one cl device : INTEL corei3
  • xorg on Card1 : from an xterm, clinfo sees two devices : INTEL corei3 and AMD GPU

1 : one xserver and two drivers simultaneaously


This leads to the proprietary libs problem :
  • Intel driver uses opensource libs ( libGL, etc )
  • AMD driver uses its own libs ( libGL, libglx, libGLEW )
So the 2 drivers loaded in the same xorg server is impossible ( leads to segfaults )

2 : An interesting thing

  

2.1 by accident

As I was testing, I was lead to boot on recovery mode ; and this is what I've found :
As root on recovery console , I run clinfo ; and magically clinfo sees two devices : INTEL corei3 and AMD GPU. Xorg is not started at this point.And fglrx throw me some logs directly in the console :

FireGL : Kernel Thread PID ...
IRQ 47 enabled
Reserved FB Block : shared ...
Reserve FB Block : unshared ...
 
After closing the recovery console, boot process continues, I log in and  :
  • clinfo still sees my two cl devices in a tty ( Ctrl + Alt + F1 )
  • clinfo segfault in an xterm

I run :
in tty1 : strace clinfo > clinfo.tty.txt 2>&1
in xterm : strace clinfo > clinfo.xterm.txt 2>&1

And use meld on the log files  ; basically the main difference is that at one point :
  • in tty1 clinfo open /dev/ati/card0
  • in xterm clinfo try to connect to the xserver, then segfaults.

Edit : this is because the environment variable COMPUTE is not defined. 
export COMPUTE=:i 
( where i is the number of your xorg server ) resolves this issue ; but only the CPU device is seen.

At this point, am I able to run a true OpenCl application on virtual tty1 whereas xorg runs ?
The response is : YES :)

I take a simple "hello world" OpenCL program, modify it to ensure it will select a CL_DEVICE_TYPE_GPU, and its OK. BUT...

2.2 root / non-root

...I have to execute it as root ; as a normal user, it sees no devices at all.

So lets investigate that ; I do

    #./helloworld > sample.root.log 2>&1 
    $./helloworld > sample.root.log 2>&1

Then a meld on the log files shows two ioctl() problems :
    ioctl(5, 0xc0586450, 0x7fffae16dba0)    = -1 EACCES (Permission denied)
    ioctl(6, 0x80146454, 0x7fffae16dc90)    = -1 EACCES (Permission denied) 
 After googling ioctl(), I found that the interesting part of the command is the lower 16-bits word of the 2nd parameter, so I googled ioctl 0x6450 and got this :
    {"drm/radeon_drm.h",    "DRM_IOCTL_RADEON_CMDBUF",      0x6450},
    {"drm/radeon_drm.h",    "DRM_IOCTL_RADEON_FREE",        0x6454},
Further investigations leads to this:
DRM_IOCTL_DEF_DRV(ioctl, func, flags)
... 
flags is a bitmask combination of the following values. It restricts how the ioctl is allowed to be called.
      DRM_AUTH - Only authenticated callers allowed
      DRM_MASTER - The ioctl can only be called on the master file handle
      DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
      DRM_CONTROL_ALLOW - The ioctl can only be called on a control device
      DRM_UNLOCKED - The ioctl handler will be called without locking the DRM global mutex
Due to the possibility of DRM_ROOT_ONLY call, I get aroud the problem for the moment by setting setuid bit :
    #chown root:root helloworld
    #chmod o=rwx helloworld
    #chmod u+s helloworld

this lead me to try this :

2.3 normal user on AMD only xserver( which is not the goal )

It works perfectly !

3 : Back to main goal


  • Section 2 seems to indicate that an OpenCL app has to connect to Xserver to run, and not connect directly ( i.e. via OpenCL SKD ) to drm devices
  • Section 1 proove that one xserver can not achieve this
So lets try two xservers ?

OK, but instead of having one xserver needing access to two different versions of some libraries ( libGL.so for exmaple ), I shall have two xservers needing access to two different versions of some libraries ! Solution ?

  • using LD_PRELOAD or LD_LIBRARY_PATH  : for instant it does not work, and I'm afraid of some hard-coded file loadings in the graphical stack.
  • using a chroot ( more later... )
I finally succeeded in running simultaneously :
  • one xorg with Card0 on a monitor, in my standard environment, with OpenGL enabled, and even Compiz. I name this display :0
  • one xorg with Card1 without monitor ( VGA & HDMI connectors empty ) , in a chrooted environment. I name this display :1 



But for instant doing 
#export COMPUTE=:1
#clinfo
in the chrooted environment just stucks, either on a tty console or a xterm on display :0 ( more later... )

4 : Finally


The only way I found to run OpenCL apps on my Radeon HD6670 while displaying my usual stuff on my HDGraphics 2000 is to run the app as root on a tty, as mentionned in 2.1.

n.b. : One last thing, if I run the OpenCl app in a tty, while no xorg server is running ( /etc/init.d/your-display-manager stop ), my 2 devices are seen.

Hope this can help others in hybrid graphics configs.