deadline: account for vrr, vfr and tearing.

account for vrr, vfr, and tearing.
This commit is contained in:
Tom Englund 2026-04-29 16:23:23 +02:00
parent aa09740100
commit 2991eb7934
5 changed files with 24 additions and 23 deletions

View file

@ -148,6 +148,8 @@
---| "ecosystem.enforce_permissions"
---| "ecosystem.no_donation_nag"
---| "ecosystem.no_update_news"
---| "experimental.deadline_client_buffer"
---| "experimental.deadline_main_buffer"
---| "experimental.wp_cm_1_2"
---| "general.allow_tearing"
---| "general.border_size"
@ -957,6 +959,8 @@ hl = {}
---@field ['ecosystem.enforce_permissions'] boolean
---@field ['ecosystem.no_donation_nag'] boolean
---@field ['ecosystem.no_update_news'] boolean
---@field ['experimental.deadline_client_buffer'] boolean
---@field ['experimental.deadline_main_buffer'] boolean
---@field ['experimental.wp_cm_1_2'] boolean
---@field ['general.allow_tearing'] boolean
---@field ['general.border_size'] integer|boolean

View file

@ -158,8 +158,11 @@ void CMonitor::onConnect(bool noRule) {
});
}
auto minVBlankInterval = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(1.0 / m_refreshRate));
m_estimatedNextVblank = (ts ? Time::fromTimespec(ts) : Time::steadyNow()) + minVBlankInterval;
if (m_pendingFrame) { // if no pending frame, VFR etc we cant estimate this.
auto minVBlankInterval = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(1.0 / m_refreshRate));
m_estimatedNextVblank = (ts ? Time::fromTimespec(ts) + minVBlankInterval : Time::steadyNow()) + minVBlankInterval;
} else
m_estimatedNextVblank = std::nullopt;
m_frameScheduler->onPresented();

View file

@ -50,7 +50,7 @@ void CHyprGLRenderer::initRender() {
bool CHyprGLRenderer::initRenderBuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
try {
m_currentRenderbuffer = getOrCreateRenderbuffer(m_currentBuffer.buffer, fmt);
m_currentRenderbuffer = getOrCreateRenderbuffer(m_currentBuffer, fmt);
} catch (std::exception& e) {
Log::logger->log(Log::ERR, "getOrCreateRenderbuffer failed for {}", NFormatUtils::drmFormatName(fmt));
return false;
@ -72,8 +72,6 @@ bool CHyprGLRenderer::beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion&
}
bool CHyprGLRenderer::beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple) {
m_currentBuffer.fence = DRM::exportFence(m_currentBuffer.buffer->dmabuf().fds[0]);
m_currentRenderbuffer->bind();
if (simple)
g_pHyprOpenGL->beginSimple(pMonitor, damage, m_currentRenderbuffer);
@ -93,7 +91,7 @@ void CHyprGLRenderer::endRender(const std::function<void()>& renderingDoneCallba
if (m_currentRenderbuffer)
m_currentRenderbuffer->unbind();
m_currentRenderbuffer = nullptr;
m_currentBuffer = {};
m_currentBuffer = nullptr;
});
if (m_renderMode != RENDER_MODE_TO_BUFFER_READ_ONLY)
@ -108,7 +106,7 @@ void CHyprGLRenderer::endRender(const std::function<void()>& renderingDoneCallba
return;
if (m_renderMode == RENDER_MODE_NORMAL)
PMONITOR->m_output->state->setBuffer(m_currentBuffer.buffer);
PMONITOR->m_output->state->setBuffer(m_currentBuffer);
if (!explicitSyncSupported()) {
Log::logger->log(Log::TRACE, "renderer: Explicit sync unsupported, falling back to implicit in endRender");

View file

@ -1655,17 +1655,17 @@ bool IHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMod
int bufferAge = 0;
if (!buffer) {
m_currentBuffer.buffer = pMonitor->m_output->swapchain->next(&bufferAge);
if (!m_currentBuffer.buffer) {
m_currentBuffer = pMonitor->m_output->swapchain->next(&bufferAge);
if (!m_currentBuffer) {
Log::logger->log(Log::ERR, "Failed to acquire swapchain buffer for {}", pMonitor->m_name);
return false;
}
} else
m_currentBuffer.buffer = buffer;
m_currentBuffer = buffer;
initRender();
if (!initRenderBuffer(m_currentBuffer.buffer, pMonitor->m_output->state->state().drmFormat)) {
if (!initRenderBuffer(m_currentBuffer, pMonitor->m_output->state->state().drmFormat)) {
Log::logger->log(Log::ERR, "failed to start a render pass for output {}, no RBO could be obtained", pMonitor->m_name);
return false;
}
@ -1916,6 +1916,8 @@ void IHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
const float ZOOMFACTOR = pMonitor->m_cursorZoom->value();
auto cleanup = CScopeGuard([pMonitor]() { pMonitor->m_estimatedNextVblank = std::nullopt; });
if (pMonitor->m_pixelSize.x < 1 || pMonitor->m_pixelSize.y < 1) {
Log::logger->log(Log::ERR, "Refusing to render a monitor because of an invalid pixel size: {}", pMonitor->m_pixelSize);
return;
@ -2350,15 +2352,13 @@ bool IHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
handleFullscreenSettings(pMonitor);
static const auto DEADLINE = CConfigValue<Config::INTEGER>("experimental:deadline_main_buffer");
if (*DEADLINE) {
if (*DEADLINE && m_currentBuffer) {
auto deadline = pMonitor->isMultiGPU() || pMonitor->m_vrrActive || pMonitor->m_tearingState.activelyTearing || !pMonitor->m_estimatedNextVblank.has_value() ?
Time::steadyNow() + std::chrono::microseconds(100) :
pMonitor->m_estimatedNextVblank;
if (deadline) {
DRM::setDeadline(deadline.value(), m_currentBuffer.fence);
pMonitor->m_estimatedNextVblank = std::nullopt;
}
pMonitor->m_estimatedNextVblank.value();
auto fence = DRM::exportFence(m_currentBuffer->dmabuf().fds[0]);
DRM::setDeadline(deadline, fence);
}
bool ok = pMonitor->m_state.commit();

View file

@ -276,11 +276,7 @@ namespace Render {
bool m_intel = false;
bool m_software = false;
bool m_mgpu = false;
struct SBuffer {
SP<Aquamarine::IBuffer> buffer = nullptr;
Hyprutils::OS::CFileDescriptor fence;
} m_currentBuffer;
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
struct {
bool hiddenOnTouch = false;