diff options
-rw-r--r-- | etc/spack/defaults/packages.yaml | 8 | ||||
-rw-r--r-- | lib/spack/docs/getting_started.rst | 94 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/libglvnd-fe/package.py | 56 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/mesa/package.py | 46 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/opengl/package.py | 42 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/paraview/package.py | 13 |
6 files changed, 242 insertions, 17 deletions
diff --git a/etc/spack/defaults/packages.yaml b/etc/spack/defaults/packages.yaml index dcfbf76b51..4e8f002787 100644 --- a/etc/spack/defaults/packages.yaml +++ b/etc/spack/defaults/packages.yaml @@ -23,8 +23,12 @@ packages: daal: [intel-daal] elf: [elfutils] fftw-api: [fftw] - gl: [mesa+opengl, opengl] - glx: [mesa+glx, opengl] + gl: [libglvnd-fe, mesa+opengl~glvnd, opengl~glvnd] + glx: [libglvnd-fe+glx, mesa+glx~glvnd, opengl+glx~glvnd] + egl: [libglvnd-fe+egl, opengl+egl~glvnd] + libglvnd-be-gl: [mesa+glvnd, opengl+glvnd] + libglvnd-be-glx: [mesa+glx+glvnd, opengl+glx+glvnd] + libglvnd-be-egl: [opengl+egl+glvnd] glu: [mesa-glu, openglu] golang: [gcc] iconv: [libiconv] diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst index 7b908465f5..04594d7e6e 100644 --- a/lib/spack/docs/getting_started.rst +++ b/lib/spack/docs/getting_started.rst @@ -811,6 +811,100 @@ to add the following to ``packages.yaml``: present in PATH, however it will have lower precedence compared to paths from other dependencies. This ensures that binaries in Spack dependencies are preferred over system binaries. + +^^^^^^ +OpenGL +^^^^^^ + +To use hardware-accelerated rendering from a system-supplied OpenGL driver, +add something like the following to your ``packages`` configuration: + +.. code-block:: yaml + + packages: + opengl: + paths: + opengl+glx@4.5: /usr + buildable: False + all: + providers: + gl: [opengl] + glx: [opengl] + +For `EGL <https://www.khronos.org/egl>` support, or for certain modern drivers, +OpenGL calls are dispatched dynamically at run time to the hardware graphics +implementation. This dynamic dispatch is performed using `libglvnd +<https://github.com/NVIDIA/libglvnd>`. In this mode, the graphics library +(e.g.: opengl) must be built to work with libglvnd. Applications then link +against libglvnd instead of the underlying implementation. Environment +variables set at run time govern the process by which libglvnd loads the +underlying implementation and dispatches calls to it. See `this +<https://github.com/NVIDIA/libglvnd/issues/177#issuecomment-496562769>` comment +for details on loading a specific GLX implementation and `this +<https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md>` +page for information about EGL ICD enumeration. + +This codependency between libglvnd and the underlying implementation is modeled +in Spack with two packages for libglvnd: libglvnd, which provides libglvnd +proper; and libglvnd-fe, a bundle package that depends on libglvnd and an +implementation. Implementations that work through libglvnd are no longer +providers for graphics virtual dependencies, like "gl" or "glx", but instead +provide libglvnd versions of these dependencies ("libglvnd-be-gl", +"libglvnd-be-glx", etc.). The libglvnd-fe package depends on these +"libglvnd-be-..." virtual packages, which provide the actual implementation. +It also depends on libglvnd, itself, and exposes its libraries to downstream +applications. For correct operation, the Spack package for the underlying +implementation has to set the runtime environment to ensure that it is loaded +when an application linked against libglvnd runs. This last detail is +important for users who want to set up an external OpenGL implementation that +requires libglvnd to work. This setup requires modifying the ``modules`` +configuration so that modules generated for the external OpenGL implementation +set the necessary environment variables. + +.. code-block:: yaml + + packages: + opengl: + paths: + opengl@4.5+glx+egl+glvnd: /does/not/exist + buildable: False + variants:+glx+egl+glvnd + libglvnd-fe: + variants:+gl+glx+egl + all: + providers: + glvnd-be-gl: [opengl] + glvnd-be-glx: [opengl] + glvnd-be-egl: [opengl] + gl: [libglvnd-fe] + glx: [libglvnd-fe] + egl: [libglvnd-fe] + +.. code-block:: yaml + + modules: + tcl: + opengl@4.5+glx+glvnd: + environment: + set: + __GLX_VENDOR_LIBRARY_NAME: nvidia + opengl@4.5+egl+glvnd: + environment: + set: + __EGL_VENDOR_LIBRARY_FILENAMES: /usr/share/glvnd/egl_vendor.d/10_nvidia.json + +One final detail about the above example is that it avoids setting the true +root of the external OpenGL implementation, instead opting to set it to a path +that is not expected to exist on the system. This is done for two reasons. +First, Spack would add directories under this root to environment variables +that would affect the process of building and installing other packages, such +as ``PATH`` and ``PKG_CONFIG_PATH``. These additions may potentially prevent +those packages from installing successfully, and this risk is especially great +for paths that house many libraries and applications, like ``/usr``. Second, +providing the true root of the external implementation in the ``packages`` +configuration is not necessary because libglvnd need only the environment +variables set above in the ``modules`` configuration to determine what OpenGL +implementation to dispatch calls to at run time. ^^^ Git diff --git a/var/spack/repos/builtin/packages/libglvnd-fe/package.py b/var/spack/repos/builtin/packages/libglvnd-fe/package.py new file mode 100644 index 0000000000..6f737a9017 --- /dev/null +++ b/var/spack/repos/builtin/packages/libglvnd-fe/package.py @@ -0,0 +1,56 @@ +# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +from spack import * + + +class LibglvndFe(BundlePackage): + """The GL Vendor-Neutral Dispatch library (Frontend Dummy Package) + + libglvnd is a vendor-neutral dispatch layer for arbitrating OpenGL API + calls between multiple vendors. It allows multiple drivers from different + vendors to coexist on the same filesystem, and determines which vendor to + dispatch each API call to at runtime. + + Both GLX and EGL are supported, in any combination with OpenGL and OpenGL + ES.""" + + homepage = "https://github.com/NVIDIA/libglvnd" + + version('1.1.1', sha256='71918ed1261e4eece18c0b74b50dc62c0237b8d526e83277ef078554544720b9') + + variant('glx', default=False, description='Provide GLX API') + variant('egl', default=False, description='Provide EGL API') + + depends_on('libglvnd') + + depends_on('libglvnd-be-gl') + depends_on('libglvnd-be-glx', when='+glx') + depends_on('libglvnd-be-egl', when='+egl') + + provides('gl') + provides('glx', when='+glx') + provides('egl', when='+egl') + + @property + def gl_libs(self): + return find_libraries('libOpenGL', + root=self.spec['libglvnd'].prefix, + shared=True, + recursive=True) + + @property + def glx_libs(self): + return find_libraries('libGLX', + root=self.spec['libglvnd'].prefix, + shared=True, + recursive=True) + + @property + def egl_libs(self): + return find_libraries('libEGL', + root=self.spec['libglvnd'].prefix, + shared=True, + recursive=True) diff --git a/var/spack/repos/builtin/packages/mesa/package.py b/var/spack/repos/builtin/packages/mesa/package.py index b277a03d19..94b352d8e2 100644 --- a/var/spack/repos/builtin/packages/mesa/package.py +++ b/var/spack/repos/builtin/packages/mesa/package.py @@ -65,9 +65,13 @@ class Mesa(AutotoolsPackage): variant('opengles', default=False, description="Enable OpenGL ES support.") # Provides - provides('gl@4.5', when='+opengl') - provides('glx@1.4', when='+glx') - # provides('egl@1.5', when='+egl') + provides('gl@4.5', when='+opengl ~glvnd') + provides('glx@1.4', when='+glx ~glvnd') + # provides('egl@1.5', when='+egl ~glvnd') + + provides('libglvnd-be-gl', when='+glvnd') + provides('libglvnd-be-glx', when='+glvnd +glx') + # provides('libglvnd-be-egl', when='+glvnd +egl') # Variant dependencies depends_on('llvm@6:', when='+llvm') @@ -179,10 +183,32 @@ class Mesa(AutotoolsPackage): return args @property - def libs(self): - for dir in ['lib64', 'lib']: - libs = find_libraries(['libGL', 'libOSMesa'], - join_path(self.prefix, dir), - shared=True, recursive=False) - if libs: - return libs + def gl_libs(self): + result = LibraryList(()) + + if '~glvnd' in self.spec: + result.extend(find_libraries('libGL', + root=self.spec.prefix, + shared='+shared' in self.spec, + recursive=True)) + return result + + @property + def glx_libs(self): + result = LibraryList(()) + + if '~glvnd' in self.spec: + result.extend(find_libraries('libGLX', + root=self.spec.prefix, + shared='+shared' in self.spec, + recursive=True)) + return result + + def setup_run_environment(self, env): + if '+glx +glvnd' in self.spec: + env.set('__GLX_VENDOR_LIBRARY_NAME', 'mesa') + + if '+egl +glvnd' in self.spec: + env.set('__EGL_VENDOR_LIBRARY_FILENAMES', ':'.join(( + os.path.join(self.spec.prefix, 'share', 'glvnd', + 'egl_vendor.d', '50_mesa.json')))) diff --git a/var/spack/repos/builtin/packages/opengl/package.py b/var/spack/repos/builtin/packages/opengl/package.py index 413b8e0f45..572fc04845 100644 --- a/var/spack/repos/builtin/packages/opengl/package.py +++ b/var/spack/repos/builtin/packages/opengl/package.py @@ -13,7 +13,14 @@ class Opengl(Package): homepage = "https://www.opengl.org/" - provides('gl') + variant('glvnd', + default=False, + description="Expose Graphics APIs through libglvnd") + + variant('glx', default=True, description="Enable GLX API.") + variant('egl', default=False, description="Enable EGL API.") + + provides('gl', when='~glvnd') provides('gl@:4.5', when='@4.5:') provides('gl@:4.4', when='@4.4:') provides('gl@:4.3', when='@4.3:') @@ -33,7 +40,19 @@ class Opengl(Package): provides('gl@:1.0', when='@1.0:') if sys.platform != 'darwin': - provides('glx@1.4') + provides('glx@1.4', when='~glvnd +glx') + + # NOTE: This package should have a dependency on libglvnd, but because it + # is exclusively provided externally the dependency is never traversed. + # depends_on('libglvnd', when='+glvnd') # don't uncomment this + + provides('libglvnd-be-gl', when='+glvnd') + provides('libglvnd-be-glx', when='+glvnd +glx') + provides('libglvnd-be-egl', when='+glvnd +egl') + + provides('egl@1.5', when='~glvnd +egl') + + depends_on('libglvnd', when='+glvnd') # Override the fetcher method to throw a useful error message; # fixes GitHub issue (#7061) in which this package threw a @@ -80,8 +99,25 @@ class Opengl(Package): @property def libs(self): + result = LibraryList(()) + + # "libs" provided by glvnd; this package sets the environment variables + # so that glvnd, in turn, loads this package's libraries at run-time. + if '+glvnd' in self.spec: + return result + for dir in ['lib64', 'lib']: libs = find_libraries('libGL', join_path(self.prefix, dir), shared=True, recursive=False) if libs: - return libs + result.extend(libs) + break + + if '+egl' in self.spec: + for dir in ['lib64', 'lib']: + libs = find_libraries('libEGL', join_path(self.prefix, dir), + shared=True, recursive=False) + if libs: + result.extend(libs) + break + return result diff --git a/var/spack/repos/builtin/packages/paraview/package.py b/var/spack/repos/builtin/packages/paraview/package.py index bb8b140b74..f5195dc2bb 100644 --- a/var/spack/repos/builtin/packages/paraview/package.py +++ b/var/spack/repos/builtin/packages/paraview/package.py @@ -49,6 +49,7 @@ class Paraview(CMakePackage, CudaPackage): description='Builds a shared version of the library') variant('kits', default=True, description='Use module kits') + variant('egl', default=False, description="Enable EGL") conflicts('+python', when='+python3') conflicts('+python', when='@5.6:') @@ -58,6 +59,9 @@ class Paraview(CMakePackage, CudaPackage): # See commit: https://gitlab.kitware.com/paraview/paraview/-/commit/798d328c conflicts('~opengl2', when='@5.5:') + conflicts('+egl', when='+osmesa') + conflicts('+egl', when='+qt') + # Workaround for # adding the following to your packages.yaml # packages: @@ -89,6 +93,10 @@ class Paraview(CMakePackage, CudaPackage): depends_on('mesa+osmesa', when='+osmesa') depends_on('gl@3.2:', when='+opengl2') depends_on('gl@1.2:', when='~opengl2') + + depends_on('glx', when='~osmesa platform=linux') + depends_on('egl', when='+egl') + depends_on('libxt', when='~osmesa platform=linux') conflicts('+qt', when='+osmesa') @@ -208,7 +216,9 @@ class Paraview(CMakePackage, CudaPackage): cmake_args = [ '-DPARAVIEW_BUILD_QT_GUI:BOOL=%s' % variant_bool('+qt'), '-DVTK_OPENGL_HAS_OSMESA:BOOL=%s' % variant_bool('+osmesa'), - '-DVTK_USE_X:BOOL=%s' % nvariant_bool('+osmesa'), + '-DVTK_OPENGL_HAS_EGL:BOOL=%s' % variant_bool('+egl'), + ('-DVTK_USE_X:BOOL=%s' % + variant_bool('~osmesa ~egl platform=linux')), '-DVTK_RENDERING_BACKEND:STRING=%s' % rendering, '-DPARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=%s' % includes, '-DBUILD_TESTING:BOOL=OFF', @@ -272,7 +282,6 @@ class Paraview(CMakePackage, CudaPackage): if 'darwin' in spec.architecture: cmake_args.extend([ - '-DVTK_USE_X:BOOL=OFF', '-DPARAVIEW_DO_UNIX_STYLE_INSTALLS:BOOL=ON', ]) |