Files
dolphin/Source/Core/VideoBackends/OGL/OGLPerfQuery.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

285 lines
7.1 KiB
C++
Raw Normal View History

// Copyright 2012 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoBackends/OGL/OGLPerfQuery.h"
#include <memory>
2016-01-17 16:54:31 -05:00
#include "Common/CommonTypes.h"
2018-10-03 23:03:26 +10:00
#include "Common/GL/GLExtensions/GLExtensions.h"
2023-01-27 13:21:09 +13:00
#include "VideoBackends/OGL/OGLGfx.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/VideoCommon.h"
2016-06-13 15:41:29 +10:00
#include "VideoCommon/VideoConfig.h"
2012-06-17 13:58:29 +02:00
namespace OGL
{
std::unique_ptr<PerfQueryBase> GetPerfQuery(bool is_gles)
{
2018-10-03 23:03:26 +10:00
if (is_gles && GLExtensions::Supports("GL_NV_occlusion_query_samples"))
return std::make_unique<PerfQueryGLESNV>();
2018-10-03 23:03:26 +10:00
else if (is_gles)
return std::make_unique<PerfQueryGL>(GL_ANY_SAMPLES_PASSED);
2018-10-03 23:03:26 +10:00
else
return std::make_unique<PerfQueryGL>(GL_SAMPLES_PASSED);
}
2012-06-17 13:58:29 +02:00
PerfQuery::PerfQuery() : m_query_read_pos()
{
ResetQuery();
2012-06-17 13:58:29 +02:00
}
void PerfQuery::EnableQuery(PerfQueryGroup group)
2012-06-17 13:58:29 +02:00
{
m_query->EnableQuery(group);
2012-06-17 13:58:29 +02:00
}
void PerfQuery::DisableQuery(PerfQueryGroup group)
2012-06-17 13:58:29 +02:00
{
m_query->DisableQuery(group);
}
2012-06-17 13:58:29 +02:00
bool PerfQuery::IsFlushed() const
{
2021-05-13 19:30:30 +02:00
return m_query_count.load(std::memory_order_relaxed) == 0;
}
// TODO: could selectively flush things, but I don't think that will do much
void PerfQuery::FlushResults()
{
m_query->FlushResults();
2012-06-17 13:58:29 +02:00
}
void PerfQuery::ResetQuery()
{
2021-05-13 19:30:30 +02:00
m_query_count.store(0, std::memory_order_relaxed);
2025-04-13 08:35:31 +02:00
for (auto& result : m_results)
result.store(0, std::memory_order_relaxed);
2012-06-17 13:58:29 +02:00
}
u32 PerfQuery::GetQueryResult(PerfQueryType type)
{
u32 result = 0;
if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
2012-06-17 13:58:29 +02:00
{
2021-05-13 19:30:30 +02:00
result = m_results[PQG_ZCOMP_ZCOMPLOC].load(std::memory_order_relaxed);
2012-06-17 13:58:29 +02:00
}
else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
2012-06-17 13:58:29 +02:00
{
2021-05-13 19:30:30 +02:00
result = m_results[PQG_ZCOMP].load(std::memory_order_relaxed);
2012-06-17 13:58:29 +02:00
}
else if (type == PQ_BLEND_INPUT)
2012-06-17 13:58:29 +02:00
{
2021-05-13 19:30:30 +02:00
result = m_results[PQG_ZCOMP].load(std::memory_order_relaxed) +
m_results[PQG_ZCOMP_ZCOMPLOC].load(std::memory_order_relaxed);
2012-06-17 13:58:29 +02:00
}
else if (type == PQ_EFB_COPY_CLOCKS)
2012-06-17 13:58:29 +02:00
{
2021-05-13 19:30:30 +02:00
result = m_results[PQG_EFB_COPY_CLOCKS].load(std::memory_order_relaxed);
2012-06-17 13:58:29 +02:00
}
return result / 4;
2012-06-17 13:58:29 +02:00
}
// Implementations
PerfQueryGL::PerfQueryGL(GLenum query_type) : m_query_type(query_type)
{
for (ActiveQuery& query : m_query_buffer)
glGenQueries(1, &query.query_id);
}
PerfQueryGL::~PerfQueryGL()
{
for (ActiveQuery& query : m_query_buffer)
glDeleteQueries(1, &query.query_id);
}
void PerfQueryGL::EnableQuery(PerfQueryGroup group)
{
2021-05-21 12:48:27 +02:00
u32 query_count = m_query_count.load(std::memory_order_relaxed);
2021-05-13 19:30:30 +02:00
// Is this sane?
2021-05-13 19:30:30 +02:00
if (query_count > m_query_buffer.size() / 2)
2021-05-21 12:48:27 +02:00
{
WeakFlush();
2021-05-21 12:48:27 +02:00
query_count = m_query_count.load(std::memory_order_relaxed);
}
2021-05-13 19:30:30 +02:00
if (m_query_buffer.size() == query_count)
{
FlushOne();
2021-05-21 12:48:27 +02:00
query_count = m_query_count.load(std::memory_order_relaxed);
2020-11-09 03:08:00 -05:00
// ERROR_LOG_FMT(VIDEO, "Flushed query buffer early!");
}
// start query
if (group == PQG_ZCOMP_ZCOMPLOC || group == PQG_ZCOMP)
{
2021-05-13 19:30:30 +02:00
auto& entry = m_query_buffer[(m_query_read_pos + query_count) % m_query_buffer.size()];
glBeginQuery(m_query_type, entry.query_id);
entry.query_group = group;
2021-05-13 19:30:30 +02:00
m_query_count.fetch_add(1, std::memory_order_relaxed);
}
}
void PerfQueryGL::DisableQuery(PerfQueryGroup group)
{
// stop query
if (group == PQG_ZCOMP_ZCOMPLOC || group == PQG_ZCOMP)
{
glEndQuery(m_query_type);
}
}
void PerfQueryGL::WeakFlush()
{
while (!IsFlushed())
{
auto& entry = m_query_buffer[m_query_read_pos];
GLuint result = GL_FALSE;
glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE, &result);
if (GL_TRUE == result)
{
FlushOne();
}
else
{
break;
}
}
}
void PerfQueryGL::FlushOne()
{
auto& entry = m_query_buffer[m_query_read_pos];
GLuint result = 0;
glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result);
// NOTE: Reported pixel metrics should be referenced to native resolution
2016-06-13 15:41:29 +10:00
// TODO: Dropping the lower 2 bits from this count should be closer to actual
// hardware behavior when drawing triangles.
result = static_cast<u64>(result) * EFB_WIDTH * EFB_HEIGHT /
(g_framebuffer_manager->GetEFBWidth() * g_framebuffer_manager->GetEFBHeight());
2016-06-13 15:41:29 +10:00
// Adjust for multisampling
if (g_ActiveConfig.iMultisamples > 1)
result /= g_ActiveConfig.iMultisamples;
m_results[entry.query_group].fetch_add(result, std::memory_order_relaxed);
m_query_read_pos = (m_query_read_pos + 1) % m_query_buffer.size();
2021-05-13 19:30:30 +02:00
m_query_count.fetch_sub(1, std::memory_order_relaxed);
}
// TODO: could selectively flush things, but I don't think that will do much
void PerfQueryGL::FlushResults()
{
while (!IsFlushed())
FlushOne();
}
PerfQueryGLESNV::PerfQueryGLESNV()
{
for (ActiveQuery& query : m_query_buffer)
glGenOcclusionQueriesNV(1, &query.query_id);
}
PerfQueryGLESNV::~PerfQueryGLESNV()
{
for (ActiveQuery& query : m_query_buffer)
glDeleteOcclusionQueriesNV(1, &query.query_id);
}
void PerfQueryGLESNV::EnableQuery(PerfQueryGroup group)
{
2021-05-21 12:48:27 +02:00
u32 query_count = m_query_count.load(std::memory_order_relaxed);
// Is this sane?
2021-05-13 19:30:30 +02:00
if (query_count > m_query_buffer.size() / 2)
2021-05-21 12:48:27 +02:00
{
WeakFlush();
2021-05-21 12:48:27 +02:00
query_count = m_query_count.load(std::memory_order_relaxed);
}
2021-05-13 19:30:30 +02:00
if (m_query_buffer.size() == query_count)
{
FlushOne();
2021-05-21 12:48:27 +02:00
query_count = m_query_count.load(std::memory_order_relaxed);
2020-11-09 03:08:00 -05:00
// ERROR_LOG_FMT(VIDEO, "Flushed query buffer early!");
}
// start query
if (group == PQG_ZCOMP_ZCOMPLOC || group == PQG_ZCOMP)
{
2021-05-13 19:30:30 +02:00
auto& entry = m_query_buffer[(m_query_read_pos + query_count) % m_query_buffer.size()];
glBeginOcclusionQueryNV(entry.query_id);
entry.query_group = group;
2021-05-13 19:30:30 +02:00
m_query_count.fetch_add(1, std::memory_order_relaxed);
}
}
void PerfQueryGLESNV::DisableQuery(PerfQueryGroup group)
{
// stop query
if (group == PQG_ZCOMP_ZCOMPLOC || group == PQG_ZCOMP)
{
glEndOcclusionQueryNV();
}
}
void PerfQueryGLESNV::WeakFlush()
{
while (!IsFlushed())
{
auto& entry = m_query_buffer[m_query_read_pos];
GLuint result = GL_FALSE;
glGetOcclusionQueryuivNV(entry.query_id, GL_PIXEL_COUNT_AVAILABLE_NV, &result);
if (GL_TRUE == result)
{
FlushOne();
}
else
{
break;
}
}
}
void PerfQueryGLESNV::FlushOne()
{
auto& entry = m_query_buffer[m_query_read_pos];
GLuint result = 0;
glGetOcclusionQueryuivNV(entry.query_id, GL_OCCLUSION_TEST_RESULT_HP, &result);
// NOTE: Reported pixel metrics should be referenced to native resolution
2016-06-13 15:41:29 +10:00
// TODO: Dropping the lower 2 bits from this count should be closer to actual
// hardware behavior when drawing triangles.
2023-01-31 17:29:16 +13:00
const u64 native_res_result =
static_cast<u64>(result) * EFB_WIDTH * EFB_HEIGHT /
(g_framebuffer_manager->GetEFBWidth() * g_framebuffer_manager->GetEFBHeight());
m_results[entry.query_group].fetch_add(static_cast<u32>(native_res_result),
std::memory_order_relaxed);
m_query_read_pos = (m_query_read_pos + 1) % m_query_buffer.size();
2021-05-13 19:30:30 +02:00
m_query_count.fetch_sub(1, std::memory_order_relaxed);
}
// TODO: could selectively flush things, but I don't think that will do much
void PerfQueryGLESNV::FlushResults()
{
while (!IsFlushed())
FlushOne();
}
} // namespace OGL