Skip to content

Commit

Permalink
STEAMOS: Dynamic swapchain override for gamescope limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
BNieuwenhuizen authored and hakzsam committed Dec 2, 2024
1 parent f1f246c commit 2f39ac8
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
41 changes: 39 additions & 2 deletions src/gallium/frontends/dri/loader_dri3_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,30 @@ dri3_update_max_num_back(struct loader_dri3_drawable *draw)
}
}

static unsigned
gamescope_swapchain_override()
{
const char *path = getenv("GAMESCOPE_LIMITER_FILE");
if (!path)
return 0;

static simple_mtx_t mtx = SIMPLE_MTX_INITIALIZER;
static int fd = -1;

simple_mtx_lock(&mtx);
if (fd < 0) {
fd = open(path, O_RDONLY);
}
simple_mtx_unlock(&mtx);

if (fd < 0)
return 0;

uint32_t override_value = 0;
pread(fd, &override_value, sizeof(override_value), 0);
return override_value;
}

void
loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
{
Expand All @@ -288,10 +312,12 @@ loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
* PS. changing from value A to B and A < B won't cause swap out of order but
* may still gets wrong target_msc value at the beginning.
*/
if (draw->swap_interval != interval)
if (draw->orig_swap_interval != interval)
loader_dri3_swapbuffer_barrier(draw);

draw->swap_interval = interval;
draw->orig_swap_interval = interval;
if (gamescope_swapchain_override() != 1)
draw->swap_interval = interval;
}

static void
Expand Down Expand Up @@ -419,6 +445,11 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
set_adaptive_sync_property(conn, draw->drawable, false);

draw->swap_interval = dri_get_initial_swap_interval(draw->dri_screen_render_gpu);
draw->orig_swap_interval = draw->swap_interval;

unsigned gamescope_override = gamescope_swapchain_override();
if (gamescope_override == 1)
draw->swap_interval = 1;

dri3_update_max_num_back(draw);

Expand Down Expand Up @@ -1064,6 +1095,12 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
if (draw->type == LOADER_DRI3_DRAWABLE_WINDOW) {
dri3_fence_reset(draw->conn, back);

unsigned gamescope_override = gamescope_swapchain_override();
if (gamescope_override == 1)
draw->swap_interval = 1;
else
draw->swap_interval = draw->orig_swap_interval;

/* Compute when we want the frame shown by taking the last known
* successful MSC and adding in a swap interval for each outstanding swap
* request. target_msc=divisor=remainder=0 means "Use glXSwapBuffers()
Expand Down
1 change: 1 addition & 0 deletions src/gallium/frontends/dri/loader_dri3_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ struct loader_dri3_drawable {
bool block_on_depleted_buffers;
bool queries_buffer_age;
int swap_interval;
int orig_swap_interval;

const struct loader_dri3_vtable *vtable;

Expand Down
38 changes: 38 additions & 0 deletions src/vulkan/wsi/wsi_common_x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "util/mesa-blake3.h"
#include "util/os_file.h"
#include "util/os_time.h"
#include "util/simple_mtx.h"
#include "util/u_debug.h"
#include "util/u_thread.h"
#include "util/xmlconfig.h"
Expand Down Expand Up @@ -223,6 +224,30 @@ wsi_x11_detect_xwayland(xcb_connection_t *conn,
return is_xwayland;
}

static unsigned
gamescope_swapchain_override()
{
const char *path = getenv("GAMESCOPE_LIMITER_FILE");
if (!path)
return 0;

static simple_mtx_t mtx = SIMPLE_MTX_INITIALIZER;
static int fd = -1;

simple_mtx_lock(&mtx);
if (fd < 0) {
fd = open(path, O_RDONLY);
}
simple_mtx_unlock(&mtx);

if (fd < 0)
return 0;

uint32_t override_value = 0;
pread(fd, &override_value, sizeof(override_value), 0);
return override_value;
}

static struct wsi_x11_connection *
wsi_x11_connection_create(struct wsi_device *wsi_dev,
xcb_connection_t *conn)
Expand Down Expand Up @@ -1128,6 +1153,8 @@ struct x11_swapchain {
uint64_t present_id;
VkResult present_progress_error;

VkPresentModeKHR orig_present_mode;

struct x11_image images[0];
};
VK_DEFINE_NONDISP_HANDLE_CASTS(x11_swapchain, base.base, VkSwapchainKHR,
Expand Down Expand Up @@ -1805,6 +1832,12 @@ x11_queue_present(struct wsi_swapchain *anv_chain,
if (status < 0)
return status;

unsigned gamescope_override = gamescope_swapchain_override();
if ((gamescope_override == 1 && chain->base.present_mode != VK_PRESENT_MODE_FIFO_KHR) ||
(gamescope_override != 1 && chain->base.present_mode != chain->orig_present_mode)) {
return x11_swapchain_result(chain, VK_ERROR_OUT_OF_DATE_KHR);
}

if (damage && damage->pRectangles && damage->rectangleCount > 0 &&
damage->rectangleCount <= MAX_DAMAGE_RECTS) {
xcb_rectangle_t *rects = chain->images[image_index].rects;
Expand Down Expand Up @@ -2524,6 +2557,10 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
xcb_void_cookie_t cookie;
VkResult result;
VkPresentModeKHR present_mode = wsi_swapchain_get_present_mode(wsi_device, pCreateInfo);
VkPresentModeKHR orig_present_mode = present_mode;

if (gamescope_swapchain_override() == 1)
present_mode = VK_PRESENT_MODE_FIFO_KHR;

assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);

Expand Down Expand Up @@ -2675,6 +2712,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
chain->base.release_images = x11_release_images;
chain->base.set_present_mode = x11_set_present_mode;
chain->base.present_mode = present_mode;
chain->orig_present_mode = orig_present_mode;
chain->base.image_count = num_images;
chain->conn = conn;
chain->window = window;
Expand Down

0 comments on commit 2f39ac8

Please sign in to comment.