264 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
<chapter xmlns="http://docbook.org/ns/docbook"
 | 
						|
         xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
						|
         xmlns:xi="http://www.w3.org/2001/XInclude"
 | 
						|
         version="5.0"
 | 
						|
         xml:id="sec-gpu-accel">
 | 
						|
  <title>GPU acceleration</title>
 | 
						|
 | 
						|
  <para>
 | 
						|
    NixOS provides various APIs that benefit from GPU hardware
 | 
						|
    acceleration, such as VA-API and VDPAU for video playback; OpenGL and
 | 
						|
    Vulkan for 3D graphics; and OpenCL for general-purpose computing.
 | 
						|
    This chapter describes how to set up GPU hardware acceleration (as far
 | 
						|
    as this is not done automatically) and how to verify that hardware
 | 
						|
    acceleration is indeed used.
 | 
						|
  </para>
 | 
						|
 | 
						|
  <para>
 | 
						|
    Most of the aforementioned APIs are agnostic with regards to which
 | 
						|
    display server is used. Consequently, these instructions should apply
 | 
						|
    both to the X Window System and Wayland compositors.
 | 
						|
  </para>
 | 
						|
 | 
						|
  <section xml:id="sec-gpu-accel-opencl">
 | 
						|
    <title>OpenCL</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      <link xlink:href="https://en.wikipedia.org/wiki/OpenCL">OpenCL</link> is a
 | 
						|
      general compute API. It is used by various applications such as
 | 
						|
      Blender and Darktable to accelerate certain operations.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      OpenCL applications load drivers through the <emphasis>Installable Client
 | 
						|
      Driver</emphasis> (ICD) mechanism. In this mechanism, an ICD file
 | 
						|
      specifies the path to the OpenCL driver for a particular GPU family.
 | 
						|
      In NixOS, there are two ways to make ICD files visible to the ICD
 | 
						|
      loader. The first is through the <varname>OCL_ICD_VENDORS</varname>
 | 
						|
      environment variable. This variable can contain a directory which
 | 
						|
      is scanned by the ICL loader for ICD files. For example:
 | 
						|
 | 
						|
      <screen><prompt>$</prompt> export \
 | 
						|
  OCL_ICD_VENDORS=`nix-build '<nixpkgs>' --no-out-link -A rocm-opencl-icd`/etc/OpenCL/vendors/</screen>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The second mechanism is to add the OpenCL driver package to
 | 
						|
      <xref linkend="opt-hardware.opengl.extraPackages"/>. This links the
 | 
						|
      ICD file under <filename>/run/opengl-driver</filename>, where it will
 | 
						|
      be visible to the ICD loader.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The proper installation of OpenCL drivers can be verified through
 | 
						|
      the <command>clinfo</command> command of the <package>clinfo</package>
 | 
						|
      package. This command will report the number of hardware devices
 | 
						|
      that is found and give detailed information for each device:
 | 
						|
    </para>
 | 
						|
 | 
						|
    <screen><prompt>$</prompt> clinfo | head -n3
 | 
						|
Number of platforms  1
 | 
						|
Platform Name        AMD Accelerated Parallel Processing
 | 
						|
Platform Vendor      Advanced Micro Devices, Inc.</screen>
 | 
						|
 | 
						|
    <section xml:id="sec-gpu-accel-opencl-amd">
 | 
						|
      <title>AMD</title>
 | 
						|
 | 
						|
      <para>
 | 
						|
       Modern AMD <link
 | 
						|
       xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics
 | 
						|
       Core Next</link> (GCN) GPUs are supported through the
 | 
						|
       <package>rocm-opencl-icd</package> package. Adding this package to
 | 
						|
       <xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL
 | 
						|
       support:
 | 
						|
 | 
						|
       <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
 | 
						|
         rocm-opencl-icd
 | 
						|
       ];</programlisting>
 | 
						|
      </para>
 | 
						|
    </section>
 | 
						|
 | 
						|
    <section xml:id="sec-gpu-accel-opencl-intel">
 | 
						|
      <title>Intel</title>
 | 
						|
 | 
						|
      <para>
 | 
						|
       <link
 | 
						|
         xlink:href="https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units#Gen8">Intel
 | 
						|
       Gen8 and later GPUs</link> are supported by the Intel NEO OpenCL
 | 
						|
       runtime that is provided by the
 | 
						|
       <package>intel-compute-runtime</package> package. For Gen7 GPUs,
 | 
						|
       the deprecated Beignet runtime can be used, which is provided
 | 
						|
       by the <package>beignet</package> package. The proprietary Intel
 | 
						|
       OpenCL runtime, in the <package>intel-ocl</package> package, is
 | 
						|
       an alternative for Gen7 GPUs.
 | 
						|
      </para>
 | 
						|
 | 
						|
      <para>
 | 
						|
       The <package>intel-compute-runtime</package>, <package>beignet</package>,
 | 
						|
       or <package>intel-ocl</package> package can be added to
 | 
						|
       <xref linkend="opt-hardware.opengl.extraPackages"/> to enable OpenCL
 | 
						|
       support. For example, for Gen8 and later GPUs, the following
 | 
						|
       configuration can be used:
 | 
						|
 | 
						|
      <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
 | 
						|
        intel-compute-runtime
 | 
						|
      ];</programlisting>
 | 
						|
 | 
						|
      </para>
 | 
						|
    </section>
 | 
						|
  </section>
 | 
						|
 | 
						|
  <section xml:id="sec-gpu-accel-vulkan">
 | 
						|
    <title>Vulkan</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      <link xlink:href="https://en.wikipedia.org/wiki/Vulkan_(API)">Vulkan</link> is a
 | 
						|
      graphics and compute API for GPUs. It is used directly by games or indirectly though
 | 
						|
      compatibility layers like <link xlink:href="https://github.com/doitsujin/dxvk/wiki">DXVK</link>.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
     By default, if <xref linkend="opt-hardware.opengl.driSupport"/> is enabled,
 | 
						|
     <package>mesa</package> is installed and provides Vulkan for supported hardware.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Similar to OpenCL, Vulkan drivers are loaded through the <emphasis>Installable Client
 | 
						|
      Driver</emphasis> (ICD) mechanism. ICD files for Vulkan are JSON files that specify
 | 
						|
      the path to the driver library and the supported Vulkan version. All successfully
 | 
						|
      loaded drivers are exposed to the application as different GPUs.
 | 
						|
      In NixOS, there are two ways to make ICD files visible to Vulkan applications: an
 | 
						|
      environment variable and a module option.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The first option is through the <varname>VK_ICD_FILENAMES</varname>
 | 
						|
      environment variable. This variable can contain multiple JSON files, separated by
 | 
						|
      <literal>:</literal>. For example:
 | 
						|
 | 
						|
      <screen><prompt>$</prompt> export \
 | 
						|
  VK_ICD_FILENAMES=`nix-build '<nixpkgs>' --no-out-link -A amdvlk`/share/vulkan/icd.d/amd_icd64.json</screen>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The second mechanism is to add the Vulkan driver package to
 | 
						|
      <xref linkend="opt-hardware.opengl.extraPackages"/>. This links the
 | 
						|
      ICD file under <filename>/run/opengl-driver</filename>, where it will
 | 
						|
      be visible to the ICD loader.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The proper installation of Vulkan drivers can be verified through
 | 
						|
      the <command>vulkaninfo</command> command of the <package>vulkan-tools</package>
 | 
						|
      package. This command will report the hardware devices and drivers found,
 | 
						|
      in this example output amdvlk and radv:
 | 
						|
    </para>
 | 
						|
 | 
						|
    <screen><prompt>$</prompt> vulkaninfo | grep GPU
 | 
						|
                GPU id  : 0 (Unknown AMD GPU)
 | 
						|
                GPU id  : 1 (AMD RADV NAVI10 (LLVM 9.0.1))
 | 
						|
     ...
 | 
						|
GPU0:
 | 
						|
        deviceType     = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
 | 
						|
        deviceName     = Unknown AMD GPU
 | 
						|
GPU1:
 | 
						|
        deviceType     = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU</screen>
 | 
						|
 | 
						|
    <para>
 | 
						|
      A simple graphical application that uses Vulkan is <command>vkcube</command>
 | 
						|
      from the <package>vulkan-tools</package> package.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <section xml:id="sec-gpu-accel-vulkan-amd">
 | 
						|
      <title>AMD</title>
 | 
						|
 | 
						|
      <para>
 | 
						|
       Modern AMD <link
 | 
						|
       xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics
 | 
						|
       Core Next</link> (GCN) GPUs are supported through either radv, which is
 | 
						|
       part of <package>mesa</package>, or the <package>amdvlk</package> package.
 | 
						|
       Adding the <package>amdvlk</package> package to
 | 
						|
       <xref linkend="opt-hardware.opengl.extraPackages"/> makes both drivers
 | 
						|
       available for applications and lets them choose. A specific driver can
 | 
						|
       be forced as follows:
 | 
						|
 | 
						|
       <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
 | 
						|
         pkgs.<package>amdvlk</package>
 | 
						|
       ];
 | 
						|
 | 
						|
       # To enable Vulkan support for 32-bit applications, also add:
 | 
						|
       <xref linkend="opt-hardware.opengl.extraPackages32"/> = [
 | 
						|
         pkgs.driversi686Linux.<package>amdvlk</package>
 | 
						|
       ];
 | 
						|
 | 
						|
       # For amdvlk
 | 
						|
       <xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES =
 | 
						|
          "/run/opengl-driver/share/vulkan/icd.d/amd_icd64.json";
 | 
						|
       # For radv
 | 
						|
       <xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES =
 | 
						|
         "/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";
 | 
						|
       </programlisting>
 | 
						|
      </para>
 | 
						|
    </section>
 | 
						|
  </section>
 | 
						|
 | 
						|
  <section xml:id="sec-gpu-accel-common-issues">
 | 
						|
   <title>Common issues</title>
 | 
						|
 | 
						|
   <section xml:id="sec-gpu-accel-common-issues-permissions">
 | 
						|
    <title>User permissions</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
     Except where noted explicitly, it should not be necessary to
 | 
						|
     adjust user permissions to use these acceleration APIs. In the default
 | 
						|
     configuration, GPU devices have world-read/write permissions
 | 
						|
     (<filename>/dev/dri/renderD*</filename>) or are tagged as
 | 
						|
     <code>uaccess</code> (<filename>/dev/dri/card*</filename>).  The
 | 
						|
     access control lists of devices with the <varname>uaccess</varname>
 | 
						|
     tag will be updated automatically when a user logs in through
 | 
						|
     <command>systemd-logind</command>. For example, if the user
 | 
						|
     <emphasis>jane</emphasis> is logged in, the access control list
 | 
						|
     should look as follows:
 | 
						|
 | 
						|
     <screen><prompt>$</prompt> getfacl /dev/dri/card0
 | 
						|
# file: dev/dri/card0
 | 
						|
# owner: root
 | 
						|
# group: video
 | 
						|
user::rw-
 | 
						|
user:jane:rw-
 | 
						|
group::rw-
 | 
						|
mask::rw-
 | 
						|
other::---</screen>
 | 
						|
 | 
						|
     If you disabled (this functionality of) <command>systemd-logind</command>,
 | 
						|
     you may need to add the user to the <code>video</code> group and
 | 
						|
     log in again.
 | 
						|
    </para>
 | 
						|
   </section>
 | 
						|
 | 
						|
   <section xml:id="sec-gpu-accel-common-issues-mixing-nixpkgs">
 | 
						|
    <title>Mixing different versions of nixpkgs</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
     The <emphasis>Installable Client Driver</emphasis> (ICD)
 | 
						|
     mechanism used by OpenCL and Vulkan loads runtimes into its address
 | 
						|
     space using <code>dlopen</code>. Mixing an ICD loader mechanism and
 | 
						|
     runtimes from different version of nixpkgs may not work. For example,
 | 
						|
     if the ICD loader uses an older version of <package>glibc</package>
 | 
						|
     than the runtime, the runtime may not be loadable due to
 | 
						|
     missing symbols. Unfortunately, the loader will generally be quiet
 | 
						|
     about such issues.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
     If you suspect that you are running into library version mismatches
 | 
						|
     between an ICL loader and a runtime, you could run an application with
 | 
						|
     the <code>LD_DEBUG</code> variable set to get more diagnostic
 | 
						|
     information. For example, OpenCL can be tested with
 | 
						|
     <code>LD_DEBUG=files clinfo</code>, which should report missing
 | 
						|
     symbols.
 | 
						|
    </para>
 | 
						|
   </section>
 | 
						|
  </section>
 | 
						|
</chapter>
 |