Skip to content

Laptop / Hybrid GPU Power Management Issue (NVIDIA, iGPU + dGPU) #1776

Description

@itsmedardan

Overview

I've been thoroughly enjoying Omarchy over the past few weeks. However, I've noticed a significant drop in battery life on my laptop. The main culprit appears to be the NVIDIA dGPU, which remains active even when not in use. It does not enter low-power states such as sleep, suspend, or d3cold, resulting in unnecessary power drain.

My goal is to set up a proper hybrid GPU configuration, where the Intel iGPU handles all general rendering tasks, and the NVIDIA dGPU is only activated on-demand for specific applications (e.g., via prime-run). I have achieved this setup successfully in the past on Arch Linux using tools like envycontrol and prime-run.


❌ Current Behavior

  • The NVIDIA dGPU remains active at all times, even when no applications explicitly require it.
  • Running sudo lsof /dev/nvidia* 2>/dev/null shows Hyprland, Walker, and other apps using the dGPU.
  • nvtop confirms that walker is utilizing the dGPU.
  • I have followed the official Hyprland Multi-GPU Guide, and I'm currently using:
  • And also using envycontrol -s hybrid

✅ Expected Behavior

  1. iGPU as Default - All regular rendering tasks, including the Wayland compositor (Hyprland), should default to the Intel iGPU.
  2. dGPU On-Demand - The NVIDIA dGPU should only be activated when launching applications with prime-run or other explicit offloading methods.
  3. dGPU Power Saving - When idle, the NVIDIA dGPU should transition into a low-power state (e.g., d3cold), conserving battery life.

Steps I have taken and guide

📦 1. Create Persistent GPU Symlinks with udev

This prevents /dev/dri/card0, /dev/dri/card1 shuffling between reboots.

🔧 Script: gpu-symlinks.sh

#!/bin/bash

declare -A GPU_SYMLINKS=(
    ["Intel"]="intel-igpu"
    ["AMD"]="amd-igpu"
    ["NVIDIA"]="nvidia-dgpu"
)

UDEV_DIR="/etc/udev/rules.d"
GPU_LIST=$(lspci -d ::03xx)

if [ -z "$GPU_LIST" ]; then
    echo "No GPUs detected!"
    exit 1
fi

for VENDOR in "${!GPU_SYMLINKS[@]}"; do
    PCI_ID=$(echo "$GPU_LIST" | grep "$VENDOR" | head -n1 | cut -f1 -d' ')
    [ -z "$PCI_ID" ] && continue

    SYMLINK_NAME="${GPU_SYMLINKS[$VENDOR]}"
    RULE_PATH="$UDEV_DIR/${SYMLINK_NAME}-dev-path.rules"

    echo "Creating udev rule for $VENDOR GPU at $PCI_ID → /dev/dri/$SYMLINK_NAME"

    UDEV_RULE=$(cat <<EOF
KERNEL=="card*", \\
KERNELS=="0000:$PCI_ID", \\
SUBSYSTEM=="drm", \\
SUBSYSTEMS=="pci", \\
SYMLINK+="dri/$SYMLINK_NAME"
EOF
    )

    echo "$UDEV_RULE" | sudo tee "$RULE_PATH" > /dev/null
done

echo "Reloading udev rules..."
sudo udevadm control --reload
sudo udevadm trigger

✅ Result

/dev/dri/intel-igpu     -> card0
/dev/dri/nvidia-dgpu    -> card1

These symlinks always point to the correct GPU regardless of boot order.

⚙️ 2. Configure Hyprland to Use iGPU
In your ~/.config/uwsm/env-hyprland or systemd environment for Hyprland:

export AQ_DRM_DEVICES="/dev/dri/intel-igpu:/dev/dri/nvidia-dgpu"

This sets iGPU as the primary renderer and allows fallback to dGPU (for external monitors or specific apps).

🧪 3. Set EnvyControl to Hybrid Mode

sudo pacman -S envycontrol
sudo envycontrol -s hybrid

This enables dynamic GPU offloading: iGPU is default, dGPU available for apps via offload.

🎮 4. Run Apps on the NVIDIA dGPU (When Needed)
Use prime-run or explicit environment variables:

prime-run blender
prime-run resolve
prime-run steam

Manual example:

__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia blender

🛑 5. Don’t Force NVIDIA Globally in Hyprland
Avoid this in your Hyprland config:

# ❌ Do NOT use when running on iGPU
# env = NVD_BACKEND,direct
# env = LIBVA_DRIVER_NAME,nvidia
# env = __GLX_VENDOR_LIBRARY_NAME,nvidia

These force NVIDIA rendering globally and can break iGPU setups.

🔋 6. Optional: Enable NVIDIA Power Management
To auto-disable dGPU when not in use:

sudo pacman -S nvidia-prime

Create config:

sudo tee /etc/modprobe.d/nvidia-power-management.conf <<EOF
options nvidia NVreg_DynamicPowerManagement=0x02
EOF

Start persistence daemon:

sudo systemctl enable nvidia-persistenced.service
sudo systemctl start nvidia-persistenced.service

Check power state:

cat /proc/driver/nvidia/gpus/0000*/power

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions