We're hiring!
*

Virtualizing GPU Access

Robert Foss avatar

Robert Foss
February 12, 2018

Share this post:

Reading time:

Virtualized GPU access is becoming common in the containerized and virtualized application space. Let's have a look at why and how.

For the past few years a clear trend of containerization of applications and services has emerged. Having processes containerized is beneficial in a number of ways. It both improves portability and strengthens security, and if done properly the performance penalty can be low.

In order to further improve security containers are commonly run in virtualized environments. This provides some new challenges in terms of supporting the accelerated graphics usecase.

OpenGL ES implementation

Currently Collabora and Google are implementing OpenGL ES 2.0 support. OpenGL ES 2.0 is the lowest common denominator for many mobile platforms and as such is a requirement for Virgil3D to be viable on the those platforms.

That is is the motivation for making Virgil3D work on OpenGL ES hosts.

How does this work?

This stack is commonly referred to as Virgil3D, since all of the parts originated from a project with that name.

Collabora - Virtualized OpenGL Stack

There are a few parts to this implementation.

QEMU, virglrenderer and virtio-gpu. The way it works is by letting the guest applications speak unmodified OpenGL to the Mesa. But instead of Mesa handing commands over to the hardware it is channeled through virtio-gpu on the guest to QEMU on the host.

QEMU then receives the raw graphics stack state (Gallium state) and interprets it using virglrenderer from the raw state into an OpenGL form, which can be executed as entirely normal OpenGL on the host machine.

The host OpenGL stack does not even have to be Mesa, and could for example be the proprietary nvidia stack.

Trying it out

Environment

First of all, let's have a look at the development environment. When doing graphical development I find it quite helpful to set up a parallel graphics stack in order to not pollute or depend on the stack of the host machine more than we have to.

function add_export_env {
  local VAR="$1"
  shift
  local VAL=$(eval echo "\$$VAR")
  if [ "$VAL" ]; then
    VAL=$(concatenate_colon "$@" "$VAL");
  else
    VAL=$(concatenate_colon "$@");
  fi
  eval "export $VAR=\"$VAL\""
}

function prefix_setup {
  local PREFIX="$1"

  add_export_env PATH "$PREFIX/bin"
  add_export_env LD_LIBRARY_PATH "$PREFIX/lib"
  add_export_env PKG_CONFIG_PATH "$PREFIX/lib/pkgconfig/" "$PREFIX/share/pkgconfig/"
  add_export_env MANPATH "$PREFIX/share/man"
  export ACLOCAL_PATH="$PREFIX/share/aclocal"
  mkdir -p "$ACLOCAL_PATH"
  export ACLOCAL="aclocal -I $ACLOCAL_PATH"
}

function projectshell {
  case "$1" in
    virgl | virglrenderer)
        export ALT_LOCAL="/opt/local/virgl"
        mkdir -p "$ALT_LOCAL"
        prefix_setup "$ALT_LOCAL"
        ;;
  esac
}

The above snippet is something that I would put in my .bashrc or .zshrc. Don't forget so run source ~/.bashrc or the equivalent after making changes.

To enter the environment I simply type projectshell virgl.

Build libepoxy

libepoxy is a library for managing OpenGL function pointers for you. And it is a dependency of virglrenderer, which we'll get to below.

git clone https://github.com/anholt/libepoxy.git
cd libepoxy
./autogen.sh --prefix=$ALT_LOCAL
make -j$(nproc --ignore=1)
make install

Build virglrenderer

Virgilrenderer is the component that QEMU uses to provide accelerated rendering.
It receives Gallium states from the guest kernel via its virtio-gpu interface, which are then translated into OpenGL on the host. It also translates shaders from the TGSI format used by Gallium into the GLSL format used by OpenGL.

git clone git://anongit.freedesktop.org/virglrenderer
cd virglrenderer
./autogen.sh --prefix=$ALT_LOCAL
make -j$(nproc --ignore=1)
make install

Build libpciaccess

libpciaccess is a library for simplifying accessing devices on the PCI bus.
It is a dependency of Mesa, which we'll get to below.

git clone git://git.freedesktop.org/git/xorg/lib/libpciaccess
cd libpciaccess
./autogen.sh --prefix=$ALT_LOCAL
make -j$(nproc --ignore=1)
make install

Build Mesa

# Fetch dependencies
sudo sed -i 's/\#deb-src/deb-src/' /etc/apt/sources.list
sudo apt update
sudo apt-get build-dep mesa

# Actually build Mesa
git clone https://anongit.freedesktop.org/git/mesa/mesa.git
cd mesa
./configure \
    --prefix=$ALT_LOCAL \
    --enable-driglx-direct \
    --enable-gles1 \
    --enable-gles2 \
    --enable-glx-tls \
    --with-egl-platforms='drm x11 wayland' \
    --with-dri-drivers="i915 i965 nouveau" \
    --with-gallium-drivers="nouveau swrast radeonsi"
make -j$(nproc --ignore=1)
make install

Build QEMU

git clone git://git.qemu.org/qemu.git
cd qemu
./configure \
    --prefix=$ALT_LOCAL \
    --target-list=x86_64-softmmu \
    --enable-kvm \
    --disable-werror \
    --enable-virglrenderer
make -j$(nproc --ignore=1)
make install

Set up a VM

As a guest we're going to use Ubuntu 17.10, but just use the latest release of whatever distro you like. The kernel has have been built with the appropriate virtio-gpu Kconfig options though.

wget http://releases.ubuntu.com/17.10/ubuntu-17.10.1-server-amd64.iso
qemu-img create -f qcow2 ubuntu.qcow2 35G
qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -hda ubuntu.qcow2 \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display sdl,gl=on \
    -boot d -cdrom ubuntu-17.10.1-desktop-amd64.iso

Run VM

qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -hda ubuntu.qcow2 \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display sdl,gl=on

Et Voila! Your guest should now have GPU acceleration!

Conclusion

Hopefully this guide will have helped you to build all of the software needed to set up your very own virglrenderer enabled graphics stack.


Visit Robert's blog.

Comments (15)

  1. Kieran:
    Feb 13, 2018 at 11:01 AM

    Thanks for the write-up! What kind of overhead does this produce compared to running on host?

    Reply to this comment

    Reply to this comment

    1. Robert Foss:
      Feb 13, 2018 at 04:30 PM

      Hey Kieran!

      That's a good question, I haven't looked into the performance aspect.

      I would think that the performance impact is not too bad. But it would also depend on the application.
      An application that executes more OpenGL calls would see a larger impact.

      Reply to this comment

      Reply to this comment

  2. Ernst Sjöstrand:
    Feb 13, 2018 at 08:29 PM

    Nice! I uploaded packages for Ubuntu with virgilrenderer enabled to my ppa and wrote a few lines about it.... https://www.sabeltand.net/virgl/

    Reply to this comment

    Reply to this comment

    1. Robert Foss:
      Mar 09, 2018 at 03:08 PM

      Hey!

      I'm glad the post helps. Overall virgl is pretty painless to work with, which is nice.

      Reply to this comment

      Reply to this comment

  3. Stephen Lawrence:
    Mar 09, 2018 at 01:09 AM

    The Genivi automotive alliance is interested in the current support for GPU virtualisation in virtio as part of its project investigating graphics sharing between automotive domains [1]. It would be great to get Collabora's input.

    [1] https://at.projects.genivi.org/wiki/pages/viewpage.action?pageId=16024743

    Reply to this comment

    Reply to this comment

    1. Robert Foss:
      Mar 09, 2018 at 03:07 PM

      Thank you for commenting here Stephen.

      A proper reply requires more than the space available in the comment section here.
      Allow us to reach out directly. We will make sure to write a follow up post on our blog here when appropriate too.

      Reply to this comment

      Reply to this comment

      1. Stephen Lawrence:
        Mar 14, 2018 at 05:20 PM

        Thanks for the reply Robert and apologies for the slow response. I've been out of the office.

        OK understood and thanks for the interest.

        Whilst not trying to continue the conversation here I can outline why the post piqued my interest. Firstly a Hypervisor project has recently begun as part of the work on interaction between automotive domains. One of its goals is considering whether IO can be standardised further to ease h/w support. Of course virtio is a key technology there. There will be a HV workshop at the upcoming Genivi AMM in Munich April 17-19. Then there is the project looking at Graphics Sharing and Distributed HMIs. Stating the obvious but GPU virtualisation is interesting there when domains are consolidated onto powerful SoCs. So for both projects the current state and future roadmap of virtio-gpu support for automotive GPUs is interesting. There are HV experts participating in the HV project but given Collabora's depth of knowledge in both the linux gfx stack and h/w GPUs I personally think Collabora could bring a very useful viewpoint. Thanks for your consideration.

        Reply to this comment

        Reply to this comment

        1. Daniel Stone:
          Mar 14, 2018 at 06:14 PM

          Right, there's quite a few things to discuss in that space. Cross-domain graphics sharing is something we have a particular interest in - see our efforts with the Waltham project. virtio is definitely valuable, as an open cross-vendor standard which allows for different virtualisation implementations to be used. We think there's a lot of value in that compared to having every component support various proprietary interfaces, and that's something we'd be very happy to discuss.

          Reply to this comment

          Reply to this comment

  4. Salvador Liébana:
    Apr 03, 2019 at 04:46 AM

    Do you know a proper glsl version when I compile qemu?? because I get this if I activate gl on my arm host

    qemu_gl_create_compile_shader: compile vertex error
    0:2(10): error: GLSL ES 3.00 is not supported. Supported versions are: 1.10, 1.20, and 1.00 ES

    qemu_gl_create_compile_shader: compile fragment error
    0:2(10): error: GLSL ES 3.00 is not supported. Supported versions are: 1.10, 1.20, and 1.00 ES

    qemu_gl_create_compile_shader: compile vertex error
    0:2(10): error: GLSL ES 3.00 is not supported. Supported versions are: 1.10, 1.20, and 1.00 ES

    qemu_gl_create_compile_shader: compile fragment error
    0:2(10): error: GLSL ES 3.00 is not supported. Supported versions are: 1.10, 1.20, and 1.00 ES

    Reply to this comment

    Reply to this comment

  5. Salvador:
    Apr 04, 2019 at 12:19 AM

    Sorry, it seems than qemu only supports opengl es 3.0.

    Reply to this comment

    Reply to this comment

    1. Robert Foss:
      Apr 04, 2019 at 02:59 PM

      I think we're running OpenGL ES 3.2 now, with the latest version of the software packages.

      Reply to this comment

      Reply to this comment

  6. Backcrack:
    Sep 03, 2019 at 08:50 AM

    Hi Peoples,

    could this maybe also interested for Virtualbox Drivers With Reactos.org or drivers for Reactos.org with QEMU as setup file for WinXP/Server2003 guests upwards .
    For a Microsoft Free future and a free download WinNT under GPL for us all (because any one should support Reactos, Linux-Brother's under GPL and MS-Hater)

    comes and help

    best regards
    Blacky

    Reply to this comment

    Reply to this comment

  7. Steve:
    Sep 25, 2023 at 04:57 PM

    I assume this post might not be up to date. For example, I don't see autogen.sh anymore in libepoxy. Any suggestion what might needs to be updated here to be up to date?

    Reply to this comment

    Reply to this comment

    1. Bob:
      Sep 25, 2023 at 06:09 PM

      In the 5+ years since this post was published many open source projects have moved away from autotools based build systems to more modern alternatives.
      For most (all?) of the components involved here, they went to the meson build system.
      See https://mesonbuild.com/Running-Meson.html for general meson guidance. In particular, take note of the `--prefix` option for specifying an install prefix.

      Reply to this comment

      Reply to this comment

      1. Steve:
        Sep 25, 2023 at 09:01 PM

        Wow, thank you Bob for the quick reply.

        Yes, sharing some up to date instructions with Meson as you pointed out.

        meson, libepoxy, virglrenderer instructions.

        https://mesonbuild.com/SimpleStart.html#linux1

        https://github.com/anholt/libepoxy#building

        https://gitlab.freedesktop.org/virgl/virglrenderer

        Reply to this comment

        Reply to this comment


Add a Comment






Allowed tags: <b><i><br>Add a new comment:


Search the newsroom

Latest Blog Posts

Automatic regression handling and reporting for the Linux Kernel

14/03/2024

In continuation with our series about Kernel Integration we'll go into more detail about how regression detection, processing, and tracking…

Almost a fully open-source boot chain for Rockchip's RK3588!

21/02/2024

Now included in our Debian images & available via our GitLab, you can build a complete, working BL31 (Boot Loader stage 3.1), and replace…

What's the latest with WirePlumber?

19/02/2024

Back in 2022, after a series of issues were found in its design, I made the call to rework some of WirePlumber's fundamentals in order to…

DRM-CI: A GitLab-CI pipeline for Linux kernel testing

08/02/2024

Continuing our Kernel Integration series, we're excited to introduce DRM-CI, a groundbreaking solution that enables developers to test their…

Persian Rug, Part 4 - The limitations of proxies

23/01/2024

This is the fourth and final part in a series on persian-rug, a Rust crate for interconnected objects. We've touched on the two big limitations:…

How to share code between Vulkan and Gallium

16/01/2024

One of the key high-level challenges of building Mesa drivers these days is figuring out how to best share code between a Vulkan driver…

Open Since 2005 logo

We use cookies on this website to ensure that you get the best experience. By continuing to use this website you are consenting to the use of these cookies. To find out more please follow this link.

Collabora Ltd © 2005-2024. All rights reserved. Privacy Notice. Sitemap.