You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.1 KiB
84 lines
2.1 KiB
/* |
|
KWin - the KDE window manager |
|
This file is part of the KDE project. |
|
|
|
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
#include "glrendertimequery.h" |
|
#include "opengl/glplatform.h" |
|
|
|
namespace KWin |
|
{ |
|
|
|
GLRenderTimeQuery::GLRenderTimeQuery(const std::shared_ptr<OpenGlContext> &context) |
|
: m_context(context) |
|
{ |
|
if (context->supportsTimerQueries()) { |
|
glGenQueries(1, &m_gpuProbe.query); |
|
} |
|
} |
|
|
|
GLRenderTimeQuery::~GLRenderTimeQuery() |
|
{ |
|
if (!m_gpuProbe.query) { |
|
return; |
|
} |
|
const auto context = m_context.lock(); |
|
if (!context) { |
|
return; |
|
} |
|
context->makeCurrent(); |
|
glDeleteQueries(1, &m_gpuProbe.query); |
|
} |
|
|
|
void GLRenderTimeQuery::begin() |
|
{ |
|
if (m_gpuProbe.query) { |
|
GLint64 start = 0; |
|
glGetInteger64v(GL_TIMESTAMP, &start); |
|
m_gpuProbe.start = std::chrono::nanoseconds(start); |
|
} |
|
m_cpuProbe.start = std::chrono::steady_clock::now(); |
|
} |
|
|
|
void GLRenderTimeQuery::end() |
|
{ |
|
m_hasResult = true; |
|
|
|
if (m_gpuProbe.query) { |
|
glQueryCounter(m_gpuProbe.query, GL_TIMESTAMP); |
|
} |
|
m_cpuProbe.end = std::chrono::steady_clock::now(); |
|
} |
|
|
|
std::optional<RenderTimeSpan> GLRenderTimeQuery::query() |
|
{ |
|
if (!m_hasResult) { |
|
return std::nullopt; |
|
} |
|
m_hasResult = false; |
|
|
|
if (m_gpuProbe.query) { |
|
const auto context = m_context.lock(); |
|
if (!context) { |
|
return std::nullopt; |
|
} |
|
context->makeCurrent(); |
|
GLint64 end = 0; |
|
glGetQueryObjecti64v(m_gpuProbe.query, GL_QUERY_RESULT, &end); |
|
m_gpuProbe.end = std::chrono::nanoseconds(end); |
|
} |
|
|
|
// timings are pretty unpredictable in the sub-millisecond range; this minimum |
|
// ensures that when CPU or GPU power states change, we don't drop any frames |
|
const std::chrono::nanoseconds minimumTime = std::chrono::milliseconds(2); |
|
const auto end = std::max({m_cpuProbe.start + (m_gpuProbe.end - m_gpuProbe.start), m_cpuProbe.end, m_cpuProbe.start + minimumTime}); |
|
return RenderTimeSpan{ |
|
.start = m_cpuProbe.start, |
|
.end = end, |
|
}; |
|
} |
|
|
|
}
|
|
|