Skip to content

dmaivel/sharedgl

Repository files navigation

SharedGL license

SharedGL is an OpenGL 4.6 implementation that enables 3D acceleration for Windows and Linux guests within QEMU/KVM by streaming OpenGL commands over shared memory or sockets.

Click to hide: Preview

preview

Click to reveal: Table of contents
  1. How it works
  2. Building the server
  3. Running the server
  4. Connecting the guest
  5. Troubleshooting
  6. Showcase

How it works

SharedGL has two halves:

  • Server (sglrenderer) which runs on the host, Linux only. Receives OpenGL commands and renders them in a window on the host.
  • Client (ICD / libGL) which runs in the guest. Installed inside the VM so that OpenGL applications there transparently forward their calls to the server.

The two halves communicate through one of two transports:

Transport Speed Setup
Shared memory Faster Default, requires an ivshmem device on the VM and a kernel driver in the guest.
Network socket Slower No drivers, no VM config. It works anywhere with a network connection, so it's not restricted to just VMs.

You pick the transport when you start the server. The rest of this README follows that order: build the server, run it, then connect a guest.

Building the server

Dependencies

Name Version
CMake 3.15+
libepoxy Latest
SDL2 2.24.0+

Prebuilt tarball

If you just want to run the Linux server, you can download the Linux release tarball instead of building from source.

Build

git clone https://github.com/dmaivel/sharedgl.git
cd sharedgl
mkdir build && cd build
cmake ..
cmake --build . --target sglrenderer --config Release

The server can only be built and run on a Linux host.

If you also want the Linux client library (libGL) for use on the host or to copy into a Linux guest, build the sharedgl-core target instead. libx11 is required for this.

Build options

Pass these to cmake with -D..., or edit them via ccmake build.

Option Values Default Description
LINUX_LIB32 ON/OFF OFF Build the Linux client library as 32-bit. Does not affect the server.

Running the server

usage: sglrenderer [-h] [-v] [-o] [-n] [-x] [-g MAJOR.MINOR]
                   [-r WIDTHxHEIGHT] [-m SIZE] [-p PORT]
Flag Description
-h Show help
-v Print sample VM configuration for the current settings
-o Enable FPS overlay on clients
-n Use networking instead of shared memory
-x Remove the shared memory file (useful for cleanup)
-g MAJOR.MINOR Report a specific OpenGL version (default: 4.6)
-r WxH Max resolution (default: 1920x1080)
-m SIZE Max memory in MiB (default: 32)
-p PORT Port when -n is used (default: 3000)

The server must be running on the host before you start the guest. If you extracted a Linux release tarball, run ./sglrenderer from the extracted root.

Connecting the guest

Choosing a transport

Before you install anything in the guest, decide how the guest will reach the server:

  • Shared memory: default, faster. You'll need to add an ivshmem device to the VM and install a kernel driver in the guest.
  • Networking: driverless, simpler, much slower. Start the server with -n, and set SGL_NETWORK_ENDPOINT=<host-ip>:<port> as an environment variable inside the guest.

VM configuration for shared memory

Run sglrenderer -v to get configuration snippets matched to your current settings. For reference:

libvirt:

<!-- SAMPLE, place inside <devices> -->
<devices>
    ...
    <shmem name="sharedgl_shared_memory">
        <model type="ivshmem-plain"/>
        <size unit="M">??</size>
    </shmem>
</devices>

qemu:

# SAMPLE
qemu-system-x86_64 \
  -object memory-backend-file,size=??M,share,mem-path=/dev/shm/sharedgl_shared_memory,id=sharedgl_shared_memory

Windows guest

A Windows guest needs two things: a kernel driver (for shared memory only) and the OpenGL client library (the ICD).

1. Kernel driver

Pick one of the three options below.

Option A: Stock VirtIO IVSHMEM driver (single client only)

  1. Download and extract the upstream VirtIO Win drivers.
  2. Go to ...\virtio-win-upstream\Win10\amd64\.
  3. Right-click ivshmem.inf and choose Install.

Option B: Stock VirtIO IVSHMEM driver + runtime patch (multi-client)

Same driver as Option A, but patched at runtime by ntoseye to allow multiple clients. The patch must be re-applied every time the VM boots.

  1. Follow Option A to install the stock driver.
  2. Install and run ntoseye (see its README if you hit issues).
  3. In the ntoseye console, run:
    lm ivshmem                          # prints start address
    s <start> 4883792000740a 0x3000     # prints match address
    f <match> 4883792000eb0a            # applies the patch
    continue
    quit
    

Option C: Bundled ksgldrv driver (multi-client, Windows 10)

Requires enabling test-signing once:

bcdedit.exe -set testsigning on

Then either install from a release or build from source:

Install from release (release 0.4.0)
  1. Download and extract the latest Windows release.
  2. Right-click ksgldrv.inf and choose Install.
Build from source (Visual Studio Developer Command Prompt)

Install the WDK first, then:

:: from the sharedgl directory
mkdir build
cd build
cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DWINKERNEL=ON ..
cmake --build . --target ksgldrv --config Release
cd ..
xcopy .\scripts\kcertify.bat .\build\Release\kcertify.bat
xcopy .\scripts\ksgldrv.inf .\build\Release\ksgldrv.inf
cd build\Release
call kcertify.bat 10_X64

:: requires admin, or right-click ksgldrv.inf and choose Install
pnputil -i -a ksgldrv.inf

The default target is 10_X64. For other or additional Windows versions, pass them to kcertify.bat (e.g. kcertify.bat 10_X64,10_NI_X64). See the OS version list.

2. Client library (ICD)

Install from a release or build from source.

Install from release (>= 0.3.1)
  1. Download and extract the latest Windows release.
  2. Run wininstall.bat as administrator.

Any OpenGL application (32-bit or 64-bit) will now route through SharedGL.

Build from source (Visual Studio Developer Command Prompt)
:: from the sharedgl directory
mkdir build
cd build
:: add -DWINKERNEL=OFF if you hit WDK errors
cmake -DCMAKE_GENERATOR_PLATFORM=x64 ..
cmake --build . --target sharedgl-core --config Release
cmake -DCMAKE_GENERATOR_PLATFORM=Win32 ..
cmake --build . --target sharedgl-core --config Release
cd ..
xcopy .\scripts\wininstall.bat .\build\Release\wininstall.bat
cd build\Release
call wininstall.bat

Linux guest

Although it's possible to use SharedGL with Linux guests, there is little reason to given first-class 3D acceleration support via virtio/virgl.

A Linux guest needs a kernel module (for shared memory only) and the client library.

1. Kernel module

Build inside the guest, then load with the provided installer:

cd kernel/linux
make
./install.sh

If the module doesn't auto-load on boot, add sharedgl to your modprobe config.

2. Client library

Build sharedgl-core as described in Building the server, or use the packaged client libraries from the Linux release tarball. Then point your loader at the client directory:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/sharedgl/lib
glxgears

Use lib32/ instead of lib/ for 32-bit applications. Some applications also need LD_PRELOAD set to the same directory.

Linux host (no VM)

The Linux client library also works directly on the host, useful for debugging without a VM. Build sharedgl-core or use the packaged tarball, set LD_LIBRARY_PATH as shown in the Linux guest section, and run your application.

Environment variables

Once the client is installed, these variables tune its behavior. SGL_NETWORK_ENDPOINT is required when the server is running in networking mode; the rest are optional. Variables marked host inherit from the server when not overridden.

Boolean env vars can only be enabled by setting them to true, not 1 or on.

Variable Values Default Platform Description
SGL_NETWORK_ENDPOINT IP:Port Windows, Linux Required in the guest when networking is enabled.
SGL_WINED3D_DONT_VFLIP boolean false Windows Set to true when running DirectX apps through WineD3D so the framebuffer renders right-side up.
SGL_RUN_WITH_LOW_PRIORITY boolean false Windows Runs the client at IDLE_PRIORITY_CLASS. Can improve smoothness on VMs with fewer vCPUs than host cores, or when using networking.
GL_VERSION_OVERRIDE D.D host Windows, Linux Override the reported OpenGL version.
GLX_VERSION_OVERRIDE D.D 1.4 Linux Override the reported GLX version.
GLSL_VERSION_OVERRIDE D.D Windows, Linux Override the reported GLSL version.

Troubleshooting

Client logs glimpl_init: failed to find memory

The VM doesn't have a shared memory device attached. Add the ivshmem config from VM configuration for shared memory, or switch to networking.

Server logs `err: failed to open shared memory 'sharedgl_shared_memory'

The shared memory file already exists with different permissions. Shut down the VM, run sudo ./sglrenderer -x to remove it, then start the server and VM again. Running the server with sudo is a shorter-term workaround.

Application stalls in the VM (process starts but hangs)

  • Confirm the server is running on the host. If it is and the app still stalls, shut down the VM, run sudo ./sglrenderer -x, restart the server, then boot the VM.
  • Confirm the driver is installed (VirtIO IVSHMEM or ksgldrv on Windows; sharedgl.ko on Linux).

Blank window in the VM

The shared memory device likely isn't sized to cover all the memory the server allocates. Check the <size> in your VM config against the server's -m value.

Crashes like IOT instruction or No provider of glXXX found.

  • Try a lower reported GL version: -g 2.0 or env vars
  • Give the server more memory: -m 256

GLFW apps report "Entry point retrieval is broken"

Use LD_PRELOAD with the client library.

Linux guest crashes with SIGILL

The client library was built on a host with a different CPU than the guest sees.

Showcase

Click to reveal: Running SuperTuxKart in a Windows virtual machine
2024-06-28.19-58-59.mp4
Click to reveal: Running a DirectX sample via WineD3D in a Windows virtual machine
2024-07-07.20-21-06.mp4
Click to reveal: Running minetest in a Windows virtual machine (old)
winminetest.mp4
Click to reveal: Running glxgears in a Windows virtual machine (old)
wingears.mov
Click to reveal: Running glxgears in a Linux virtual machine (old)
glxgears.mov
Click to reveal: Running a compute shader in a Linux virtual machine (old)
compute.mov

Packages

 
 
 

Contributors

Languages