Skip to content
Snippets Groups Projects
Unverified Commit 573489db authored by Omar Padron's avatar Omar Padron Committed by GitHub
Browse files

Add libglvnd packages/Add EGL support (#14572)

* add new package: "libglvnd-frontend"

* add +glvnd variant to opengl package

* add +glvnd variant to mesa package

* add +egl variant to paraview package

* add libglvnd-frontend entries to default packages config

* fix style

* add default providers for glvnd virtuals

add default providers for glvnd-gl, glvnd-glx, and glvnd-egl

* WIP: rough start to external OpenGL documentation

* rename libglvnd-frontend package and backend virtual dependencies

* update documentation

* fix ligvnd-be-* typos

* fix libglvnd-fe package class name

* fix doc parse error
parent 9c42f246
No related branches found
No related tags found
No related merge requests found
...@@ -23,8 +23,12 @@ packages: ...@@ -23,8 +23,12 @@ packages:
daal: [intel-daal] daal: [intel-daal]
elf: [elfutils] elf: [elfutils]
fftw-api: [fftw] fftw-api: [fftw]
gl: [mesa+opengl, opengl] gl: [libglvnd-fe, mesa+opengl~glvnd, opengl~glvnd]
glx: [mesa+glx, opengl] 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] glu: [mesa-glu, openglu]
golang: [gcc] golang: [gcc]
iconv: [libiconv] iconv: [libiconv]
......
...@@ -811,6 +811,100 @@ to add the following to ``packages.yaml``: ...@@ -811,6 +811,100 @@ to add the following to ``packages.yaml``:
present in PATH, however it will have lower precedence compared to paths present in PATH, however it will have lower precedence compared to paths
from other dependencies. This ensures that binaries in Spack dependencies from other dependencies. This ensures that binaries in Spack dependencies
are preferred over system binaries. 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 Git
......
# 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)
...@@ -65,9 +65,13 @@ class Mesa(AutotoolsPackage): ...@@ -65,9 +65,13 @@ class Mesa(AutotoolsPackage):
variant('opengles', default=False, description="Enable OpenGL ES support.") variant('opengles', default=False, description="Enable OpenGL ES support.")
# Provides # Provides
provides('gl@4.5', when='+opengl') provides('gl@4.5', when='+opengl ~glvnd')
provides('glx@1.4', when='+glx') provides('glx@1.4', when='+glx ~glvnd')
# provides('egl@1.5', when='+egl') # 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 # Variant dependencies
depends_on('llvm@6:', when='+llvm') depends_on('llvm@6:', when='+llvm')
...@@ -179,10 +183,32 @@ def configure_args(self): ...@@ -179,10 +183,32 @@ def configure_args(self):
return args return args
@property @property
def libs(self): def gl_libs(self):
for dir in ['lib64', 'lib']: result = LibraryList(())
libs = find_libraries(['libGL', 'libOSMesa'],
join_path(self.prefix, dir), if '~glvnd' in self.spec:
shared=True, recursive=False) result.extend(find_libraries('libGL',
if libs: root=self.spec.prefix,
return libs 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'))))
...@@ -13,7 +13,14 @@ class Opengl(Package): ...@@ -13,7 +13,14 @@ class Opengl(Package):
homepage = "https://www.opengl.org/" 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.5', when='@4.5:')
provides('gl@:4.4', when='@4.4:') provides('gl@:4.4', when='@4.4:')
provides('gl@:4.3', when='@4.3:') provides('gl@:4.3', when='@4.3:')
...@@ -33,7 +40,19 @@ class Opengl(Package): ...@@ -33,7 +40,19 @@ class Opengl(Package):
provides('gl@:1.0', when='@1.0:') provides('gl@:1.0', when='@1.0:')
if sys.platform != 'darwin': 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; # Override the fetcher method to throw a useful error message;
# fixes GitHub issue (#7061) in which this package threw a # fixes GitHub issue (#7061) in which this package threw a
...@@ -80,8 +99,25 @@ def fetcher(self): ...@@ -80,8 +99,25 @@ def fetcher(self):
@property @property
def libs(self): 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']: for dir in ['lib64', 'lib']:
libs = find_libraries('libGL', join_path(self.prefix, dir), libs = find_libraries('libGL', join_path(self.prefix, dir),
shared=True, recursive=False) shared=True, recursive=False)
if libs: 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
...@@ -49,6 +49,7 @@ class Paraview(CMakePackage, CudaPackage): ...@@ -49,6 +49,7 @@ class Paraview(CMakePackage, CudaPackage):
description='Builds a shared version of the library') description='Builds a shared version of the library')
variant('kits', default=True, variant('kits', default=True,
description='Use module kits') description='Use module kits')
variant('egl', default=False, description="Enable EGL")
conflicts('+python', when='+python3') conflicts('+python', when='+python3')
conflicts('+python', when='@5.6:') conflicts('+python', when='@5.6:')
...@@ -58,6 +59,9 @@ class Paraview(CMakePackage, CudaPackage): ...@@ -58,6 +59,9 @@ class Paraview(CMakePackage, CudaPackage):
# See commit: https://gitlab.kitware.com/paraview/paraview/-/commit/798d328c # See commit: https://gitlab.kitware.com/paraview/paraview/-/commit/798d328c
conflicts('~opengl2', when='@5.5:') conflicts('~opengl2', when='@5.5:')
conflicts('+egl', when='+osmesa')
conflicts('+egl', when='+qt')
# Workaround for # Workaround for
# adding the following to your packages.yaml # adding the following to your packages.yaml
# packages: # packages:
...@@ -89,6 +93,10 @@ class Paraview(CMakePackage, CudaPackage): ...@@ -89,6 +93,10 @@ class Paraview(CMakePackage, CudaPackage):
depends_on('mesa+osmesa', when='+osmesa') depends_on('mesa+osmesa', when='+osmesa')
depends_on('gl@3.2:', when='+opengl2') depends_on('gl@3.2:', when='+opengl2')
depends_on('gl@1.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') depends_on('libxt', when='~osmesa platform=linux')
conflicts('+qt', when='+osmesa') conflicts('+qt', when='+osmesa')
...@@ -208,7 +216,9 @@ def nvariant_bool(feature): ...@@ -208,7 +216,9 @@ def nvariant_bool(feature):
cmake_args = [ cmake_args = [
'-DPARAVIEW_BUILD_QT_GUI:BOOL=%s' % variant_bool('+qt'), '-DPARAVIEW_BUILD_QT_GUI:BOOL=%s' % variant_bool('+qt'),
'-DVTK_OPENGL_HAS_OSMESA:BOOL=%s' % variant_bool('+osmesa'), '-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, '-DVTK_RENDERING_BACKEND:STRING=%s' % rendering,
'-DPARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=%s' % includes, '-DPARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=%s' % includes,
'-DBUILD_TESTING:BOOL=OFF', '-DBUILD_TESTING:BOOL=OFF',
...@@ -272,7 +282,6 @@ def nvariant_bool(feature): ...@@ -272,7 +282,6 @@ def nvariant_bool(feature):
if 'darwin' in spec.architecture: if 'darwin' in spec.architecture:
cmake_args.extend([ cmake_args.extend([
'-DVTK_USE_X:BOOL=OFF',
'-DPARAVIEW_DO_UNIX_STYLE_INSTALLS:BOOL=ON', '-DPARAVIEW_DO_UNIX_STYLE_INSTALLS:BOOL=ON',
]) ])
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment