13

I've installed Manjaro Linux. My graphics card is an Nvidia GTX 1050Ti.

When I boot my computer and try to watch videos, I notice harsh screen tearing. This problem is resolved when I go to the Nvidia X Server Settings and enable the option "Force Full Composition Pipeline".

Is there any way to permanently set this option so that I don't have to manually enable it every time I reboot my computer?

7 Answers 7

15

My laptop is equipped with a Quadro K2100M, running Ubuntu Bionic with KDE Plasma 5.17 (from the neon repo) and using the nvidia-driver-430.

Since I have a different set of configurations for the monitors at home and at work, I needed something dynamic and here is what is working for me:

  1. I wrote the following script to handle the dynamic configuration of the screens (~/bin/force-composition-pipeline.sh):

    #!/bin/bash
    s="$(nvidia-settings -q CurrentMetaMode -t)"
    
    if [[ "${s}" != "" ]]; then
      s="${s#*" :: "}"
      nvidia-settings -a CurrentMetaMode="${s//\}/, ForceCompositionPipeline=On\}}"
    fi
    
  2. I added that script to the autostart:
    chmod +x ~/bin/force-composition-pipeline.sh
    ln -s ~/bin/force-composition-pipeline.sh ~/.config/autostart-scripts/
    
  3. In KDE Plasma settings, in Display and Monitor -> Compositor, I set the Tearing prevention ("vsync") to Never.

Note that I found the non-full ForceCompositionPipeline to be enough for me.

2
  • 2
    Thank you so much! I have been looking for this automatic solution for about more than 1 year....
    – CuongDC
    Commented Sep 8, 2020 at 15:30
  • It works. ForceFullCompositionPipeline works better for me instead of ForceCompositionPipeline
    – Pablo
    Commented Oct 4, 2022 at 19:08
3

Adding to Paradox's answer (since it seems I can't post comments...), I would put that command in ~/.bash_profile rather than in ~/.bashrc.

~/.bashrc is sourced every time you open a new bash session, i.e. every time you open a new terminal emulator window/tab.

On the other hand ~/.bash_profile is sourced only once when you start bash as a login shell, e.g. when you log in a graphical desktop environment. c.f. https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files

EDIT: There's now a better solution to the tearing issue with KWin when using the nvidia proprietary driver; you need to have a recent enough version of kwin, version >= 5.12 [1] and enable modesetting for the nvidia-drm kernel module [2]. I tested that and it works for me with kwin-5.17.80 (git snapshot from openSuse repos) and nvidia 440.26.

EDIT: hmm, there's a side effect to enabling modeset with the nvidia-drm module, resuming from suspend seems to fail...

EDIT (again): it looks like even without enabling modeset with the nvidia-drm module, tearting seems to be gone, for now at least...

[1]https://wiki.archlinux.org/index.php/NVIDIA/Troubleshooting#Avoid_screen_tearing_in_KDE_(KWin) https://phabricator.kde.org/D19867

[2]https://wiki.archlinux.org/index.php/NVIDIA#DRM_kernel_mode_setting

2

You can set the "Force Full Composition Pipeline" option in a terminal, like this:

$ nvidia-settings --assign CurrentMetaMode="nvidia-auto-select +0+0 { ForceFullCompositionPipeline = On }"

To do it automatically, the easiest way to do so is to put it inside your .bashrc. To proceed just type this inside a terminal:

$ echo "$ nvidia-settings --assign CurrentMetaMode=\"nvidia-auto-select +0+0 { ForceFullCompositionPipeline = On }\"" >> ~/.bashrc

You can log out and log back in (or reboot), to have this applied. Note that this is meant to be a one monitor solution only, because of the "auto-select".

Another method would be to do the same inside ~/.nvidia-settings-rc but the behaviour could change over time, while in .bashrc, you are sure on how it is done.

Addendum

Regarding screen tearing, you might want to try other tweaks.

Since you are using Manjaro, I assume you are using KDE. You can tell the window manager (KWin) to use triple buffering or to wait for the current image to be displayed before updating the screen.

1) Wait for the GPU to fully display current image

# echo "export __GL_YIELD=\"USLEEP\"" >> /etc/profile.d/kwin.sh

2) Enable triple buffering in KWin

# echo "export KWIN_TRIPLE_BUFFER=1" >> /etc/profile.d/kwin.sh

Do not have both of the above enabled at the same time. Be sure to enable triple buffering in nvidia-settings if you enable triple buffering in KWin.

1
  • If he has a xorg.conf file it can be added there to make it perm which would be the correct method.
    – Jeight
    Commented Oct 1, 2019 at 22:50
2

you can create a file called /etc/X11/xorg.conf.d/20-nvidia.conf

And add these lines

Section "Device"
        Identifier "Nvidia Card"
        Driver     "nvidia"
        VendorName "NVIDIA Corporation"
        BoardName  "GeForce GTX 1050 Ti"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    Monitor        "Monitor0"
    Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
    Option         "AllowIndirectGLXProtocol" "off"
    Option         "TripleBuffer" "on"
EndSection

more info: https://wiki.archlinux.org/index.php/NVIDIA/Troubleshooting#Bad_performance_after_installing_a_new_driver_version

2

For Single Monitor:

Create a text file and paste this:

[Desktop Entry]
Type=Application
Name=nvidia-force-full-compositon
Exec=nvidia-settings --assign CurrentMetaMode="nvidia-auto-select +0+0 { ForceFullCompositionPipeline = On }"

For Dual Monitor:

if you have a dual monitor you can open this file in text editor: /etc/X11/xorg.conf Then do a search with this word metamodeswith ctrl+F and see what it has configured. mine is something like this:

"metamodes" "DVI-I-0: nvidia-auto-select +1920+0 {ForceCompositionPipeline=On}, HDMI-0: nvidia-auto-select +0+0

so I have created the destop entry like this:

[Desktop Entry]
Type=Application
Name=nvidia-force-full-compositon
Exec=nvidia-settings --assign CurrentMetaMode="nvidia-auto-select +1920+0 {ForceCompositionPipeline=On}, nvidia-auto-select +0+0 { ForceCompositionPipeline = On }"

NOTE: You can either do ForceFullCompositionPipeline or ForceCompositionPipeline only. Just change the text as you need.

save the text file as something like this:

nvidia-force-full-compositon.desktop

where .desktop is essential.

Now copy paste it in ~/.config/autostart

Reboot.

0

Since I sometimes use a dual monitor setup and sometimes a quadruple monitor setup I wanted to have the script a bit more dynamic. Therefore I wrote this script which first retrieves the CurrentMetaMode, analyses it and adds the necessary options if needed to all connected and active monitors.

#!/bin/bash

# Avoids getting this error: Gtk-Message: 21:17:19.921: Failed to load module "xapp-gtk3-module"
extraOpts=("--use-gtk2")

# Set to false if you don't want/need the full composition pipeline
full_composition_pipeline=true

current_meta_mode="$(nvidia-settings "${extraOpts[@]}" --query CurrentMetaMode --terse)"
meta_mode_splitted="${current_meta_mode#*" :: "}"
meta_mode_converted="$(sed -E 's/\b([^: ]+):\s*([^{]+?)\s*\{([^}]+)\}(,\s*|$)/\1:\2:\3:\4\n/g' <<< "$meta_mode_splitted")"

changed=false
new_meta_mode=""
while IFS=":" read -r display resolution options end; do
    if ! [[ "$options" == *"ForceCompositionPipeline=On"* ]]; then
        options="$options, ForceCompositionPipeline=On"
        changed=true
        echo "${display}: Add ForceCompositionPipeline=On"
    fi
    if ! [[ "$options" == *"ForceFullCompositionPipeline=On"* ]] && ${full_composition_pipeline}; then
        options="$options, ForceFullCompositionPipeline=On"
        changed=true
        echo "${display}: Add ForceFullCompositionPipeline=On"
    fi
    new_meta_mode="${new_meta_mode}${display}: ${resolution} {$options}${end}"
done <<< "$meta_mode_converted"

if $changed; then
    nvidia-settings "${extraOpts[@]}" -a CurrentMetaMode="${new_meta_mode}"
fi

Hope that helps.

0

Here is my script with options.
You can choose:

  • either you want to set only the ForceCompositionPipeline

    or also the ForceFullCompositionPipeline

    or unset at all

  • for the first display only

    or for all connected displays

~/bin/nvvsync:

#!/bin/bash

USAGE() {
    echo "${0##*/}         Set only for the first display."
    echo "${0##*/} -a      Set for all displays (bad idea)."
    echo "${0##*/} -f      Set also the 'ForceFullCompositionPipeline'."
    echo "${0##*/} -u      Unset."
    echo "${0##*/} -v      Verbose."
    echo "${0##*/} -h      Show this help."
    exit 1
}
while getopts "afuvh\?" OPTION; do
  case "$OPTION" in
    a )  all_displays=1                           ;;
    f )  full=1                                   ;;
    u )  unset=1                                  ;;
    v )  verbose=1                                ;;
    h )  USAGE                                    ;;
    \?)  USAGE                                    ;;
    * )  echo "Unknown option \"$OPTION\""; USAGE ;;
  esac
done
shift $(($OPTIND-1))

s="$(nvidia-settings -q CurrentMetaMode -t)"
s="${s#*" :: "}"

# Check if more than one display is active
expr "$s" : ".*DPY-2.*" >/dev/null || single_display=1
# Check if ForceCompositionPipeline is already set
expr "$s" : ".*ForceCompositionPipeline=.*" >/dev/null && Comp_is_set=true || Comp_is_set=false
# Check if ForceFullCompositionPipeline is already set
 expr "$s" : ".*ForceFullCompositionPipeline=.*" >/dev/null && FullComp_is_set=true || FullComp_is_set=false

UNSET() {
    if $Comp_is_set; then
        s="$(echo "$s" | sed -rn "s/(,| )?(,| )?ForceCompositionPipeline=(On|Off)//gp")"
    fi
    if $FullComp_is_set; then
        s="$(echo "$s" | sed -rn "s/(,| )?(,| )?FullCompositionPipeline=(On|Off)//gp")"
    fi
    nvidia-settings -a CurrentMetaMode="${s}"
    exit
}
(($unset)) && UNSET

if [[ "${s}" != "" ]]; then
    (($verbose)) && echo -e "Initial:\n${s}\n"

    # Set only for the first display
    if ! (($all_displays)); then
        # CompositionPipeline
        if $Comp_is_set; then
            s="$(echo "$s" | sed -rn '0,/ForceCompositionPipeline/ s/((,| )?(,| )?)ForceCompositionPipeline=(On|Off)/\1ForceCompositionPipeline=On/p')"
        else
            if (($single_display)); then
                s="${s//\}/, ForceCompositionPipeline=On\}}"
            else
                s="$(echo "$s" | sed -rn 's/(DPY-1:.*)(})(, DPY-2)/\1, ForceCompositionPipeline=On\2\3/p')"
            fi
        fi

        # FullCompositionPipeline
        if (($full)); then
            if $FullComp_is_set; then
                s="$(echo "$s" | sed -rn '0,/ForceFullCompositionPipeline/ s/((,| )?(,| )?)ForceFullCompositionPipeline=(On|Off)/\1ForceCompositionPipeline=On/p')"
            else
                if (($single_display)); then
                    s="${s//\}/, ForceFullCompositionPipeline=On\}}"
                else
                    s="$(echo "$s" | sed -rn 's/(DPY-1:.*)(})(, DPY-2)/\1, ForceFullCompositionPipeline=On\2\3/p')"
                fi
            fi
        fi
        (($verbose)) && echo -e "Result:\n${s}"

    # Set for all displays (bad idea)
    else
        # CompositionPipeline
        if $Comp_is_set; then
            s="$(echo "$s" | sed -rn "s/(,| )?(,| )?ForceCompositionPipeline=(On|Off)//gp")"
        fi
        s="${s//\}/, ForceCompositionPipeline=On\}}"
        
        # FullCompositionPipeline
        if (($full)); then
            if $FullComp_is_set; then
                s="$(echo "$s" | sed -rn "s/(,| )?(,| )?FullCompositionPipeline=(On|Off)//gp")"
            fi
            s="${s//\}/, FullCompositionPipeline=On\}}"
        fi
        (($verbose)) && echo -e "Result:\n${s}"
    fi

    nvidia-settings -a CurrentMetaMode="${s}"
fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .