Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 16 additions & 9 deletions src/Backends/DRMBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4020,19 +4020,26 @@ namespace gamescope
if ( bDefer && !!( g_uCompositeDebug & CompositeDebugFlag::Markers ) )
g_uCompositeDebug |= CompositeDebugFlag::Markers_Partial;

std::optional oCompositeResult = vulkan_composite( &compositeFrameInfo, nullptr, !bNeedsFullComposite );
// Only present composites advance the output ring, so the last one is still on screen.
const bool bReuseLastComposite = pFrameInfo->bRepeatFrame && bNeedsFullComposite &&
m_bWasCompositing && !m_bWasPartialCompositing && vulkan_get_last_output_image( false, false ) != nullptr;

m_bWasCompositing = true;
if ( !bReuseLastComposite )
{
std::optional oCompositeResult = vulkan_composite( &compositeFrameInfo, nullptr, !bNeedsFullComposite );

g_uCompositeDebug &= ~CompositeDebugFlag::Markers_Partial;
m_bWasCompositing = true;

if ( !oCompositeResult )
{
xwm_log.errorf("vulkan_composite failed");
return -EINVAL;
}
g_uCompositeDebug &= ~CompositeDebugFlag::Markers_Partial;

vulkan_wait( *oCompositeResult, true );
if ( !oCompositeResult )
{
xwm_log.errorf("vulkan_composite failed");
return -EINVAL;
}

vulkan_wait( *oCompositeResult, true );
}

FrameInfo_t presentCompFrameInfo = {};
presentCompFrameInfo.allowVRR = pFrameInfo->allowVRR;
Expand Down
4 changes: 4 additions & 0 deletions src/rendervulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4681,6 +4681,10 @@ bool vulkan_format_supports_features(VkFormat format, VkFormatFeatureFlags featu

gamescope::Rc<CVulkanTexture> vulkan_get_last_output_image( bool partial, bool defer )
{
// A remake drops the deferred images until the next composite makes them.
if ( g_output.outputImages.empty() )
return nullptr;

// Get previous image ( +2 )
// 1 2 3
// |
Expand Down
2 changes: 2 additions & 0 deletions src/rendervulkan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ struct FrameInfo_t
gamescope::Rc<CVulkanTexture> lut3D[EOTF_Count];

bool allowVRR;
// Content identical to the previous present, eg. an adaptive sync idle hold.
bool bRepeatFrame;
bool applyOutputColorMgmt; // drm only
EOTF outputEncodingEOTF;

Expand Down
44 changes: 39 additions & 5 deletions src/steamcompmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ gamescope::ConVar<bool> cv_adaptive_sync( "adaptive_sync", false, "Whether or no
gamescope::ConVar<bool> cv_adaptive_sync_ignore_overlay( "adaptive_sync_ignore_overlay", false, "Whether or not to ignore overlay planes for pushing commits with adaptive sync." );
gamescope::ConVar<int> cv_adaptive_sync_overlay_cycles( "adaptive_sync_overlay_cycles", 1, "Number of vblank cycles to ignore overlay repaints before forcing a commit with adaptive sync." );
gamescope::ConVar<bool> cv_adaptive_sync_uncapped( "adaptive_sync_uncapped", true, "Whether or not to allow mailbox/immediate clients to run uncapped with adaptive sync by deferring paints until the display can take a new flip." );
gamescope::ConVar<int> cv_adaptive_sync_cursor_min_fps( "adaptive_sync_cursor_min_fps", 30, "Content frame rate at or above which cursor repaints coalesce with content frames when adaptive sync is on. 0 = repaint the cursor immediately." );
gamescope::ConVar<bool> cv_adaptive_sync_idle_hold( "adaptive_sync_idle_hold", true, "Hold the display at its refresh rate while the Steam UI is focused with adaptive sync." );

gamescope::ConVar<bool> cv_upscale_preemptive( "upscale_preemptive", true, "Allow pre-emptive upscaling" );
gamescope::ConVar<bool> cv_upscale_preemptive_debug_force_sync( "upscale_preemptive_debug_force_sync", false, "Force synchronize pre-emptive upscaling" );
Expand Down Expand Up @@ -1115,6 +1117,7 @@ uint32_t lastPublishedInputCounter;

std::atomic<bool> hasRepaint = false;
bool hasRepaintNonBasePlane = false;
std::atomic<bool> hasCursorRepaint = false;

bool g_bUpdateForwardedVROverlays = false;

Expand Down Expand Up @@ -2058,7 +2061,7 @@ void MouseCursor::checkSuspension()

// We're hiding the cursor, force redraw if we were showing it
if (window && !m_imageEmpty ) {
hasRepaintNonBasePlane = true;
hasCursorRepaint = true;
nudge_steamcompmgr();
}
}
Expand Down Expand Up @@ -3096,7 +3099,7 @@ gamescope::ConVar<bool> cv_paint_cursor_plane{ "paint_cursor_plane", true };
gamescope::ConVar<bool> cv_paint_mura_plane{ "paint_mura_plane", true };

static void
paint_all( global_focus_t *pFocus, bool async )
paint_all( global_focus_t *pFocus, bool async, bool bRepeatFrame )
{
if ( !pFocus )
return;
Expand All @@ -3110,8 +3113,13 @@ paint_all( global_focus_t *pFocus, bool async )

static long long int paintID = 0;

const uint32_t uColorMgmtSerial = g_ColorMgmt.serial;
update_color_mgmt();

// New LUTs need a fresh composite even when nothing was damaged.
if ( g_ColorMgmt.serial != uColorMgmtSerial )
bRepeatFrame = false;

paintID++;
gpuvis_trace_begin_ctx_printf( paintID, "paint_all" );
steamcompmgr_win_t *w;
Expand Down Expand Up @@ -3156,6 +3164,7 @@ paint_all( global_focus_t *pFocus, bool async )
frameInfo.applyOutputColorMgmt = g_ColorMgmt.pending.enabled;
frameInfo.outputEncodingEOTF = g_ColorMgmt.pending.outputEncodingEOTF;
frameInfo.allowVRR = cv_adaptive_sync;
frameInfo.bRepeatFrame = bRepeatFrame;
frameInfo.bFadingOut = fadingOut;
frameInfo.eUpscaleFilter = pFocus->eUpscaleFilter;
frameInfo.eUpscaleScaler = pFocus->eUpscaleScaler;
Expand Down Expand Up @@ -10735,6 +10744,7 @@ steamcompmgr_main(int argc, char **argv)
bool bPainted = false;

static int nIgnoredOverlayRepaints = 0;
static uint64_t s_ulLastContentPaintTime = 0;

if ( !hasRepaintNonBasePlane )
nIgnoredOverlayRepaints = 0;
Expand All @@ -10745,6 +10755,7 @@ steamcompmgr_main(int argc, char **argv)
for ( auto &iter : g_VirtualConnectorFocuses )
{
global_focus_t *pPaintFocus = &iter.second;
bool bRepeatFrame = false;

const UpscaleSettings_t upscaleSettings = GetUpscaleSettings(
window_is_steam( pPaintFocus->focusWindow ),
Expand Down Expand Up @@ -10835,13 +10846,13 @@ steamcompmgr_main(int argc, char **argv)
{
case FlipType::Normal:
{
bShouldPaint = vblank && ( hasRepaint || hasRepaintNonBasePlane || bForceSyncFlip );
bShouldPaint = vblank && ( hasRepaint || hasRepaintNonBasePlane || hasCursorRepaint || bForceSyncFlip );
break;
}

case FlipType::Async:
{
bShouldPaint = hasRepaint;
bShouldPaint = hasRepaint || hasCursorRepaint;

if ( vblank && !bShouldPaint && hasRepaintNonBasePlane )
nIgnoredOverlayRepaints++;
Expand All @@ -10853,6 +10864,25 @@ steamcompmgr_main(int argc, char **argv)
{
bShouldPaint = hasRepaint && bVRRCanFlip;

// Content at or above adaptive_sync_cursor_min_fps carries the cursor with its own frames.
if ( !bShouldPaint && hasCursorRepaint && bVRRCanFlip )
{
const int nCursorMinFPS = cv_adaptive_sync_cursor_min_fps;
if ( nCursorMinFPS <= 0 ||
get_time_in_nanos() - s_ulLastContentPaintTime >= 1'000'000'000ul / uint64_t( nCursorMinFPS ) )
{
bShouldPaint = true;
}
}

// Hold the Steam UI at the refresh rate so an idle panel can't stretch toward its minimum and flicker.
if ( !bShouldPaint && bIsVBlankFromTimer && g_bSteamIsActiveWindow &&
cv_adaptive_sync_idle_hold )
{
bShouldPaint = true;
bRepeatFrame = !hasCursorRepaint && !hasRepaintNonBasePlane;
}

if ( bIsVBlankFromTimer )
{
if ( hasRepaintNonBasePlane )
Expand Down Expand Up @@ -10890,7 +10920,7 @@ steamcompmgr_main(int argc, char **argv)

if ( bShouldPaint )
{
paint_all( pPaintFocus, eFlipType == FlipType::Async );
paint_all( pPaintFocus, eFlipType == FlipType::Async, bRepeatFrame );

bPainted = true;
}
Expand All @@ -10909,8 +10939,12 @@ steamcompmgr_main(int argc, char **argv)
{
GetBackend()->OnEndFrame();

if ( hasRepaint )
s_ulLastContentPaintTime = get_time_in_nanos();

hasRepaint = false;
hasRepaintNonBasePlane = false;
hasCursorRepaint = false;
nIgnoredOverlayRepaints = 0;

{
Expand Down
5 changes: 3 additions & 2 deletions src/wlserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct wlr_surface *wlserver_surface_to_main_surface( struct wlr_surface *pSurfa
bool wlserver_process_hotkeys( wlr_keyboard *keyboard, uint32_t key, bool press );

extern std::atomic<bool> hasRepaint;
extern std::atomic<bool> hasCursorRepaint;

std::vector<ResListEntry_t>& gamescope_xwayland_server_t::retrieve_commits()
{
Expand Down Expand Up @@ -2818,7 +2819,7 @@ void wlserver_oncursorevent()

if ( !wlserver.bCursorHidden && wlserver.bCursorHasImage )
{
hasRepaint = true;
hasCursorRepaint = true;
}
}

Expand Down Expand Up @@ -2972,7 +2973,7 @@ void wlserver_mousehide()
if ( wlserver.bCursorHidden != true )
{
wlserver.bCursorHidden = true;
hasRepaint = true;
hasCursorRepaint = true;
}
}

Expand Down
Loading