mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-31 04:01:56 -07:00
opengl: detect android fence support and disable explicit if it's missing (#11077)
Checks for explicit sync support via the android fences, and falls back to implicit sync if it isn't
This commit is contained in:
@@ -8,10 +8,15 @@ CMonitorFrameScheduler::CMonitorFrameScheduler(PHLMONITOR m) : m_monitor(m) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onSyncFired() {
|
bool CMonitorFrameScheduler::newSchedulingEnabled() {
|
||||||
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
||||||
|
|
||||||
if (!*PENABLENEW)
|
return *PENABLENEW && g_pHyprOpenGL->explicitSyncSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitorFrameScheduler::onSyncFired() {
|
||||||
|
|
||||||
|
if (!newSchedulingEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Sync fired: reset submitted state, set as rendered. Check the last render time. If we are running
|
// Sync fired: reset submitted state, set as rendered. Check the last render time. If we are running
|
||||||
@@ -36,9 +41,7 @@ void CMonitorFrameScheduler::onSyncFired() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onPresented() {
|
void CMonitorFrameScheduler::onPresented() {
|
||||||
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
if (!newSchedulingEnabled())
|
||||||
|
|
||||||
if (!*PENABLENEW)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_pendingThird)
|
if (!m_pendingThird)
|
||||||
@@ -65,8 +68,6 @@ void CMonitorFrameScheduler::onPresented() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onFrame() {
|
void CMonitorFrameScheduler::onFrame() {
|
||||||
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
|
||||||
|
|
||||||
if (!canRender())
|
if (!canRender())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ void CMonitorFrameScheduler::onFrame() {
|
|||||||
m_monitor->m_tearingState.frameScheduledWhileBusy = false;
|
m_monitor->m_tearingState.frameScheduledWhileBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*PENABLENEW) {
|
if (!newSchedulingEnabled()) {
|
||||||
m_monitor->m_lastPresentationTimer.reset();
|
m_monitor->m_lastPresentationTimer.reset();
|
||||||
|
|
||||||
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
||||||
|
@@ -24,6 +24,7 @@ class CMonitorFrameScheduler {
|
|||||||
private:
|
private:
|
||||||
bool canRender();
|
bool canRender();
|
||||||
void onFinishRender();
|
void onFinishRender();
|
||||||
|
bool newSchedulingEnabled();
|
||||||
|
|
||||||
bool m_renderAtFrame = true;
|
bool m_renderAtFrame = true;
|
||||||
bool m_pendingThird = false;
|
bool m_pendingThird = false;
|
||||||
|
@@ -210,7 +210,7 @@ CProtocolManager::CProtocolManager() {
|
|||||||
else
|
else
|
||||||
lease.reset();
|
lease.reset();
|
||||||
|
|
||||||
if (!PROTO::sync)
|
if (g_pHyprOpenGL->m_exts.EGL_ANDROID_native_fence_sync_ext && !PROTO::sync)
|
||||||
PROTO::sync = makeUnique<CDRMSyncobjProtocol>(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj");
|
PROTO::sync = makeUnique<CDRMSyncobjProtocol>(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -257,7 +257,7 @@ EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) {
|
|||||||
CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
||||||
const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||||
|
|
||||||
Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS, ' '), EGLEXTENSIONS);
|
Debug::log(LOG, "Supported EGL global extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS, ' '), EGLEXTENSIONS);
|
||||||
|
|
||||||
m_exts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference");
|
m_exts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference");
|
||||||
|
|
||||||
@@ -344,6 +344,15 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
|||||||
if (!m_exts.EXT_image_dma_buf_import || !m_exts.EXT_image_dma_buf_import_modifiers)
|
if (!m_exts.EXT_image_dma_buf_import || !m_exts.EXT_image_dma_buf_import_modifiers)
|
||||||
Debug::log(WARN, "Your GPU does not support DMABUFs, this will possibly cause issues and will take a hit on the performance.");
|
Debug::log(WARN, "Your GPU does not support DMABUFs, this will possibly cause issues and will take a hit on the performance.");
|
||||||
|
|
||||||
|
const std::string EGLEXTENSIONS_DISPLAY = (const char*)eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Supported EGL display extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS_DISPLAY, ' '), EGLEXTENSIONS_DISPLAY);
|
||||||
|
|
||||||
|
m_exts.EGL_ANDROID_native_fence_sync_ext = EGLEXTENSIONS_DISPLAY.contains("EGL_ANDROID_native_fence_sync");
|
||||||
|
|
||||||
|
if (!m_exts.EGL_ANDROID_native_fence_sync_ext)
|
||||||
|
Debug::log(WARN, "Your GPU does not support explicit sync via the EGL_ANDROID_native_fence_sync extension.");
|
||||||
|
|
||||||
#ifdef USE_TRACY_GPU
|
#ifdef USE_TRACY_GPU
|
||||||
|
|
||||||
loadGLProc(&glQueryCounter, "glQueryCounterEXT");
|
loadGLProc(&glQueryCounter, "glQueryCounterEXT");
|
||||||
@@ -3054,6 +3063,10 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(PHLMONITOR pMonitor) {
|
|||||||
return pMonitor->m_output->state->state().drmFormat;
|
return pMonitor->m_output->state->state().drmFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CHyprOpenGLImpl::explicitSyncSupported() {
|
||||||
|
return m_exts.EGL_ANDROID_native_fence_sync_ext;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
||||||
return m_drmFormats;
|
return m_drmFormats;
|
||||||
}
|
}
|
||||||
@@ -3120,6 +3133,8 @@ float SRenderModifData::combinedScale() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UP<CEGLSync> CEGLSync::create() {
|
UP<CEGLSync> CEGLSync::create() {
|
||||||
|
RASSERT(g_pHyprOpenGL->m_exts.EGL_ANDROID_native_fence_sync_ext, "Tried to create an EGL sync when syncs are not supported on the gpu");
|
||||||
|
|
||||||
EGLSyncKHR sync = g_pHyprOpenGL->m_proc.eglCreateSyncKHR(g_pHyprOpenGL->m_eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
EGLSyncKHR sync = g_pHyprOpenGL->m_proc.eglCreateSyncKHR(g_pHyprOpenGL->m_eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
||||||
|
|
||||||
if (sync == EGL_NO_SYNC_KHR) {
|
if (sync == EGL_NO_SYNC_KHR) {
|
||||||
|
@@ -253,6 +253,8 @@ class CHyprOpenGLImpl {
|
|||||||
|
|
||||||
void ensureLockTexturesRendered(bool load);
|
void ensureLockTexturesRendered(bool load);
|
||||||
|
|
||||||
|
bool explicitSyncSupported();
|
||||||
|
|
||||||
bool m_shadersInitialized = false;
|
bool m_shadersInitialized = false;
|
||||||
SP<SPreparedShaders> m_shaders;
|
SP<SPreparedShaders> m_shaders;
|
||||||
|
|
||||||
@@ -297,6 +299,7 @@ class CHyprOpenGLImpl {
|
|||||||
bool KHR_display_reference = false;
|
bool KHR_display_reference = false;
|
||||||
bool IMG_context_priority = false;
|
bool IMG_context_priority = false;
|
||||||
bool EXT_create_context_robustness = false;
|
bool EXT_create_context_robustness = false;
|
||||||
|
bool EGL_ANDROID_native_fence_sync_ext = false;
|
||||||
} m_exts;
|
} m_exts;
|
||||||
|
|
||||||
SP<CTexture> m_screencopyDeniedTexture;
|
SP<CTexture> m_screencopyDeniedTexture;
|
||||||
|
@@ -2326,6 +2326,22 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
|||||||
if (m_renderMode == RENDER_MODE_NORMAL)
|
if (m_renderMode == RENDER_MODE_NORMAL)
|
||||||
PMONITOR->m_output->state->setBuffer(m_currentBuffer);
|
PMONITOR->m_output->state->setBuffer(m_currentBuffer);
|
||||||
|
|
||||||
|
if (!g_pHyprOpenGL->explicitSyncSupported()) {
|
||||||
|
Debug::log(TRACE, "renderer: Explicit sync unsupported, falling back to implicit in endRender");
|
||||||
|
|
||||||
|
// nvidia doesn't have implicit sync, so we have to explicitly wait here
|
||||||
|
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
||||||
|
glFinish();
|
||||||
|
else
|
||||||
|
glFlush(); // mark an implicit sync point
|
||||||
|
|
||||||
|
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||||
|
if (renderingDoneCallback)
|
||||||
|
renderingDoneCallback();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UP<CEGLSync> eglSync = CEGLSync::create();
|
UP<CEGLSync> eglSync = CEGLSync::create();
|
||||||
if (eglSync && eglSync->isValid()) {
|
if (eglSync && eglSync->isValid()) {
|
||||||
for (auto const& buf : m_usedAsyncBuffers) {
|
for (auto const& buf : m_usedAsyncBuffers) {
|
||||||
@@ -2350,11 +2366,7 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
|||||||
PMONITOR->m_output->state->setExplicitInFence(PMONITOR->m_inFence.get());
|
PMONITOR->m_output->state->setExplicitInFence(PMONITOR->m_inFence.get());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(ERR, "renderer: couldn't use EGLSync for explicit gpu synchronization");
|
Debug::log(ERR, "renderer: Explicit sync failed, releasing resources");
|
||||||
|
|
||||||
// nvidia doesn't have implicit sync, so we have to explicitly wait here
|
|
||||||
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
|
||||||
glFinish();
|
|
||||||
|
|
||||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||||
if (renderingDoneCallback)
|
if (renderingDoneCallback)
|
||||||
|
Reference in New Issue
Block a user