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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b0a31e7
[client] vulkan: add skeleton
spencercw Jan 25, 2025
9d947f8
[client] vulkan: create device
spencercw Jan 25, 2025
e4bef3d
[client] vulkan: create swapchain
spencercw Jan 25, 2025
f436366
[client] vulkan: create swapchain image views
spencercw Jan 26, 2025
65eeea2
[client] vulkan: create render pass
spencercw Jan 26, 2025
8b7a080
[client] vulkan: create framebuffers
spencercw Jan 26, 2025
a142275
[client] vulkan: create command pool
spencercw Jan 26, 2025
1cf6cb0
[client] vulkan: allocate command buffer
spencercw Jan 26, 2025
b9e7b60
[client] vulkan: create semaphores and fence
spencercw Jan 26, 2025
3f5c443
[client] vulkan: load shaders
spencercw Jan 26, 2025
0acc2c6
[client] vulkan: create graphics pipeline
spencercw Jan 26, 2025
eb79287
[client] vulkan: implement basic rendering
spencercw Jan 26, 2025
65f51ee
[client] vulkan: render from texture
spencercw Jan 26, 2025
064c9bf
[client] vulkan: copy desktop image into render texture
spencercw Jan 26, 2025
c742d21
[client] vulkan: populate HDR metadata using display data from DXGI
spencercw Jan 26, 2025
d843898
[client] vulkan: improve logic for selecting extensions
spencercw Jan 29, 2025
1e59341
[client] vulkan: add X11 support
spencercw Jan 29, 2025
17e473e
[client] vulkan: take color space into account when blending cursor
spencercw Jan 29, 2025
5ce9e8b
[client] vulkan: upload ImGui textures
spencercw Jan 30, 2025
b978952
[client] imgui: update to cimgui 1.91.7
spencercw Jan 30, 2025
632dfe0
[client] vulkan: render ImGui
spencercw Jan 31, 2025
95fea3f
[client] vulkan: upload cursor image
spencercw Feb 2, 2025
2ecc027
[client] vulkan: render color cursor
spencercw Feb 2, 2025
aef1cea
[host] use perceptual quantization when converting 16-bit HDR to 10-bit
spencercw Feb 4, 2025
89727d8
[client] vulkan: handle 10-bit HDR formats
spencercw Feb 4, 2025
8ab2187
[client] vulkan: take color space into account when blending cursor
spencercw Feb 6, 2025
4c76038
[client] vulkan: take color space into account when blending ImGui
spencercw Feb 9, 2025
1c3a2ed
[host] d12: send SDR white level to client
spencercw Feb 9, 2025
0092fee
[client] vulkan: adjust cursor and ImGui based upon host SDR white level
spencercw Feb 9, 2025
8e2c084
[client] wayland: lock surface during Vulkan present
spencercw Feb 9, 2025
0c3bf1c
[client] vulkan: render other cursor types
spencercw Feb 10, 2025
76c4fc0
[client] vulkan: log driver details
spencercw Feb 11, 2025
6b9acd5
[client] dxgi: populate HDR metadata
spencercw Feb 11, 2025
f46fba8
[client] vulkan: wait for queue idle before destroying swapchain
spencercw Feb 11, 2025
96ce298
[client] vulkan: add option to enable validation layer
spencercw Feb 11, 2025
d5007fd
[client] vulkan: move desktop handling code into separate file
spencercw Feb 13, 2025
c3fd26b
[client] vulkan: populate overlay timing graphs
spencercw Feb 13, 2025
0382a46
[client] main: lock renderer around resize
spencercw Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.19)
project(looking-glass-client C CXX)

get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE)
Expand Down Expand Up @@ -33,6 +33,9 @@ add_feature_info(ENABLE_OPENGL ENABLE_OPENGL "Legacy OpenGL renderer.")
option(ENABLE_EGL "Enable the EGL renderer" ON)
add_feature_info(ENABLE_EGL ENABLE_EGL "EGL renderer.")

option(ENABLE_VULKAN "Enable the Vulkan renderer" OFF)
add_feature_info(ENABLE_VULKAN ENABLE_VULKAN "Vulkan renderer.")

option(ENABLE_BACKTRACE "Enable backtrace support on crash" ON)
add_feature_info(ENABLE_BACKTRACE ENABLE_BACKTRACE "Backtrace support.")

Expand Down Expand Up @@ -74,6 +77,13 @@ if (ENABLE_EGL)
add_definitions(-D ENABLE_EGL)
endif()

if (ENABLE_VULKAN)
add_definitions(-D ENABLE_VULKAN)

# Vulkan bindings are not present in the default generated bindings
set(CIMGUI_GEN_BINDINGS ON)
endif()

if(ENABLE_ASAN)
add_compile_options("-fno-omit-frame-pointer" "-fsanitize=address")
set(EXE_FLAGS "${EXE_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
Expand Down Expand Up @@ -138,6 +148,20 @@ set(SOURCES
# Force cimgui to build as a static library.
set(IMGUI_STATIC "yes" CACHE STRING "Build as a static library")

# Only generate cimgui bindings if the defaults are not sufficient. This avoids
# a potentially unnecessary dependency on LuaJIT
if(CIMGUI_GEN_BINDINGS)
message(STATUS "Generating cimgui bindings")
file(LOCK "${PROJECT_TOP}/repos/cimgui/generator" DIRECTORY GUARD FILE)
execute_process(
COMMAND luajit ./generator.lua gcc internal opengl2 opengl3 vulkan
WORKING_DIRECTORY "${PROJECT_TOP}/repos/cimgui/generator"
OUTPUT_QUIET
ERROR_QUIET
COMMAND_ERROR_IS_FATAL ANY
)
endif()

add_subdirectory("${PROJECT_TOP}/resources" "${CMAKE_BINARY_DIR}/resources")
add_subdirectory("${PROJECT_TOP}/common" "${CMAKE_BINARY_DIR}/common" )
add_subdirectory("${PROJECT_TOP}/repos/LGMP/lgmp" "${CMAKE_BINARY_DIR}/LGMP" )
Expand Down
1 change: 1 addition & 0 deletions client/displayservers/Wayland/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_library(displayserver_Wayland STATIC
presentation.c
state.c
registry.c
vulkan.c
wayland.c
window.c
)
Expand Down
19 changes: 8 additions & 11 deletions client/displayservers/Wayland/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ static const struct wl_keyboard_listener keyboardListener = {

static void waylandCleanUpPointer(void)
{
INTERLOCKED_SECTION(wlWm.confineLock, {
INTERLOCKED_SECTION(wlWm.surfaceLock, {
if (wlWm.lockedPointer)
{
zwp_locked_pointer_v1_destroy(wlWm.lockedPointer);
Expand Down Expand Up @@ -419,15 +419,12 @@ bool waylandInputInit(void)
wl_seat_add_listener(wlWm.seat, &seatListener, NULL);
wl_display_roundtrip(wlWm.display);

LG_LOCK_INIT(wlWm.confineLock);

return true;
}

void waylandInputFree(void)
{
waylandUngrabPointer();
LG_LOCK_FREE(wlWm.confineLock);

if (wlWm.pointer)
waylandCleanUpPointer();
Expand Down Expand Up @@ -463,7 +460,7 @@ void waylandGrabPointer(void)
&relativePointerListener, NULL);
}

INTERLOCKED_SECTION(wlWm.confineLock,
INTERLOCKED_SECTION(wlWm.surfaceLock,
{
if (!wlWm.confinedPointer && !wlWm.lockedPointer)
{
Expand All @@ -477,7 +474,7 @@ void waylandGrabPointer(void)
inline static void internalUngrabPointer(bool lock)
{
if (lock)
LG_LOCK(wlWm.confineLock);
LG_LOCK(wlWm.surfaceLock);

if (wlWm.confinedPointer)
{
Expand All @@ -486,7 +483,7 @@ inline static void internalUngrabPointer(bool lock)
}

if (lock)
LG_UNLOCK(wlWm.confineLock);
LG_UNLOCK(wlWm.surfaceLock);

if (!wlWm.warpSupport)
{
Expand Down Expand Up @@ -517,7 +514,7 @@ void waylandCapturePointer(void)
return;
}

INTERLOCKED_SECTION(wlWm.confineLock,
INTERLOCKED_SECTION(wlWm.surfaceLock,
{
if (wlWm.confinedPointer)
{
Expand All @@ -533,7 +530,7 @@ void waylandCapturePointer(void)

void waylandUncapturePointer(void)
{
INTERLOCKED_SECTION(wlWm.confineLock,
INTERLOCKED_SECTION(wlWm.surfaceLock,
{
if (wlWm.lockedPointer)
{
Expand Down Expand Up @@ -582,11 +579,11 @@ void waylandWarpPointer(int x, int y, bool exiting)
if (!wlWm.pointerInSurface || wlWm.lockedPointer)
return;

INTERLOCKED_SECTION(wlWm.confineLock,
INTERLOCKED_SECTION(wlWm.surfaceLock,
{
if (wlWm.lockedPointer)
{
LG_UNLOCK(wlWm.confineLock);
LG_UNLOCK(wlWm.surfaceLock);
return;
}

Expand Down
75 changes: 75 additions & 0 deletions client/displayservers/Wayland/vulkan.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Looking Glass
* Copyright © 2017-2024 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifdef ENABLE_VULKAN
#include "wayland.h"

#include <vulkan/vulkan_wayland.h>

const char * waylandGetVulkanSurfaceExtension(void)
{
return "VK_KHR_wayland_surface";
}

VkSurfaceKHR waylandCreateVulkanSurface(VkInstance instance)
{
struct VkWaylandSurfaceCreateInfoKHR createInfo =
{
.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
.display = wlWm.display,
.surface = wlWm.surface
};

VkSurfaceKHR surface;
VkResult result = vkCreateWaylandSurfaceKHR(instance, &createInfo, NULL,
&surface);
if (result != VK_SUCCESS)
{
DEBUG_ERROR("Failed to create Vulkan Wayland surface (VkResult: %d)",
result);
return NULL;
}

return surface;
}

bool waylandVulkanPresent(VkQueue queue, struct VkPresentInfoKHR * presentInfo)
{
waylandPresentationFrame();

// vkQueuePresentKHR issues a batch of Wayland requests terminated with a
// commit. This must be isolated from anything else that may issue a commit
// otherwise a half-completed batch may be committed, resulting in a protocol
// error and the present operation failing
VkResult result;
INTERLOCKED_SECTION(wlWm.surfaceLock,
{
result = vkQueuePresentKHR(queue, presentInfo);
});

if (result != VK_SUCCESS)
{
DEBUG_ERROR("Failed to present swapchain image (VkResult: %d)", result);
return false;
}

return true;
}
#endif
9 changes: 9 additions & 0 deletions client/displayservers/Wayland/wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ static bool waylandInit(const LG_DSInitParams params)
return false;
#endif

LG_LOCK_INIT(wlWm.surfaceLock);

return true;
}

Expand All @@ -184,6 +186,7 @@ static void waylandShutdown(void)

static void waylandFree(void)
{
LG_LOCK_FREE(wlWm.surfaceLock);
waylandIdleFree();
waylandWindowFree();
waylandPresentationFree();
Expand Down Expand Up @@ -252,6 +255,12 @@ struct LG_DisplayServerOps LGDS_Wayland =
.glSetSwapInterval = waylandGLSetSwapInterval,
.glSwapBuffers = waylandGLSwapBuffers,
#endif

#ifdef ENABLE_VULKAN
.getVulkanSurfaceExtension = waylandGetVulkanSurfaceExtension,
.createVulkanSurface = waylandCreateVulkanSurface,
.vulkanPresent = waylandVulkanPresent,
#endif
.waitFrame = waylandWaitFrame,
.skipFrame = waylandSkipFrame,
.stopWaitFrame = waylandStopWaitFrame,
Expand Down
8 changes: 7 additions & 1 deletion client/displayservers/Wayland/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct WaylandDSState
struct wl_seat * seat;
struct wl_shm * shm;
struct wl_compositor * compositor;
LG_Lock surfaceLock;

wl_fixed_t scale;
bool fractionalScale;
Expand Down Expand Up @@ -163,7 +164,6 @@ struct WaylandDSState
struct zwp_locked_pointer_v1 * lockedPointer;
bool showPointer;
uint32_t pointerEnterSerial;
LG_Lock confineLock;

struct zwp_idle_inhibit_manager_v1 * idleInhibitManager;
struct zwp_idle_inhibitor_v1 * idleInhibitor;
Expand Down Expand Up @@ -259,6 +259,12 @@ void waylandGLSetSwapInterval(int interval);
void waylandGLSwapBuffers(void);
#endif

#ifdef ENABLE_VULKAN
const char * waylandGetVulkanSurfaceExtension(void);
VkSurfaceKHR waylandCreateVulkanSurface(VkInstance instance);
bool waylandVulkanPresent(VkQueue queue, struct VkPresentInfoKHR * presentInfo);
#endif

// idle module
bool waylandIdleInit(void);
void waylandIdleFree(void);
Expand Down
50 changes: 50 additions & 0 deletions client/displayservers/X11/x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
#include "eglutil.h"
#endif

#ifdef ENABLE_VULKAN
#include <vulkan/vulkan_xlib.h>
#endif

#include "app.h"
#include "common/debug.h"
#include "common/time.h"
Expand Down Expand Up @@ -1563,6 +1567,47 @@ static void x11GLSwapBuffers(void)
}
#endif

#ifdef ENABLE_VULKAN
static const char * x11GetVulkanSurfaceExtension(void)
{
return "VK_KHR_xlib_surface";
}

static VkSurfaceKHR x11CreateVulkanSurface(VkInstance instance)
{
struct VkXlibSurfaceCreateInfoKHR createInfo =
{
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
.dpy = x11.display,
.window = x11.window
};

VkSurfaceKHR surface;
VkResult result = vkCreateXlibSurfaceKHR(instance, &createInfo, NULL,
&surface);
if (result != VK_SUCCESS)
{
DEBUG_ERROR("Failed to create Vulkan Xlib surface (VkResult: %d)", result);
return NULL;
}

return surface;
}

static bool x11VulkanPresent(VkQueue queue,
struct VkPresentInfoKHR * presentInfo)
{
VkResult result = vkQueuePresentKHR(queue, presentInfo);
if (result != VK_SUCCESS)
{
DEBUG_ERROR("Failed to present swapchain image (VkResult: %d)", result);
return false;
}

return true;
}
#endif

static bool x11WaitFrame(void)
{
/* wait until we are woken up by the present event */
Expand Down Expand Up @@ -2008,6 +2053,11 @@ struct LG_DisplayServerOps LGDS_X11 =
.glMakeCurrent = x11GLMakeCurrent,
.glSetSwapInterval = x11GLSetSwapInterval,
.glSwapBuffers = x11GLSwapBuffers,
#endif
#ifdef ENABLE_VULKAN
.getVulkanSurfaceExtension = x11GetVulkanSurfaceExtension,
.createVulkanSurface = x11CreateVulkanSurface,
.vulkanPresent = x11VulkanPresent,
#endif
.waitFrame = x11WaitFrame,
.stopWaitFrame = x11StopWaitFrame,
Expand Down
6 changes: 6 additions & 0 deletions client/include/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ void app_glSetSwapInterval(int interval);
void app_glSwapBuffers(void);
#endif

#ifdef ENABLE_VULKAN
const char * app_getVulkanSurfaceExtension(void);
VkSurfaceKHR app_createVulkanSurface(VkInstance instance);
bool app_vulkanPresent(VkQueue queue, struct VkPresentInfoKHR * presentInfo);
#endif

#define MAX_OVERLAY_RECTS 10
void app_registerOverlay(const struct LG_OverlayOps * ops, const void * params);
void app_initOverlays(void);
Expand Down
11 changes: 11 additions & 0 deletions client/include/interface/displayserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include "common/types.h"
#include "common/debug.h"

#ifdef ENABLE_VULKAN
#include <vulkan/vulkan.h>
#endif

typedef enum LG_ClipboardData
{
LG_CLIPBOARD_DATA_TEXT = 0,
Expand Down Expand Up @@ -158,6 +162,13 @@ struct LG_DisplayServerOps
void (*glSwapBuffers)(void);
#endif

#ifdef ENABLE_VULKAN
/* Vulkan support */
const char * (*getVulkanSurfaceExtension)(void);
VkSurfaceKHR (*createVulkanSurface)(VkInstance instance);
bool (*vulkanPresent)(VkQueue queue, struct VkPresentInfoKHR * presentInfo);
#endif

/* Waits for a good time to render the next frame in time for the next vblank.
* This is optional and a display server may choose to not implement it.
*
Expand Down
Loading
Loading