Summary of the situation of OpenCL in Debian
********************************************

OpenCL goals
============

From wikipedia:
  Open Computing Language (OpenCL) is a framework for writing programs that
  execute across heterogeneous platforms consisting of central processing unit
  (CPUs), graphics processing unit (GPUs), and other processors.
    OpenCL includes a language (based on C99) for writing kernels (functions
  that execute on OpenCL devices), plus application programming interfaces
  (APIs) that are used to define and then control the platforms.
  [...]
    OpenCL is an open standard maintained by the non-profit technology
  consortium Khronos Group. It has been adopted by Intel, Advanced Micro
  Devices, Nvidia, and ARM Holdings.

What is important for Debian is that:
- OpenCL is a standard maintained by the Khronos Group
- OpenCL is a language (for target platforms) *and* an API.
- there will be several implementations (we can hope that, at least one for
  processors will be free)
- API of OpenCL is design to support several implementations at the same time
- API of OpenCL offert the possibility to choose the used platform (and OpenCL
  vendor) at runtime (instead of compilation/link-time as this is the case for
  MPI)
- API of OpenCL offers the possibility to use vendor extensions, looking for
  address function at runtime (here again by opposition to compile/runtime)

Mechanisms used to archieve all these goals
===========================================

An application using OpenCL can compile with, and link directly at, a specific
implementation (as in the MPI world). However, doing this will forbid most of
the runtime choices presented in the previous paragraph.

The classical situation for OpenCL is that:
- each vendors (ie OpenCL implementor) must provide:
  - an OpenCL ICD (Installable Client Driver) as a shared library with
    some convention/features/symbols (see later)
  - the path of this library in a vendor-specific text file in
    /etc/OpenCL/vendors/ directory
- the application is compiled with
  - some OpenCL headers. This can be:
    - the official Kronos OpenCL headers (all official features and extensions,
      no private vendor extension)
    - some vendors headers, generally based on the previous one but with
      some extensions (functions, constants, ...) added
  - OpenCL ICD Loader which offer the OpenCL API to the applications. The
    ICD Loader is mainly a call dispatcher. Kronos group provides (nonfree)
    sources of one to its members.
    - most vendors (amd, intel, nvidia at least) provide a ICD Loader
    - ocl-icd provides a free one after some reverse engeenering of the
      previously cited ones.

ICD Loaders and ICD
===================
In therory (see below), any ICD Loader should be able to load and use any ICD.
An ICD must implement some mandatory functions. One of these functions allows
the ICD Loader to get the address of a structure which contains the address of
all ICD implementation of OpenCL functions.
Writing such an ICD Loader is easy once you know the order of the functions
in the structure (list and order that the Khronos group restrict to its members
and that the ocl-icd projet reverse engeenered)
  The Khronos group ensures that any functions added to this structure will
never be removed (so that their won't be incompatibility between to ICD
Loaders).

In pratice, we can really use the ICD Loader from Intel to use the NVidia ICD.
But, there is no support for the ICD to declare which version of the structure
it provides. An ICD can offers (through the structure) more functions. It
happens when the ICD provides an OpenCL version greater than the one provided
by the ICD Loader. This is not really a problem but the an OpenCL application
using the more recent OpenCL version will not be able to link to the ICD
Loader. It will then fail at link time.
  But there is also the opposite: the ICD Loader supports a greater version of
OpenCL than the ICD. In this case, an OpenCL application using features from
the new version will call the ICD Loader that will call the "function" at the
address present in the memory after the end of the (old) structure provider by
the ICD. This generally leads to a segfault.
  The ICD Loader cannot do anything about that: it does not have the
information. Even if ICDs declare a supported OpenCL version, it is the
OpenCL version for which the support is full. At the time of writing, the Intel
ICD declare to support OpenCL 1.1 but provides to the ICD Loader the structure
of OpenCL 1.2 *with* some address of functions specific to OpenCL 1.2 (but not
all of them, hence the no declaration of OpenCL 1.2 support).
  This situation is also a problem for application (PyCL ?) that detect at
compilation time which version of OpenCL is supported. They will get the
OpenCL version of the ICD Loader, but not the one of the ICD itself that
will be loaded at runtime.

  An ICD not implementing one function of the structure puts a NULL pointer.
But non-free ICD Loaders (cnot ocl-icd for now) do not do any checks for
non-NULL value before dispatching the call. So it is again easy to get segfault
with some combination of program/ICD.


  About compatibility, each ICD must also implement the support for the OpenCL
*language* (for the code dedicated to the target platforms). Of course, as the
norm is not complete, or not fully implemented or implemented with extension,
the portability of OpenCL code is not as good as one can hope. But there is
little to do here with respect to Debian packaging.

Current packaging situation
===========================
Brief overview of sources packages/OpenCL implementations:
* AMD and NVidia OpenCL implementation are packaged into the non-free section.
* Intel is not packaged. It is not redistribuable, so its packaging would
  involve a 'installer' package.
  Intel ICD Loader support OpenCL 1.2
  Intel ICD support OpenCL 1.1 and some functions of OpenCL 1.2
* Khronos OpenCL headers 1.2 are packaged in main
* Ocl-icd project is packaged in main
* Pocl, a free implementation of OpenCL, will be packaged in main. Its state
  does not seem yet good enough to be able to run non simple OpenCL
  applications. This should change in the future.

Overview of binary packages currently in sid (and probably testing) on amd64:
[AMD]
* amd-libopencl1: AMD ICD Loader (support OpenCL 1.2)
    install libOpenCL.so.1
      shared library
        soname libOpenCL.so.1
        symbols versioned (with OpenCL version, but no conflicts on symbols)
    install libOpenCL.so
      symlink to libOpenCL.so.1
  Multi-Arch: same
  Provides: libopencl1
  Conflicts: amd-app, nvidia-libopencl1
    => should Conflicts and Provides libopencl1. See #679038
* amd-opencl-icd: AMD ICD (support OpenCL 1.2)
  Multi-Arch: same
  Depends: libopencl1
  Enhances: libopencl1
  Conflicts: amd-app
* amd-opencl-dev: AMD OpenCL development
    Metapackage
  Multi-Arch: same
  Depends: amd-libopencl1 | libopencl1, opencl-headers (>= 1.2)
* amd-clinfo:
  No Multi-Arch
  Depends: amd-libopencl1
    => should depends on the virtual package libopencl1. See #679025 (pending)

[NVidia]
* nvidia-libopencl1: NVidia ICD Loader (support OpenCL 1.1)
    install libOpenCL.so.1.0.0
      shared library
        soname libOpenCL.so.1
        symbols not versioned
    install libOpenCL.so.1
      symlink to libOpenCL.so.1.0.0
    install libOpenCL.so
      symlink to libOpenCL.so.1
  Multi-Arch: same
  Provides: libopencl1
  Recommends: opencl-icd | nvidia-opencl-icd
  Conflicts: nvidia-libopencl1-dev
    => should Conflicts and Provides libopencl1. See #679047
* nvidia-libopencl1-ia32: 32-bit NVidia ICD Loader (support OpenCL 1.1)
    install lib32/libOpenCL.so.1.0.0
      shared library
        soname libOpenCL.so.1
        symbols not versioned
    install lib32/libOpenCL.so.1
      symlink to libOpenCL.so.1.0.0
    install lib32/libOpenCL.so
      symlink to libOpenCL.so.1
  No Multi-Arch
  Provides: lib32opencl1
  Recommends: opencl-icd | nvidia-opencl-icd-ia32
  => the Recommends to opencl-icd seems wrong to me
  => this package should disappear (replaced by nvidia-libopencl1:i386)
* nvidia-opencl-common: common files for NVidia ICD (support OpenCL 1.1)
  Multi-Arch: foreign
  Recommends: nvidia-opencl-icd | nvidia-opencl-icd-ia32
* nvidia-opencl-icd: NVidia ICD (support OpenCL 1.1)
  Multi-Arch: same
  Provides: opencl-icd
  Depends: nvidia-opencl-common, libopencl1
  Enhances: libopencl1
* nvidia-opencl-icd-ia32: 32-bit NVidia ICD (support OpenCL 1.1)
  No Multi-Arch
  Provides: opencl-icd
  Depends: nvidia-opencl-common, lib32opencl1
  Enhances: lib32opencl1
  => the Provides opencl-icd seems wrong to me
  =>  this package should disappear (replaced by nvidia-opencl-icd:i386)
* nvidia-opencl-dev: NVidia OpenCL development
    Metapackage
  No Multi-Arch
  Provides: opencl-dev
  Depends: nvidia-libopencl1 | libopencl1, opencl-headers (>= 1.1)

[ocl-icd] (version 1.3-2 currently in NEW or in my own repo)
* ocl-icd-libopencl1: ocl-icd ICD Loader (support OpenCL 1.2)
    install libOpenCL.so.1.0.0
      shared library
        soname libOpenCL.so.1
        symbols versioned (with OpenCL version, but no conflicts on symbols)
    install libOpenCL.so.1
      symlink to libOpenCL.so.1.0.0
    install libOpenCL.so
      symlink to libOpenCL.so.1.0.0
  Multi-Arch: same
  Provides: libopencl1
  Conflicts: libopencl1, amd-app, nvidia-libopencl1-dev
  Replaces: libopencl1, amd-app, nvidia-libopencl1-dev
   Note: amd-app, nvidia-libopencl1-dev seems to be old/external packages
         providing some of these files
  Suggests: opencl-icd
   Note: would be promoted to a recommends once a free OpenCL implementation
     will be available
* ocl-icd-opencl-dev: OpenCL development
    install OpenCL.pc
      pkg-config file for OpenCL
  Multi-Arch: same
  Provides: opencl-dev
  Depends: opencl-headers (>= 1.2), libopencl1
  Conflicts: amd-app, opencl-dev
  Replaces: amd-app, opencl-dev
* ocl-icd-dev: devel package to develop an ICD
    install ocl_icd.h
      headers with the structure with all functions that an ICD must provide
    install some examples (skeleton of a ICD source and linker map)
    install ocl-icd.pc
  No Multi-Arch

[Intel OpenCL SDK]: no public Debian packages (software not redistributable)
* ICD Loader (support OpenCL 1.2): can be installed in Multi-Arch paths
    install libOpenCL.so
      shared library
        soname libOpenCL.so
        symbols not versioned
    => problem with wrong soname
    => can still be used by programs that require libOpenCL.so.1 by creating
       a symlink (the dynamic linker do not check the soname)
* ICD (support OpenCL 1.1 + some 1.2 functions)
* OpenCL headers
  based on the Khronos ones. Intel's one seem a little bit outdated but
  include some constants/... that seems to be Intel specific...


Virtual packages:
* opencl-icd: existing virtual package for OpenCL ICD
  ensure an OpenCL ICD is installed
  a package providing opencl-icd should (must?):
  - Provides: opencl-icd
  - Enhances: libopencl1
* opencl-dev: existing virtual package dor OpenCL development
  ensure headers and libraries are installed
  a package providing opencl-dev should (must?):
  - Provides: opencl-dev
  - install OpenCL headers
    can be done with a (versioned) dependency on the opencl-headers package
  - Depends: libopencl1
  - Recommends: libgl1-mesa-dev | libgl-dev
    GL headers are often required when compiling OpenCL program
    => not done in amd-opencl-dev
* libopencl1: existing virtual package for OpenCL ICD Loaders
  ensure an OpenCL ICD Loader is installed
  a package providing libopencl1 should (must?):
  - Conflicts/Replaces/Provides: libopencl1
    https://www.debian.org/doc/debian-policy/ch-relationships.html#s7.6.2
  - Recommends: opencl-icd
  - install libOpenCL.so.1 in library search path
  - install libOpenCL.so in library search path
    NOTE: this last one must not be in a -dev package if we want to
    support binaries compiled with the Intel SDK
  - libOpenCL.so.1 must have libOpenCL.so.1 as soname
    [proposed, not right for the intel one]
  - libOpenCL.so.1 must have its symbols versioned
    [proposed, not right for the intel and nvidia ones]
* libopencl1.1: proposed virtual package
  a package providing libopencl1.1 must:
  - provides libopencl1
  - implements and dispatch all functions from OpenCL 1.1 API
* libopencl1.2: proposed virtual package
  a package providing libopencl1.2 must:
  - provides libopencl1
  - implements and dispatch all functions from OpenCL 1.2 API
NOTE: libopencl1.0 is not proposed as a virtual package:
  - the 1.0 API is not really designed to work with ICD Loaders
  - most (all?) OpenCL implementations target at least OpenCL 1.1


A few remarks:
* due to the soname of Intel (libOpenCL.so instead of libOpenCL.so.1), it is
  better to install the libOpenCL.so link in the libopencl1 packages instead
  of installing it in the dev packages
* is it really necessary to keep the three -dev packages?
  + ocl-icd-opencl-dev is free and provides a OpenCL.pc file
  + amd-opencl-dev is a metapackage that install by default the amd-libopencl1
    that itself install by default the amd-opencl-icd
  + same for nvidia-opencl-dev
* if we keep the three -dev packages (to ease the installation of the
  full AMD and NVidia SDK), do we want to rename ocl-icd-opencl-dev
  into opencl-dev (ie use the virtual package name as the binary
  package name of the free alternative)
* do we want to keep the various *-libopencl1 (ie ICD loaders) packages in
  Debian?
  ocl-icd-libopencl1 provides a free alternative
  {amd,nvidia}-libopencl1 will be useful:
  - when ocl-icd-libopencl1 is not yet updated to the latest version
    where as {amd,nvidia}-libopencl1 are
  - if {amd,nvidia}-libopencl1 start to implement non standard things
  - to ease the reverse engeenering required to improve ocl-icd-libopencl1
    when non-free ICD loader implements more functions
* at least, here is a summary of problems/warning for different combinaison of
  ICD *Loaders* used at compile-time (CT) and at run-time (RT)
  (problems with ICD compatibility themselves are not taken into account here)

   \    |	  |	  |	    |	    |
    \RT | ocl-icd | AMD   |  NVidia | Intel |
     \  |	  |	  |	    |	    |
   CT \ |	  |	  |	    |	    |
--------+---------+-------+---------+-------+
        |	  |       |	    |	    |
ocl-icd |   ok    |  ok   |   MVS   |  MVS  |
        |	  |       |   MS    |  MSO  |
--------+---------+-------+---------+-------+
	|	  |	  |	    |	    |
AMD	|   ok    |  ok	  |   MVS   |  MVS  |
	|	  |	  |   MS    |  MSO  |
--------+---------+-------+---------+-------+
        |	  |   	  |	    |	    |
NVidia  |   ok    |  ok	  |   ok    |  MSO  |
        |	  |       |         |	    |
--------+---------+-------+---------+-------+
        |	  |       |	    |	    |
Intel   |   BSO   |  BSO  |   BSO   |  ok   |
        |	  |       |   MS    |	    |
--------+---------+-------+---------+-------+
MVS: missing version on symbol => a warning from the linker at program start
MS: missing symbols. The linker can fail to find some symbols (NVidia ICD
    Loader still only support the 1.1 API)
BSO: the libOpenCL.so link must be present at runtime.
    The requested soname is libOpenCL.so
    The soname in the loaded library (filename) is libOpenCL.so.1
MSO: wrong soname:
    The requested soname is libOpenCL.so.1
    The soname in the loaded library (filename) is libOpenCL.so

