From 7c01f70bdc82ca1cfad7616ac1ce0ee9bb249c96 Mon Sep 17 00:00:00 2001 From: Trigger Huang Date: Sat, 14 Sep 2024 16:32:49 +0800 Subject: [PATCH] mesa: Fix AMD performance monitor implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For cmd GL_PERFMON_RESULT_SIZE_AMD and GL_PERFMON_RESULT_AMD of glGetPerfMonitorCounterDataAMD(), the current implementation will return 0 if the result is not available on HW, but according to the sepc, if cmd is PERFMON_RESULT_SIZE_AMD, will contain actual size of all counter results being sampled, instead of 0. And if cmd is PERFMON_RESULT_AMD, will contain results. The spec doesn't require the application to wait for the result available on HW before executing cmd PERFMON_RESULT_SIZE_AMD and PERFMON_RESULT_AMD. So for cmd PERFMON_RESULT_SIZE_AMD, it should immediately return the correct result size for the counters enabled by glSelectPerfMonitorCountersAMD(), and for cmd PERFMON_RESULT_AMD, it should wait until the result is available on HW and then return the result. Without this fix, the Sample Usage in the spec will not work properly as it always gets size 0 when calling the cmd PERFMON_RESULT_SIZE_AMD V2: If SelectPerfMonitorCountersAMD is called on a monitor, then the result of querying for PERFMON_RESULT_SIZE will be 0. Signed-off-by: Trigger Huang Reviewed-by: Marek Olšák Part-of: --- src/mesa/main/performance_monitor.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/mesa/main/performance_monitor.c b/src/mesa/main/performance_monitor.c index cfb9db649b3..c184a8bd165 100644 --- a/src/mesa/main/performance_monitor.c +++ b/src/mesa/main/performance_monitor.c @@ -941,6 +941,15 @@ perf_monitor_result_size(const struct gl_context *ctx, unsigned group, counter; unsigned size = 0; + /** + * If no BeginPerfMonitorAMD has been issued for a monitor, + * or if SelectPerfMonitorCountersAMD is called on a monitor, then the result + * of querying for PERFMON_RESULT_SIZE will be 0. + * Using the same logic in is_perf_monitor_result_available(). + */ + if (!m->num_active_counters) + return 0; + for (group = 0; group < ctx->PerfMonitor.NumGroups; group++) { const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[group]; @@ -963,7 +972,6 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, GET_CURRENT_CONTEXT(ctx); struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); - bool result_available; if (m == NULL) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -985,12 +993,12 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, return; } - /* If the monitor has never ended, there is no result. */ - result_available = m->Ended && - is_perf_monitor_result_available(ctx, m); - - /* AMD appears to return 0 for all queries unless a result is available. */ - if (!result_available) { + /** + * If no EndPerfMonitorAMD has been issued for a monitor + * then the result of querying for PERFMON_RESULT_AVAILABLE and + * PERFMON_RESULT_SIZE will be 0 + */ + if (!m->Ended) { *data = 0; if (bytesWritten != NULL) *bytesWritten = sizeof(GLuint); @@ -999,7 +1007,10 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, switch (pname) { case GL_PERFMON_RESULT_AVAILABLE_AMD: - *data = 1; + if (is_perf_monitor_result_available(ctx, m)) + *data = 1; + else + *data = 0; if (bytesWritten != NULL) *bytesWritten = sizeof(GLuint); break;