> ## Documentation Index
> Fetch the complete documentation index at: https://hyperscape-ai-mintlify-docs-update.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# GPU Rendering for Streaming

> Configure hardware GPU rendering for WebGPU streaming on Vast.ai and cloud containers

## Overview

Hyperscape streaming requires **hardware GPU rendering** for WebGPU support. The game uses Three.js Shading Language (TSL) which compiles to WGSL and requires WebGPU—software rendering is not supported.

<Warning>
  Software rendering (Xvfb, SwiftShader, Lavapipe) is **NOT supported**. WebGPU requires hardware GPU acceleration.
</Warning>

## GPU Rendering Modes

The deployment system supports two GPU rendering modes, automatically detected based on container capabilities:

### 1. Xorg Mode (Preferred)

**Requirements:**

* DRM/DRI device access (`/dev/dri/card0` or similar)
* NVIDIA GPU with working drivers
* X server support

**Advantages:**

* Full hardware GPU acceleration
* Best performance
* Lowest latency
* Supports all WebGPU features

**Configuration:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
export DISPLAY=:99
export DUEL_CAPTURE_USE_XVFB=false
export GPU_RENDERING_MODE=xorg
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
```

**Xorg Setup:**

The deployment script automatically configures Xorg for headless GPU rendering:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Auto-detect GPU BusID
GPU_BUS_ID=$(nvidia-smi --query-gpu=pci.bus_id --format=csv,noheader | head -1)

# Generate Xorg config
cat > /etc/X11/xorg-nvidia-headless.conf << EOF
Section "ServerLayout"
    Identifier     "Layout0"
    Screen      0  "Screen0"
EndSection

Section "Device"
    Identifier     "Device0"
    Driver         "nvidia"
    BusID          "PCI:1:0:0"
    Option         "AllowEmptyInitialConfiguration" "True"
    Option         "UseDisplayDevice" "None"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
        Virtual    1920 1080
    EndSubSection
EndSection
EOF

# Start Xorg
Xorg :99 -config /etc/X11/xorg-nvidia-headless.conf -noreset &
```

**Verification:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check Xorg is running
xdpyinfo -display :99

# Check GPU rendering
DISPLAY=:99 glxinfo | grep "OpenGL renderer"
# Should show: NVIDIA GeForce RTX ...
```

### 2. Headless EGL Mode (Fallback)

**Requirements:**

* NVIDIA GPU with EGL support
* No DRM/DRI device access required
* Chrome's new headless mode

**Advantages:**

* Works in containers without DRM/DRI access
* No X server required
* Ideal for Vast.ai containers
* Still uses hardware GPU via NVIDIA EGL

**Configuration:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
export DISPLAY=
export STREAM_CAPTURE_HEADLESS=new
export STREAM_CAPTURE_USE_EGL=true
export GPU_RENDERING_MODE=headless-egl
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
```

**Chrome Flags:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
--headless=new                    # Chrome's new headless mode
--use-gl=egl                      # Use EGL directly
--ozone-platform=headless         # Headless Ozone platform
--enable-features=VaapiVideoDecoder,VaapiVideoEncoder  # GPU video encoding
```

**Verification:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check EGL library exists
ls -la /usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.0

# Test Chrome with EGL
google-chrome-unstable --headless=new --use-gl=egl --enable-unsafe-webgpu \
  --screenshot=test.png https://get.webgl.org/webgpu/
```

## Automatic GPU Detection

The `scripts/deploy-vast.sh` script automatically detects and configures the best GPU rendering mode:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# 1. Check for DRI devices
if [ -d "/dev/dri" ] && [ -e "/dev/dri/card0" ]; then
    # DRI available → Use Xorg mode
    export GPU_RENDERING_MODE=xorg
    export DISPLAY=:99
    export DUEL_CAPTURE_USE_XVFB=false
    # Start Xorg with NVIDIA config
else
    # No DRI → Use headless EGL mode
    export GPU_RENDERING_MODE=headless-egl
    export DISPLAY=
    export STREAM_CAPTURE_HEADLESS=new
    export STREAM_CAPTURE_USE_EGL=true
fi

# 2. Force NVIDIA-only Vulkan ICD (avoid Mesa conflicts)
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
```

## Environment Variables

### GPU Rendering Configuration

| Variable                | Values                                    | Description                         |
| ----------------------- | ----------------------------------------- | ----------------------------------- |
| `GPU_RENDERING_MODE`    | `xorg`, `headless-egl`                    | Rendering mode (auto-detected)      |
| `DISPLAY`               | `:99`, empty                              | X display (empty for headless EGL)  |
| `DUEL_CAPTURE_USE_XVFB` | `true`, `false`                           | Use Xvfb (deprecated, always false) |
| `VK_ICD_FILENAMES`      | `/usr/share/vulkan/icd.d/nvidia_icd.json` | Force NVIDIA Vulkan ICD             |

### Chrome Capture Configuration

| Variable                        | Values                 | Description      |
| ------------------------------- | ---------------------- | ---------------- |
| `STREAM_CAPTURE_HEADLESS`       | `false`, `new`, `true` | Headless mode    |
| `STREAM_CAPTURE_USE_EGL`        | `true`, `false`        | Use EGL directly |
| `STREAM_CAPTURE_CHANNEL`        | `chrome-dev`           | Browser channel  |
| `STREAM_CAPTURE_ANGLE`          | `vulkan`, `gl`         | ANGLE backend    |
| `STREAM_CAPTURE_DISABLE_WEBGPU` | `true`, `false`        | Disable WebGPU   |

## System Requirements

### NVIDIA Drivers

**Required:**

* NVIDIA GPU (RTX 3060 Ti or better)
* NVIDIA driver version 525+ (for Vulkan 1.3)
* Vulkan ICD installed

**Installation:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check driver version
nvidia-smi

# Install Vulkan tools
apt-get install -y \
    mesa-vulkan-drivers \
    vulkan-tools \
    libvulkan1

# Verify Vulkan
vulkaninfo --summary
```

### Xorg Dependencies (Xorg Mode)

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
apt-get install -y \
    xserver-xorg-core \
    xserver-xorg-video-nvidia-XXX \
    x11-xserver-utils \
    mesa-utils \
    libglvnd0 \
    libgl1 \
    libglx0
```

Replace `XXX` with your NVIDIA driver version (e.g., `525`, `535`).

### EGL Dependencies (Headless EGL Mode)

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
apt-get install -y \
    libegl1 \
    libgles2 \
    mesa-utils \
    libglvnd0
```

## Chrome Dev Channel

WebGPU support requires Chrome Dev channel (google-chrome-unstable):

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Install Chrome Dev
wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
apt-get update
apt-get install -y google-chrome-unstable

# Verify installation
google-chrome-unstable --version
```

**Playwright Configuration:**

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const browser = await chromium.launch({
  channel: 'chrome-dev',  // Maps to google-chrome-unstable
  headless: false,        // or 'new' for headless EGL
  args: [
    '--use-gl=egl',       // or '--use-gl=angle'
    '--use-angle=vulkan', // if using ANGLE
    '--enable-unsafe-webgpu',
  ]
});
```

## Vulkan Configuration

### Force NVIDIA ICD

Vast.ai containers may have conflicting Mesa Vulkan ICDs. Force NVIDIA-only:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
```

**Why This Matters:**

* Mesa ICDs can conflict with NVIDIA drivers
* Some Mesa ICDs are misconfigured (point to wrong libraries)
* Forcing NVIDIA ICD ensures hardware Vulkan works correctly

**Verification:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check which ICD is being used
vulkaninfo | grep "deviceName"
# Should show: NVIDIA GeForce RTX ...

# List available ICDs
ls /usr/share/vulkan/icd.d/
# Should include: nvidia_icd.json
```

### Vulkan Troubleshooting

**Problem:** `vulkaninfo` fails with "Cannot create Vulkan instance"

**Causes:**

1. NVIDIA driver not installed
2. Vulkan ICD misconfigured
3. Missing Vulkan libraries

**Solutions:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# 1. Check NVIDIA driver
nvidia-smi
# If fails: Install NVIDIA driver

# 2. Check Vulkan ICD
cat /usr/share/vulkan/icd.d/nvidia_icd.json
# Should point to valid library path

# 3. Check Vulkan libraries
ldconfig -p | grep vulkan
# Should show libvulkan.so.1

# 4. Force NVIDIA ICD
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
vulkaninfo --summary
```

## Deployment Integration

### ecosystem.config.cjs

The PM2 configuration automatically uses GPU rendering settings:

```javascript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
module.exports = {
  apps: [{
    name: "hyperscape-duel",
    env: {
      // GPU Rendering (auto-detected by deploy script)
      GPU_RENDERING_MODE: process.env.GPU_RENDERING_MODE || "xorg",
      DISPLAY: process.env.DISPLAY || "",
      DUEL_CAPTURE_USE_XVFB: "false",
      VK_ICD_FILENAMES: "/usr/share/vulkan/icd.d/nvidia_icd.json",
      
      // Chrome Capture
      STREAM_CAPTURE_HEADLESS: process.env.STREAM_CAPTURE_HEADLESS || "false",
      STREAM_CAPTURE_USE_EGL: process.env.STREAM_CAPTURE_USE_EGL || "false",
      STREAM_CAPTURE_CHANNEL: "chrome-dev",
      STREAM_CAPTURE_ANGLE: "vulkan",
      STREAM_CAPTURE_DISABLE_WEBGPU: "false",
    }
  }]
};
```

### deploy-vast.sh

The deployment script handles GPU detection and configuration:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
#!/bin/bash
# GPU Rendering Setup

# 1. Verify NVIDIA GPU
if ! nvidia-smi &>/dev/null; then
    echo "FATAL: NVIDIA GPU not accessible"
    exit 1
fi

# 2. Check for DRI devices
if [ -d "/dev/dri" ] && [ -e "/dev/dri/card0" ]; then
    # Xorg mode
    export GPU_RENDERING_MODE=xorg
    export DISPLAY=:99
    export DUEL_CAPTURE_USE_XVFB=false
    
    # Start Xorg
    Xorg :99 -config /etc/X11/xorg-nvidia-headless.conf &
    sleep 5
    
    # Verify Xorg
    if xdpyinfo -display :99 >/dev/null 2>&1; then
        echo "✓ Xorg started successfully"
    else
        echo "Xorg failed, falling back to headless EGL"
        export GPU_RENDERING_MODE=headless-egl
        export DISPLAY=
        export STREAM_CAPTURE_HEADLESS=new
        export STREAM_CAPTURE_USE_EGL=true
    fi
else
    # Headless EGL mode
    export GPU_RENDERING_MODE=headless-egl
    export DISPLAY=
    export STREAM_CAPTURE_HEADLESS=new
    export STREAM_CAPTURE_USE_EGL=true
fi

# 3. Force NVIDIA Vulkan ICD
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json

# 4. Start PM2 with GPU environment
bunx pm2 start ecosystem.config.cjs
```

## Troubleshooting

### Black Screen in Stream

**Symptom:** Stream shows black screen instead of game

**Diagnosis:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# 1. Check GPU access
nvidia-smi

# 2. Check Vulkan
vulkaninfo --summary

# 3. Check display (Xorg mode)
xdpyinfo -display :99

# 4. Check Chrome GPU status
# Navigate to chrome://gpu in the capture browser
# Should show: "WebGPU: Hardware accelerated"
```

**Solutions:**

**If Xorg mode:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check Xorg logs
cat /var/log/Xorg.99.log | tail -50

# Restart Xorg
pkill Xorg
Xorg :99 -config /etc/X11/xorg-nvidia-headless.conf &
```

**If headless EGL mode:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check EGL library
ls -la /usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.0

# Test Chrome with EGL
google-chrome-unstable --headless=new --use-gl=egl \
  --enable-unsafe-webgpu --screenshot=test.png \
  https://get.webgl.org/webgpu/
```

### WebGPU Not Available

**Symptom:** Chrome reports "WebGPU not supported"

**Diagnosis:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Check Chrome GPU info
google-chrome-unstable --headless=new --use-gl=egl \
  --enable-unsafe-webgpu --enable-logging=stderr \
  --log-level=0 https://get.webgl.org/webgpu/ 2>&1 | grep -i webgpu
```

**Common Causes:**

1. **Vulkan ICD not working:**
   ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
   # Force NVIDIA ICD
   export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
   vulkaninfo --summary
   ```

2. **Missing Chrome flags:**
   ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
   # Required flags for WebGPU
   --enable-unsafe-webgpu
   --enable-features=Vulkan,WebGPU
   --ignore-gpu-blocklist
   ```

3. **Wrong GL backend:**
   ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
   # For Xorg mode
   --use-gl=angle --use-angle=vulkan

   # For headless EGL mode
   --use-gl=egl --ozone-platform=headless
   ```

### Vulkan Instance Creation Fails

**Symptom:** `vulkaninfo` fails with "Cannot create Vulkan instance"

**Causes:**

* Conflicting Mesa ICDs
* Broken NVIDIA ICD configuration
* Missing Vulkan libraries

**Solutions:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# 1. Force NVIDIA-only ICD
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json

# 2. Check ICD configuration
cat /usr/share/vulkan/icd.d/nvidia_icd.json
# Should point to valid library path

# 3. Verify library exists
ls -la /usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0

# 4. Test Vulkan
vulkaninfo --summary
```

### DRI Devices Not Available

**Symptom:** `/dev/dri/` directory doesn't exist or is empty

**Cause:** Container doesn't have DRM/DRI device access (common on Vast.ai)

**Solution:** Use headless EGL mode instead of Xorg:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
export GPU_RENDERING_MODE=headless-egl
export DISPLAY=
export STREAM_CAPTURE_HEADLESS=new
export STREAM_CAPTURE_USE_EGL=true
```

**Why This Works:**

* EGL doesn't require DRM/DRI devices
* Chrome's new headless mode supports EGL
* NVIDIA EGL provides hardware GPU access
* WebGPU works via Vulkan over EGL

## Performance Optimization

### GPU Memory

Monitor GPU memory usage:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Watch GPU memory
watch -n 1 nvidia-smi

# Check Chrome GPU memory
# Navigate to chrome://gpu in capture browser
```

**Optimization:**

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Limit texture size
STREAM_CAPTURE_WIDTH=1280
STREAM_CAPTURE_HEIGHT=720

# Reduce quality if needed
STREAM_CDP_QUALITY=70  # Default: 80
```

### CPU Usage

GPU rendering offloads work from CPU:

```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
# Monitor CPU usage
htop

# Check FFmpeg CPU usage
ps aux | grep ffmpeg
```

**Expected CPU usage:**

* Xorg mode: 50-80% (encoding only)
* Headless EGL mode: 60-90% (encoding + EGL overhead)
* Software rendering: 200-300% (NOT SUPPORTED)

## Tested Configurations

| GPU         | Mode         | Status          | Notes                       |
| ----------- | ------------ | --------------- | --------------------------- |
| RTX 3060 Ti | Xorg         | ✅ Working       | Preferred configuration     |
| RTX 4090    | Xorg         | ✅ Working       | Excellent performance       |
| RTX 4090    | Headless EGL | ✅ Working       | Vast.ai containers          |
| RTX 3060 Ti | Headless EGL | ✅ Working       | Vast.ai containers          |
| Any GPU     | Xvfb         | ❌ Not Supported | Software rendering too slow |
| Any GPU     | SwiftShader  | ❌ Not Supported | CPU Vulkan too slow         |
| Any GPU     | Lavapipe     | ❌ Not Supported | CPU Vulkan too slow         |

## Related Documentation

* [Audio Streaming Guide](/devops/audio-streaming) - PulseAudio configuration
* [Deployment Guide](/guides/deployment) - Full deployment process
* [Configuration Reference](/devops/configuration) - Environment variables
* [Troubleshooting](/devops/troubleshooting) - Common issues

## Commit History

Recent GPU rendering improvements:

* **dd649da** (Feb 27, 2026): Fix headless mode flag passing (args vs option)
* **e51a332** (Feb 27, 2026): Add headless EGL mode for containers without DRM
* **30bdaf0** (Feb 27, 2026): Require NVIDIA Xorg, no software rendering fallback
* **5fe4a18** (Feb 27, 2026): Add robust Xorg/Xvfb fallback handling
* **263bfc5** (Feb 27, 2026): Use Xorg instead of Xvfb for NVIDIA GPU rendering
* **89b78e3** (Feb 27, 2026): Use NVIDIA hardware Vulkan instead of SwiftShader
* **54836200** (Feb 27, 2026): Enable SwiftShader for WebGPU (deprecated)
* **ba1cf0a** (Feb 27, 2026): Use Lavapipe software Vulkan (deprecated)
* **ef8033c** (Feb 27, 2026): Use SwiftShader and WebGL fallback (deprecated)
