wez / wezterm

A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust
https://wezfurlong.org/wezterm/
Other
17.6k stars 786 forks source link

WebGPU front_end #2756

Closed wez closed 1 year ago

wez commented 1 year ago

I just pushed preliminary support for using wgpu.rs to power an rendering front end in wezterm.

You can enable it by adding front_end = "WebGpu" to your configuration.

When using WebGPU, you will have access to a variety of different rendering backends, depending on your system:

The default behavior is to select the best supported low-power (integrated) GPU available to your system.

You can explicitly select a discrete GPU if you wish by setting webgpu_power_preference = "HighPerformance".

You can explicit request a fallback/software based backend (not recommended, as it will be slow!) by setting webgpu_force_fallback_adapter = true.

You can list the available GPUs using the debug overlay; call the wezterm.gui.enumerate_gpus() function:

image

You can then force the use of one of those if you wish:

return {
   webgpu_preferred_adapter={
      backend="Vulkan",
      device_type="Cpu",
      name="llvmpipe (LLVM 14.0.0, 256 bits)"
   }
}

This is a new backend and likely has some issues that are waiting to be discovered: I'd love to hear about them!

luisiacc commented 1 year ago

using the Dx12 on nvidia makes the font looks weird:

Edit: also happened with internal Intel graphics, just enabling the front_end makes the font looks wider, like in the picture.

with it:

image

without it:

image
wez commented 1 year ago

@luisiacc: I'm seeing the same thing here on linux with nvidia/vulkan. It is reminiscent of this earlier issue:

I'm continuing to dig into this.

Suyashtnt commented 1 year ago

image It seems to just not want to create the adapter at all.

Config

local wezterm = require "wezterm"

return {
    color_scheme = "Catppuccin Mocha",
    font = wezterm.font_with_fallback {
        'JetBrainsMono Nerd Font Mono', -- Comic code breaks the font
        'Noto Color Emoji',
    },
    font_size = 13,
    line_height = 1.6,
    harfbuzz_features = {
        "cv06=1",
        "cv14=1",
        "cv32=1",
        "ss04=1",
        "ss07=1",
        "ss09=1",
    },
    enable_wayland = false, -- https://github.com/wez/wezterm/issues/1701
    front_end = "WebGpu",
    webgpu_force_fallback_adapater = true,
    cursor_blink_ease_in = "EaseIn",
    cursor_blink_ease_out = "EaseOut",
    animation_fps = 120,
    cursor_blink_rate = 800,
    cursor_thickness = 1.0,
    default_cursor_style = "BlinkingBar",
    initial_rows = 17,
    initial_cols = 70,
    window_padding = {
        left = 12,
        right = 12,
        top = 12,
        bottom = 12,
    },
    window_frame = {
        inactive_titlebar_bg = '#171723',
        active_titlebar_bg = '#171723',
        inactive_titlebar_fg = '#9399b2',
        active_titlebar_fg = '#cdd6f4',
        font = wezterm.font { family = 'Inter', weight = 'Bold' },
    },
    colors = {
        tab_bar = {
            active_tab = {
                bg_color = '#1e1e2e',
                fg_color = '#cdd6f4',
                intensity = 'Bold',
            },
            inactive_tab = {
                bg_color = '#313244',
                fg_color = '#9399b2',
            },
                        inactive_tab_hover = {
                                bg_color = '#11111b',
                                fg_color = '#cdd6f4',
                        },
            new_tab = {
                bg_color = '#181825',
                fg_color = '#cdd6f4',
            },
            new_tab_hover = {
                                bg_color = '#1e1e2e',
                                fg_color = '#cdd6f4',
                        },
        },
    },
}
wez commented 1 year ago

@Suyashtnt start wezterm using wezterm -n then press CTRL-SHIFT-L to open the Debug Overlay, then type wezterm.gui.enumerate_gpus() and press enter; please copy and paste the output from the terminal here.

Suyashtnt commented 1 year ago
> wezterm.gui.enumerate_gpus()
[
    {
        "backend": "Gl",
        "device": 0,
        "device_type": "Other",
        "name": "NVIDIA GeForce GTX 1660 SUPER/PCIe/SSE2",
        "vendor": 4318,
    },
]
cairijun commented 1 year ago

WebGpu (with Vulkan) seems noticeably smoother than OpenGL on my Windows, though no much difference on my another Linux x11 laptop. That's quite impressive!

Some font rendering issues noticed:

  1. selected glyphs look faint, especially when freetype_render_target = 'Normal'
  2. un-selected glyphs get a little bit thicker on WebGpu than OpenGL, especially when freetype_render_target = 'HorizontalLcd'

webgpu_lcd opengl_lcd webgpu_normal opengl_normal

Windows 10 on name=Intel(R) UHD Graphics 630, device_type=IntegratedGpu, backend=Vulkan, driver=Intel Corporation, driver_info=Intel driver, vendor=32902, device=16024

jokeyrhyme commented 1 year ago

Okay, I have what might be a weird hardware combination: AMD Ryzan 7950X (integrated GPU) + AMD Radeon RX 6800XT (discrete GPU) + monitor plugged into 6800XT (oops, forgot to say Archlinux btw, with wezterm packaged from this commit: https://github.com/wez/wezterm/commit/49b9839fdb41eff4d2aae3bb91e6a4befb9cd20b )

> wezterm.gui.enumerate_gpus()
[
    {
        "backend": "Vulkan",
        "device": 29631,
        "device_type": "DiscreteGpu",
        "driver": "radv",
        "driver_info": "Mesa 22.2.3",
        "name": "AMD Radeon RX 6800 XT (RADV NAVI21)",
        "vendor": 4098,
    },
    {
        "backend": "Vulkan",
        "device": 5710,
        "device_type": "IntegratedGpu",
        "driver": "radv",
        "driver_info": "Mesa 22.2.3",
        "name": "AMD Radeon Graphics (RADV GFX1036)",
        "vendor": 4098,
    },
    {
        "backend": "Gl",
        "device": 0,
        "device_type": "Other",
        "name": "AMD Radeon RX 6800 XT (navi21, LLVM 14.0.6, DRM 3.48, 6.0.9-arch1-1)",
        "vendor": 4098,
    },
]
>
Tests with `AMD_VULKAN_ICD=RADV wezterm` (and with compositor launched with RADV): - with just `front_end = "WebGpu"` -> > ERROR wezterm_gui > running message loop: Error while flushing display: Broken pipe (os error 32); terminating - with `front_end = "WebGpu"` and `webgpu_power_preference = "HighPerformance"` - > wezterm window appears with my shell, but is either non-responsive or isn't updating to show my input - with `front_end = "WebGpu"` and `webgpu_force_fallback_adapter = true` -> > ERROR wezterm_gui::frontend > Failed to create window: no compatible adapter found. Available: name=AMD Radeon RX 6800 XT (RADV NAVI21), device_type=DiscreteGpu, backend=Vulkan, driver=radv, driver_info=Mesa 22.2.3, vendor=4098, device=29631, compatible=yes > name=AMD Radeon Graphics (RADV GFX1036), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 22.2.3, vendor=4098, device=5710, compatible=yes > name=AMD Radeon RX 6800 XT (navi21, LLVM 14.0.6, DRM 3.48, 6.0.9-arch1-1), device_type=Other, backend=Gl, vendor=4098, device=0, compatible=yes
Tests with `AMD_VULKAN_ICD=AMDVLK wezterm` (but with compositor launched with RADV): - with just `front_end = "WebGpu"` -> > ERROR wgpu::backend::direct > Error in Adapter::request_device: not enough memory left > ERROR wezterm_gui::frontend > Failed to create window: Requesting a device failed ( probably https://github.com/GPUOpen-Drivers/AMDVLK/issues/305 ) - with `front_end = "WebGpu"` and `webgpu_power_preference = "HighPerformance"` - > > ERROR wgpu::backend::direct > Error in Adapter::request_device: not enough memory left > ERROR wezterm_gui::frontend > Failed to create window: Requesting a device failed - with `front_end = "WebGpu"` and `webgpu_force_fallback_adapter = true` -> > ERROR wezterm_gui::frontend > Failed to create window: no compatible adapter found. Available: > name=Null hardware (RADV NAVI10), device_type=DiscreteGpu, backend=Vulkan, driver=radv, driver_info=Mesa 22.2.3, vendor=4098, device=29456, compatible=yes > name=AMD Radeon RX 6800 XT (navi21, LLVM 14.0.6, DRM 3.48, 6.0.9-arch1-1), device_type=Other, backend=Gl, vendor=4098, device=0, compatible=yes
Tests with `AMD_VULKAN_ICD=AMDVLK wezterm` (and with compositor launched with AMDVLK): - with just `front_end = "WebGpu"` -> > ERROR wgpu::backend::direct > Error in Adapter::request_device: not enough memory left > ERROR wezterm_gui::frontend > Failed to create window: Requesting a device failed ( probably https://github.com/GPUOpen-Drivers/AMDVLK/issues/305 ) - with `front_end = "WebGpu"` and `webgpu_power_preference = "HighPerformance"` - > > ERROR wgpu::backend::direct > Error in Adapter::request_device: not enough memory left > ERROR wezterm_gui::frontend > Failed to create window: Requesting a device failed - with `front_end = "WebGpu"` and `webgpu_force_fallback_adapter = true` -> > ERROR wezterm_gui::frontend > Failed to create window: no compatible adapter found. Available: > name=Null hardware (RADV NAVI10), device_type=DiscreteGpu, backend=Vulkan, driver=radv, driver_info=Mesa 22.2.3, vendor=4098, device=29456, compatible=yes > name=AMD Radeon RX 6800 XT (navi21, LLVM 14.0.6, DRM 3.48, 6.0.9-arch1-1), device_type=Other, backend=Gl, vendor=4098, device=0, compatible=yes

It's interesting to me that even when everything is using AMDVLK, that output still says "driver=radv", but maybe this is normal?

wez commented 1 year ago

especially when freetype_render_target = 'HorizontalLcd'

@cairijun: HorizontalLcd doesn't currently have correct logic for subpixel AA in the shader in WebGPU mode. It's a bit of a PITA to make it work correctly with alpha blending, requiring multiple render passes. In the OpenGL front-end we use a feature called dual source blending, but that isn't supported in wgpu. On modern high density displays you don't really need it anyway.

wez commented 1 year ago

@jokeyrhyme re: 'no compatible adapter found' messages, followed by a list that shows that all adapters are compatible. That is shown after trying to match the power preference and force-fallback preference using a wgpu built-in function. I'll do something to refine the error message.

For more flexible selection of the underlying adapter, it might make sense to put something like this into your config file:

local adapter = nil
local front_end = nil

for _, gpu in wezterm.gui.enumerate_gpus() do
   if gpu.backend == "Vulkan" and gpu.device_type == "Integrated" then
     adapter = gpu
     front_end = "WebGpu"
     break
   end
end

return {
   webgpu_preferred_adapter = adapter,
   front_end = front_end
}
wez commented 1 year ago

@Suyashtnt: could you try putting this in your config file:

local gpus = wezterm.gui.enumerate_gpus()
return {
  webgpu_preferred_adapter = gpus[1]
  front_end = "WebGpu",
}
Suyashtnt commented 1 year ago

@Suyashtnt: could you try putting this in your config file:

local gpus = wezterm.gui.enumerate_gpus()
return {
  webgpu_preferred_adapter = gpus[1]
  front_end = "WebGpu",
}

Will try in a few hours (I checked this issue at the right time damn)

jokeyrhyme commented 1 year ago

For more flexible selection of the underlying adapter... -- https://github.com/wez/wezterm/issues/2756#issuecomment-1322215192

Thanks, that's a handy snippet

I was mostly testing webgpu_force_fallback_adapter to see if it made anything better/worse

I use the same wezterm.lua file on multiple machines, so I'll review my decisions about what GPUs are plugged into which monitors and see if I can boil that down into Lua code that works on all of them

Suyashtnt commented 1 year ago

@wez image colours are still bork

Suyashtnt commented 1 year ago
local wezterm = require "wezterm"
local gpus = wezterm.gui.enumerate_gpus()

return {
    color_scheme = "Catppuccin Mocha",
    font = wezterm.font_with_fallback {
        'JetBrainsMono Nerd Font Mono', -- Comic code breaks the font
        'Noto Color Emoji',
    },
    font_size = 13,
    line_height = 1.6,
    harfbuzz_features = {
        "cv06=1",
        "cv14=1",
        "cv32=1",
        "ss04=1",
        "ss07=1",
        "ss09=1",
    },
    webgpu_preferred_adapter = gpus[1],
    front_end = "WebGpu",
    enable_wayland = true, -- https://github.com/wez/wezterm/issues/1701
    cursor_blink_ease_in = "EaseIn",
    cursor_blink_ease_out = "EaseOut",
    animation_fps = 120,
    cursor_blink_rate = 800,
    cursor_thickness = 1.0,
    default_cursor_style = "BlinkingBar",
    initial_rows = 17,
    initial_cols = 70,
    window_padding = {
        left = 12,
        right = 12,
        top = 12,
        bottom = 12,
    },
    window_frame = {
        inactive_titlebar_bg = '#171723',
        active_titlebar_bg = '#171723',
        inactive_titlebar_fg = '#9399b2',
        active_titlebar_fg = '#cdd6f4',
        font = wezterm.font { family = 'Inter', weight = 'Bold' },
    },
    colors = {
        tab_bar = {
            active_tab = {
                bg_color = '#1e1e2e',
                fg_color = '#cdd6f4',
                intensity = 'Bold',
            },
            inactive_tab = {
                bg_color = '#313244',
                fg_color = '#9399b2',
            },
                        inactive_tab_hover = {
                                bg_color = '#11111b',
                                fg_color = '#cdd6f4',
                        },
            new_tab = {
                bg_color = '#181825',
                fg_color = '#cdd6f4',
            },
            new_tab_hover = {
                                bg_color = '#1e1e2e',
                                fg_color = '#cdd6f4',
                        },
        },
    },
}
luisiacc commented 1 year ago

don't know if anyone has tried this, but when entering fullscreen on windows 11 with the webgpu activated, I just get an entire black screen.

colemickens commented 1 year ago

I'm getting really terrible performance. Pasting the lua line in took 15 seconds to actualize:

wezterm version: 20221119-145034-49b9839f
OpenGL version: WebGPU: name=RENOIR (renoir, LLVM 14.0.6, DRM 3.48, 6.0.9), device_type=Other, backend=Gl, vendor=4098, device=0
Enter lua statements or expressions and hit Enter.
Press ESC or CTRL-D to exit
> wezterm.gui.enumerate_gpus()
[
    {
        "backend": "Gl",
        "device": 0,
        "device_type": "Other",
        "name": "RENOIR (renoir, LLVM 14.0.6, DRM 3.48, 6.0.9)",
        "vendor": 4098,
    },
]

What can I do to debug or understand what backends are available? For example, my compositor is running in OpenGL mode, but vulkaninfo seems to indicate Vulkan ought to be available.

luisiacc commented 1 year ago

don't know if anyone has tried this, but when entering fullscreen on windows 11 with the webgpu activated, I just get an entire black screen.

@wez this happens still on a lower scale but it's still pretty annoying, whenever I enter fullscreen with webGpu activated, I get a blackscreen entirely for like 2 seconds, once I'm able to see wezterm gui, I can write and all of that, if alt-tab it, or try to change to another program I get the same 2 seconds with blackscreen, and again when trying to alt-tab to wezterm again.

wez commented 1 year ago

@luisiacc please open a separate issue for that so that I can track it more effectively

wez commented 1 year ago

For the most part, this has seemed to have worked quite well. I've just pushed some docs for this, and I'm going to close out this issue. If you have a webgpu issue, please file a separate issue so that it can be tracked effectively.

github-actions[bot] commented 1 year ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.