Skip to content

Add Vulkan renderer #1163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open

Add Vulkan renderer #1163

wants to merge 38 commits into from

Conversation

spencercw
Copy link
Contributor

This PR adds a new Vulkan renderer to complement the existing EGL renderer. It is usable, but incomplete, considered experimental, and disabled by default. Notably, it is currently slower than the EGL renderer owing to unimplemented DMA-BUF and damage rect support.

The primary motivation for this change is to bring true HDR support to Looking Glass, which is not currently possible via EGL.1

Building with Vulkan support

Pass -DENABLE_VULKAN=1 to cmake when building the Looking Glass client. You may need to install luajit if cimgui binding generation fails.

Using the Vulkan renderer

Pass app:renderer=Vulkan to looking-glass-client to use the Vulkan renderer.

I also recommend initially passing vulkan:validate=true to enable the Vulkan validation layer. If any validation errors are logged to the console, please let me know.

Using HDR

Requirements

  • Wayland
  • A compositor which implements the Wayland color management protocol. I have tested against KWin 6.3. Hyprland may also work, but I have not tried it
  • Enable HDR in your system display settings on both client and host
  • Install the Vulkan Wayland HDR WSI layer (available in AUR as vk-hdr-layer-kwin6-git)
  • Run looking-glass-client with the environment variable ENABLE_HDR_WSI=1 to enable the above Vulkan layer
  • If using AMD graphics on the client, you must use RADV (Mesa). If you have both RADV and AMDVLK installed, you can force RADV by running looking-glass-client with the environment variable AMD_VULKAN_ICD=RADV.

Other HDR advice

The following advice is specific to KWin 6.3. Other compositors/versions may behave slightly differently.

Set the SDR content brightness to 31 in Windows. This is approximately equal to the reference luminance of 203 nits used by KWin, which should make SDR white content look identical to that of native Linux applications, and the difference between HDR on and off in Windows should be virtually indistinguishable when looking at SDR content.

Be aware that the 'Maximum SDR Brightness' setting within the KDE display configuration also affects HDR content.2 I recommend setting this to whatever brightness feels most comfortable, but it can be set to the reference level of 203 nits to most accurately reproduce the Windows output with minimal interference by KWin.

Footnotes

  1. Theoretically, maybe it could be supported via extensions such as EGL_EXT_gl_colorspace_bt2020_pq, but Mesa does not currently implement these.

  2. https://zamundaaa.github.io/wayland/2024/11/06/hdr-and-color-management-in-kwin-part-5.html

Currently, the sRGB cursor image is rendered directly into the framebuffer,
resulting in the cursor not matching the host white level when using HDR.

The fixed-function blending capabilities are not really adequate for our
purposes when using HDR. For standard color cursors it could work if we
converted the entire framebuffer from non-linear RGBA10 to linear RGBA16,
but that still doesn't help us with the other cursor types which require
the ability to invert a pixel with reference to the current SDR white
level.

To work around this, add a subpass self-dependency and attach the swapchain
image to the renderpass as both a color attachment and an input attachment.
This allows us to first render the desktop into the color attachment, add a
pipeline barrier to make the changes visible, then render the cursor, where
we can read the rendered desktop image from the input attachment to
manually blend it with the cursor.
The current logic simply adjusts for the SDR white level, so any true HDR
content is lost. Use perceptual quantization so HDR content can be
correctly rendered on the client.
Currently, the sRGB cursor image is rendered directly into the framebuffer,
resulting in the cursor not matching the host white level when using HDR.

The fixed-function blending capabilities are not really adequate for our
purposes when using HDR. For standard color cursors it could work if we
converted the entire framebuffer from non-linear RGBA10 to linear RGBA16,
but that still doesn't help us with the other cursor types which require
the ability to invert a pixel with reference to the current SDR white
level.

To work around this, add a subpass self-dependency and attach the swapchain
image to the renderpass as both a color attachment and an input attachment.
This allows us to first render the desktop into the color attachment, add a
pipeline barrier to make the changes visible, then render the cursor, where
we can read the rendered desktop image from the input attachment to
manually blend it with the cursor.
ImGui is rendered assuming a standard SDR sRGB output, so it looks very bad
when rendered into an HDR surface. Instead, render into an SDR surface,
then manually blend the result into the output HDR surface while performing
the necessary color space conversions.
The Vulkan present operation can currently be interrupted by the Wayland
pointer handling code if it issues a commit at the same time, resulting in
a protocol error.
This may be useful for diagnosing driver-related issues. For instance, the
Wayland HDR Vulkan layer does not work with AMDVLK, but it does work with
RADV.
This fixes a crash with the Intel driver when switching swapchain surface
formats.
This avoids a potential race with the invocation of onFrameFormat on the
frame thread.
@Vityacv
Copy link

Vityacv commented Feb 22, 2025

Getting this if validation layers enabled

VUID-VkSwapchainCreateInfoKHR-imageExtent-01689(ERROR / SPEC): msgNum: 320081257 - Validation Error: [ VUID-VkSwapchainCreateInfoKHR-imageExtent-01689 ] | MessageID = 0x13140d69 | vkCreateSwapchainKHR(): pCreateInfo->imageExtent (width = 0, height = 0) is invalid.
The Vulkan spec states: imageExtent members width and height must both be non-zero (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkSwapchainCreateInfoKHR-imageExtent-01689)
VUID-VkSwapchainCreateInfoKHR-pNext-07781(ERROR / SPEC): msgNum: 1284057537 - Validation Error: [ VUID-VkSwapchainCreateInfoKHR-pNext-07781 ] | MessageID = 0x4c8929c1 | vkCreateSwapchainKHR(): pCreateInfo->imageExtent (width = 0, height = 0), which is outside the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (width = 4294967295, height = 4294967295), minImageExtent = (width = 1, height = 1), maxImageExtent = (width = 16384, height = 16384).
The Vulkan spec states: If a VkSwapchainPresentScalingCreateInfoEXT structure was not included in the pNext chain, or it is included and VkSwapchainPresentScalingCreateInfoEXT::scalingBehavior is zero then imageExtent must be between minImageExtent and maxImageExtent, inclusive, where minImageExtent and maxImageExtent are members of the VkSurfaceCapabilitiesKHR structure returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkSwapchainCreateInfoKHR-pNext-07781)
VUID-VkFramebufferCreateInfo-width-00885(ERROR / SPEC): msgNum: -1231547098 - Validation Error: [ VUID-VkFramebufferCreateInfo-width-00885 ] | MessageID = 0xb6981526 | vkCreateFramebuffer(): pCreateInfo->width is zero.
The Vulkan spec states: width must be greater than 0 (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-width-00885)
VUID-VkFramebufferCreateInfo-height-00887(ERROR / SPEC): msgNum: -1513456701 - Validation Error: [ VUID-VkFramebufferCreateInfo-height-00887 ] | MessageID = 0xa5ca7bc3 | vkCreateFramebuffer(): pCreateInfo->height is zero.
The Vulkan spec states: height must be greater than 0 (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-height-00887)
00:00:00.544 [E]             crash.c:215  | crit_err_hdlr                  | ==== FATAL CRASH (B7-rc1-72-g0382a46d49+) ====
00:00:00.544 [E]             crash.c:216  | crit_err_hdlr                  | signal 11 (Segmentation fault), address is (nil)
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (0) /usr/lib/libc.so.6(+0x42560) [0x7b075abe7560]
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (1) /usr/lib/libVkLayer_khronos_validation.so(+0x8a71ea) [0x7b073a4e71ea]
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (2) /usr/lib/libVkLayer_khronos_validation.so(+0x924e3a) [0x7b073a564e3a]
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (3) /usr/lib/libVkLayer_khronos_validation.so(+0x8fa589) [0x7b073a53a589]
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (4) /usr/lib/libVkLayer_khronos_validation.so(+0x507442) [0x7b073a147442]
00:00:00.544 [E]             crash.c:202  | printBacktrace                 | [trace]: (5) vulkan.c:0 (vulkan_createFramebuffers)
00:00:00.544 [E]             crash.c:202  | printBacktrace                 | [trace]: (6) vulkan.c:0 (vulkan_initPipeline)
00:00:00.544 [E]             crash.c:202  | printBacktrace                 | [trace]: (7) vulkan.c:0 (vulkan_onFrameFormat)
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (8) /data/build/LookingGlass/client/build/looking-glass-client(+0x4da1d) [0x5e6b4e62fa1d]
00:00:00.544 [E]             crash.c:202  | printBacktrace                 | [trace]: (9) thread.c:0 (threadWrapper)
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (10) /usr/lib/libc.so.6(+0x9fc5c) [0x7b075ac44c5c]
00:00:00.544 [E]             crash.c:207  | printBacktrace                 | [trace]: (11) /usr/lib/libc.so.6(+0x1218dc) [0x7b075acc68dc]

@Vityacv Vityacv mentioned this pull request Feb 22, 2025
@spencercw
Copy link
Contributor Author

@Vityacv Can you identify any particular condition that triggers this failure? It seems from your comment in #1151 that the Vulkan renderer is generally working?

@Tony763
Copy link

Tony763 commented Mar 4, 2025

Hi, on Ubuntu 24.10 build failed with: /bin/sh: 1: glslangValidator: not found. Fixed by installing glslang-dev and glslang-tools.

@Tony763
Copy link

Tony763 commented Mar 4, 2025

For me, window size cannot be changed, when resizing, it get malformed.

image

./looking-glass-client -a -d -S -k -f /dev/shm/looking-glass app:renderer=Vulkan

Running without vulkan enabled still works as expected.

00:00:00.000 [I]              main.c:1865 | main                           | Looking Glass (B7-rc1-72-g0382a46d49+)
00:00:00.000 [I]              main.c:1866 | main                           | Locking Method: Atomic
00:00:00.000 [I]           cpuinfo.c:38   | cpuInfo_log                    | CPU Model: 13th Gen Intel(R) Core(TM) i9-13980HX
00:00:00.000 [I]           cpuinfo.c:39   | cpuInfo_log                    | CPU: 1 sockets, 24 cores, 32 threads
00:00:00.019 [I]              main.c:1192 | lg_run                         | Using font: /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf
00:00:00.020 [I]           ivshmem.c:137  | ivshmemOpenDev                 | KVMFR Device     : /dev/shm/looking-glass
00:00:00.021 [I]             audio.c:159  | audio_init                     | Using AudioDev: PipeWire
00:00:00.021 [I]                ps.c:245  | purespice_connect              | Connecting to socket 127.0.0.1:5900
00:00:00.028 [I]               rsa.c:178  | rsa_encryptPassword            | Using Nettle
00:00:00.028 [I]                ps.c:268  | purespice_connect              | Connected
00:00:00.028 [I]             agent.c:103  | agent_connect                  | Connected to the spice guest agent
00:00:00.028 [I]      channel_main.c:167  | onMessage_mainName             | Guest name: win11
00:00:00.028 [I]      channel_main.c:183  | onMessage_mainUUID             | Guest UUID: 8d7b69aa-7899-4b76-a824-a3d015d35605
00:00:00.034 [I]                ps.c:644  | ps_connectChannel              | RECORD channel connected
00:00:00.042 [I]                ps.c:644  | ps_connectChannel              | PLAYBACK channel connected
00:00:00.048 [I]                ps.c:644  | ps_connectChannel              | INPUTS channel connected
00:00:00.048 [I]              main.c:1321 | lg_run                         | Trying forced renderer
00:00:00.048 [I]           channel.c:323  | onMessage_notify               | [notify] keyboard channel is insecure
00:00:00.048 [I]              main.c:1146 | tryRenderer                    | Using Renderer: Vulkan
00:00:00.048 [I]           wayland.c:120  | waylandInit                    | Compositor: gnome-shell
00:00:00.048 [I]           wayland.c:130  | waylandInit                    | Selected  : libdecor
00:00:00.319 [I]        extensions.c:129  | vulkan_checkExtensions         | Enabling optional extension 'VK_EXT_swapchain_colorspace'
00:00:00.539 [I]            vulkan.c:1159 | vulkan_printDeviceDetails      | Device      : Intel(R) Graphics (RPL-S)
00:00:00.539 [I]            vulkan.c:1160 | vulkan_printDeviceDetails      | Driver name : Intel open-source Mesa driver
00:00:00.539 [I]            vulkan.c:1161 | vulkan_printDeviceDetails      | Driver info : Mesa 25.0~git2502210600.64552d~oibaf~o (git-64552db 2025-02-21 oracular-oibaf-ppa)
00:00:00.539 [I]            vulkan.c:1162 | vulkan_printDeviceDetails      | Queue family: 0
00:00:00.554 [I]            vulkan.c:533  | vulkan_createSwapchain         | Min image count: 4
00:00:00.554 [I]            vulkan.c:534  | vulkan_createSwapchain         | Image format   : 44
00:00:00.554 [I]            vulkan.c:535  | vulkan_createSwapchain         | Color space    : 0
00:00:00.554 [I]            vulkan.c:536  | vulkan_createSwapchain         | Extent         : 1024x768
00:00:00.554 [I]            vulkan.c:538  | vulkan_createSwapchain         | Pre-transform  : 1
00:00:00.554 [I]            vulkan.c:539  | vulkan_createSwapchain         | Composite alpha: 1
00:00:00.554 [I]            vulkan.c:540  | vulkan_createSwapchain         | Present mode   : 1
00:00:00.554 [I]              main.c:1596 | lg_run                         | Guest Information:
00:00:00.554 [I]              main.c:1597 | lg_run                         | Version  : B7-rc1-72-g0382a46d49+
00:00:00.554 [I]              main.c:1618 | lg_run                         | UUID     : 00000000-0000-0000-0000-000000000000
00:00:00.554 [I]              main.c:1627 | lg_run                         | CPU Model: 13th Gen Intel(R) Core(TM) i9-13980HX
00:00:00.554 [I]              main.c:1628 | lg_run                         | CPU      : 1 sockets, 6 cores, 12 threads
00:00:00.554 [I]              main.c:1630 | lg_run                         | Using    : D12
00:00:00.554 [I]              main.c:1716 | lg_run                         | OS       : Windows
00:00:00.554 [I]              main.c:1718 | lg_run                         | OS Name  : Windows 10 Pro (Build: 26100) 
00:00:00.554 [I]              main.c:1740 | lg_run                         | Starting session
00:00:00.873 [I]              main.c:717  | main_frameThread               | Format: FRAME_TYPE_BGRA 3840x2160 (3840x2160) stride:3840 pitch:15360 rotation:0 hdr:0 pq:0

Also system is detected as Windows 10 but actually is Windows 11.

@Tony763
Copy link

Tony763 commented Mar 4, 2025

Forcing full screen with -F parameter open small window which is hidden/minimized and cannot be opened. Moving to another monitor does not help.

image

This and above is with -DLIBDECOR=ON.


Below is with -DLIBDECOR=NO.

Window is small/cannot resize due to missing decorator (expected). When I toggle full screen with keyboard shortcut, window size stay same and Ubuntu toolbars got hidden (toolbar shoud be on left and top side).

image
Using keyboard shortcut brings toolbars back.
image

When I force full screen by -F, window opens for half a second and crash with:

00:00:00.512 [I]              main.c:1718 | lg_run                         | OS Name  : Windows 10 Pro (Build: 26100) 
00:00:00.512 [I]              main.c:1740 | lg_run                         | Starting session
00:00:00.701 [E]            vulkan.c:1713 | vulkan_acquireSwapchainImage   | Failed to acquire swapchain image (VkResult: 1000001003)
00:00:00.747 [I]           channel.c:269  | channel_internal_disconnect    | RECORD channel disconnected
00:00:00.747 [I]           channel.c:269  | channel_internal_disconnect    | PLAYBACK channel disconnected
00:00:00.747 [I]           channel.c:269  | channel_internal_disconnect    | INPUTS channel disconnected
00:00:00.747 [I]           channel.c:269  | channel_internal_disconnect    | MAIN channel disconnected

@Vityacv
Copy link

Vityacv commented Mar 5, 2025

@Vityacv Can you identify any particular condition that triggers this failure? It seems from your comment in #1151 that the Vulkan renderer is generally working?

It works only with vulkan:validate=no, also log when launching with amd gpu (using validate=yes)

00:00:00.022 [I]              main.c:1146 | tryRenderer                    | Using Renderer: Vulkan
00:00:00.022 [I]           wayland.c:120  | waylandInit                    | Compositor: sway
00:00:00.022 [I]           wayland.c:130  | waylandInit                    | Selected  : xdg
00:00:00.027 [I]            vulkan.c:1097 | vulkan_createInstance          | Enabling validation layer
00:00:00.027 [I]        extensions.c:129  | vulkan_checkExtensions         | Enabling optional extension 'VK_EXT_swapchain_colorspace'
00:00:00.028 [E]            vulkan.c:1130 | vulkan_createInstance          | Failed to create Vulkan instance (VkResult: -6)
00:00:00.028 [E]              main.c:176  | renderThread                   | Renderer failed to start
00:00:00.121 [I]           channel.c:269  | channel_internal_disconnect    | INPUTS channel disconnected
00:00:00.121 [I]           channel.c:269  | channel_internal_disconnect    | MAIN channel disconnected
00:00:00.121 [I]                ps.c:330  | purespice_disconnect           | Disconnected

Having issues that @Tony763 having with a window, but in my case I can force size of it in the client settings, and it's usable with sway

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants