Module: Mesa Branch: main Commit: bc9b176aef9cd4b8551a513806d34decf853f9a0 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=bc9b176aef9cd4b8551a513806d34decf853f9a0
Author: Dave Airlie <[email protected]> Date: Thu Dec 16 08:40:56 2021 +1000 mesa/st: move perfmon code from st into mesa This merges the perfmon code after the objects have been merged. Acked-by: Marek Olšák <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14327> --- src/mesa/main/performance_monitor.c | 294 +++++++++++++++++++++++++++++++-- src/mesa/state_tracker/st_cb_perfmon.c | 273 ------------------------------ src/mesa/state_tracker/st_cb_perfmon.h | 11 -- 3 files changed, 284 insertions(+), 294 deletions(-) diff --git a/src/mesa/main/performance_monitor.c b/src/mesa/main/performance_monitor.c index 73893005b2d..5228b1eec88 100644 --- a/src/mesa/main/performance_monitor.c +++ b/src/mesa/main/performance_monitor.c @@ -47,7 +47,9 @@ #include "util/u_memory.h" #include "api_exec_decl.h" -#include "state_tracker/st_cb_perfmon.h" +#include "state_tracker/st_cb_bitmap.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_debug.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" @@ -60,6 +62,278 @@ _mesa_init_performance_monitors(struct gl_context *ctx) ctx->PerfMonitor.Groups = NULL; } + +static bool +init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct pipe_context *pipe = ctx->pipe; + unsigned *batch = NULL; + unsigned num_active_counters = 0; + unsigned max_batch_counters = 0; + unsigned num_batch_counters = 0; + int gid, cid; + + st_flush_bitmap_cache(st_context(ctx)); + + /* Determine the number of active counters. */ + for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) { + const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid]; + + if (m->ActiveGroups[gid] > g->MaxActiveCounters) { + /* Maximum number of counters reached. Cannot start the session. */ + if (ST_DEBUG & DEBUG_MESA) { + debug_printf("Maximum number of counters reached. " + "Cannot start the session!\n"); + } + return false; + } + + num_active_counters += m->ActiveGroups[gid]; + if (g->has_batch) + max_batch_counters += m->ActiveGroups[gid]; + } + + if (!num_active_counters) + return true; + + m->active_counters = CALLOC(num_active_counters, + sizeof(*m->active_counters)); + if (!m->active_counters) + return false; + + if (max_batch_counters) { + batch = CALLOC(max_batch_counters, sizeof(*batch)); + if (!batch) + return false; + } + + /* Create a query for each active counter. */ + for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) { + const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid]; + + BITSET_FOREACH_SET(cid, m->ActiveCounters[gid], g->NumCounters) { + const struct gl_perf_monitor_counter *c = &g->Counters[cid]; + struct gl_perf_counter_object *cntr = + &m->active_counters[m->num_active_counters]; + + cntr->id = cid; + cntr->group_id = gid; + if (c->flags & PIPE_DRIVER_QUERY_FLAG_BATCH) { + cntr->batch_index = num_batch_counters; + batch[num_batch_counters++] = c->query_type; + } else { + cntr->query = pipe->create_query(pipe, c->query_type, 0); + if (!cntr->query) + goto fail; + } + ++m->num_active_counters; + } + } + + /* Create the batch query. */ + if (num_batch_counters) { + m->batch_query = pipe->create_batch_query(pipe, num_batch_counters, + batch); + m->batch_result = CALLOC(num_batch_counters, sizeof(m->batch_result->batch[0])); + if (!m->batch_query || !m->batch_result) + goto fail; + } + + FREE(batch); + return true; + +fail: + FREE(batch); + return false; +} + +static void +do_reset_perf_monitor(struct gl_perf_monitor_object *m, + struct pipe_context *pipe) +{ + unsigned i; + + for (i = 0; i < m->num_active_counters; ++i) { + struct pipe_query *query = m->active_counters[i].query; + if (query) + pipe->destroy_query(pipe, query); + } + FREE(m->active_counters); + m->active_counters = NULL; + m->num_active_counters = 0; + + if (m->batch_query) { + pipe->destroy_query(pipe, m->batch_query); + m->batch_query = NULL; + } + FREE(m->batch_result); + m->batch_result = NULL; +} + +static void +delete_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + do_reset_perf_monitor(m, pipe); + FREE(m); +} + +static GLboolean +begin_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + unsigned i; + + if (!m->num_active_counters) { + /* Create a query for each active counter before starting + * a new monitoring session. */ + if (!init_perf_monitor(ctx, m)) + goto fail; + } + + /* Start the query for each active counter. */ + for (i = 0; i < m->num_active_counters; ++i) { + struct pipe_query *query = m->active_counters[i].query; + if (query && !pipe->begin_query(pipe, query)) + goto fail; + } + + if (m->batch_query && !pipe->begin_query(pipe, m->batch_query)) + goto fail; + + return true; + +fail: + /* Failed to start the monitoring session. */ + do_reset_perf_monitor(m, pipe); + return false; +} + +static void +end_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + unsigned i; + + /* Stop the query for each active counter. */ + for (i = 0; i < m->num_active_counters; ++i) { + struct pipe_query *query = m->active_counters[i].query; + if (query) + pipe->end_query(pipe, query); + } + + if (m->batch_query) + pipe->end_query(pipe, m->batch_query); +} + +static void +reset_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + if (!m->Ended) + end_perf_monitor(ctx, m); + + do_reset_perf_monitor(m, pipe); + + if (m->Active) + begin_perf_monitor(ctx, m); +} + +static GLboolean +is_perf_monitor_result_available(struct gl_context *ctx, + struct gl_perf_monitor_object *m) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + unsigned i; + + if (!m->num_active_counters) + return false; + + /* The result of a monitoring session is only available if the query of + * each active counter is idle. */ + for (i = 0; i < m->num_active_counters; ++i) { + struct pipe_query *query = m->active_counters[i].query; + union pipe_query_result result; + if (query && !pipe->get_query_result(pipe, query, FALSE, &result)) { + /* The query is busy. */ + return false; + } + } + + if (m->batch_query && + !pipe->get_query_result(pipe, m->batch_query, FALSE, m->batch_result)) + return false; + + return true; +} + +static void +get_perf_monitor_result(struct gl_context *ctx, + struct gl_perf_monitor_object *m, + GLsizei dataSize, + GLuint *data, + GLint *bytesWritten) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + unsigned i; + + /* Copy data to the supplied array (data). + * + * The output data format is: <group ID, counter ID, value> for each + * active counter. The API allows counters to appear in any order. + */ + GLsizei offset = 0; + bool have_batch_query = false; + + if (m->batch_query) + have_batch_query = pipe->get_query_result(pipe, m->batch_query, TRUE, + m->batch_result); + + /* Read query results for each active counter. */ + for (i = 0; i < m->num_active_counters; ++i) { + struct gl_perf_counter_object *cntr = &m->active_counters[i]; + union pipe_query_result result = { 0 }; + int gid, cid; + GLenum type; + + cid = cntr->id; + gid = cntr->group_id; + type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type; + + if (cntr->query) { + if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result)) + continue; + } else { + if (!have_batch_query) + continue; + result.batch[0] = m->batch_result->batch[cntr->batch_index]; + } + + data[offset++] = gid; + data[offset++] = cid; + switch (type) { + case GL_UNSIGNED_INT64_AMD: + memcpy(&data[offset], &result.u64, sizeof(uint64_t)); + offset += sizeof(uint64_t) / sizeof(GLuint); + break; + case GL_UNSIGNED_INT: + memcpy(&data[offset], &result.u32, sizeof(uint32_t)); + offset += sizeof(uint32_t) / sizeof(GLuint); + break; + case GL_FLOAT: + case GL_PERCENTAGE_AMD: + memcpy(&data[offset], &result.f, sizeof(GLfloat)); + offset += sizeof(GLfloat) / sizeof(GLuint); + break; + } + } + + if (bytesWritten) + *bytesWritten = offset * sizeof(GLuint); +} + void _mesa_free_perfomance_monitor_groups(struct gl_context *ctx) { @@ -204,7 +478,7 @@ new_performance_monitor(struct gl_context *ctx, GLuint index) fail: ralloc_free(m->ActiveGroups); ralloc_free(m->ActiveCounters); - st_DeletePerfMonitor(ctx, m); + delete_perf_monitor(ctx, m); return NULL; } @@ -216,7 +490,7 @@ free_performance_monitor(void *data, void *user) ralloc_free(m->ActiveGroups); ralloc_free(m->ActiveCounters); - st_DeletePerfMonitor(ctx, m); + delete_perf_monitor(ctx, m); } void @@ -501,14 +775,14 @@ _mesa_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors) if (m) { /* Give the driver a chance to stop the monitor if it's active. */ if (m->Active) { - st_ResetPerfMonitor(ctx, m); + reset_perf_monitor(ctx, m); m->Ended = false; } _mesa_HashRemove(ctx->PerfMonitor.Monitors, monitors[i]); ralloc_free(m->ActiveGroups); ralloc_free(m->ActiveCounters); - st_DeletePerfMonitor(ctx, m); + delete_perf_monitor(ctx, m); } else { /* "INVALID_VALUE error will be generated if any of the monitor IDs * in the <monitors> parameter to DeletePerfMonitorsAMD do not @@ -568,7 +842,7 @@ _mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, * results for that monitor become invalidated and the result queries * PERFMON_RESULT_SIZE_AMD and PERFMON_RESULT_AVAILABLE_AMD are reset to 0." */ - st_ResetPerfMonitor(ctx, m); + reset_perf_monitor(ctx, m); /* Sanity check the counter ID list. */ for (i = 0; i < numCounters; i++) { @@ -623,7 +897,7 @@ _mesa_BeginPerfMonitorAMD(GLuint monitor) /* The driver is free to return false if it can't begin monitoring for * any reason. This translates into an INVALID_OPERATION error. */ - if (st_BeginPerfMonitor(ctx, m)) { + if (begin_perf_monitor(ctx, m)) { m->Active = true; m->Ended = false; } else { @@ -652,7 +926,7 @@ _mesa_EndPerfMonitorAMD(GLuint monitor) return; } - st_EndPerfMonitor(ctx, m); + end_perf_monitor(ctx, m); m->Active = false; m->Ended = true; @@ -714,7 +988,7 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, /* If the monitor has never ended, there is no result. */ result_available = m->Ended && - st_IsPerfMonitorResultAvailable(ctx, m); + is_perf_monitor_result_available(ctx, m); /* AMD appears to return 0 for all queries unless a result is available. */ if (!result_available) { @@ -736,7 +1010,7 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, *bytesWritten = sizeof(GLuint); break; case GL_PERFMON_RESULT_AMD: - st_GetPerfMonitorResult(ctx, m, dataSize, data, bytesWritten); + get_perf_monitor_result(ctx, m, dataSize, data, bytesWritten); break; default: _mesa_error(ctx, GL_INVALID_ENUM, diff --git a/src/mesa/state_tracker/st_cb_perfmon.c b/src/mesa/state_tracker/st_cb_perfmon.c index 7c18c319f40..64c5ef9b911 100644 --- a/src/mesa/state_tracker/st_cb_perfmon.c +++ b/src/mesa/state_tracker/st_cb_perfmon.c @@ -39,279 +39,6 @@ #include "main/performance_monitor.h" -static bool -init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) -{ - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - unsigned *batch = NULL; - unsigned num_active_counters = 0; - unsigned max_batch_counters = 0; - unsigned num_batch_counters = 0; - int gid, cid; - - st_flush_bitmap_cache(st); - - /* Determine the number of active counters. */ - for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) { - const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid]; - - if (m->ActiveGroups[gid] > g->MaxActiveCounters) { - /* Maximum number of counters reached. Cannot start the session. */ - if (ST_DEBUG & DEBUG_MESA) { - debug_printf("Maximum number of counters reached. " - "Cannot start the session!\n"); - } - return false; - } - - num_active_counters += m->ActiveGroups[gid]; - if (g->has_batch) - max_batch_counters += m->ActiveGroups[gid]; - } - - if (!num_active_counters) - return true; - - m->active_counters = CALLOC(num_active_counters, - sizeof(*m->active_counters)); - if (!m->active_counters) - return false; - - if (max_batch_counters) { - batch = CALLOC(max_batch_counters, sizeof(*batch)); - if (!batch) - return false; - } - - /* Create a query for each active counter. */ - for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) { - const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid]; - - BITSET_FOREACH_SET(cid, m->ActiveCounters[gid], g->NumCounters) { - const struct gl_perf_monitor_counter *c = &g->Counters[cid]; - struct gl_perf_counter_object *cntr = - &m->active_counters[m->num_active_counters]; - - cntr->id = cid; - cntr->group_id = gid; - if (c->flags & PIPE_DRIVER_QUERY_FLAG_BATCH) { - cntr->batch_index = num_batch_counters; - batch[num_batch_counters++] = c->query_type; - } else { - cntr->query = pipe->create_query(pipe, c->query_type, 0); - if (!cntr->query) - goto fail; - } - ++m->num_active_counters; - } - } - - /* Create the batch query. */ - if (num_batch_counters) { - m->batch_query = pipe->create_batch_query(pipe, num_batch_counters, - batch); - m->batch_result = CALLOC(num_batch_counters, sizeof(m->batch_result->batch[0])); - if (!m->batch_query || !m->batch_result) - goto fail; - } - - FREE(batch); - return true; - -fail: - FREE(batch); - return false; -} - -static void -reset_perf_monitor(struct gl_perf_monitor_object *m, - struct pipe_context *pipe) -{ - unsigned i; - - for (i = 0; i < m->num_active_counters; ++i) { - struct pipe_query *query = m->active_counters[i].query; - if (query) - pipe->destroy_query(pipe, query); - } - FREE(m->active_counters); - m->active_counters = NULL; - m->num_active_counters = 0; - - if (m->batch_query) { - pipe->destroy_query(pipe, m->batch_query); - m->batch_query = NULL; - } - FREE(m->batch_result); - m->batch_result = NULL; -} - -void -st_DeletePerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - - reset_perf_monitor(m, pipe); - FREE(m); -} - -GLboolean -st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - unsigned i; - - if (!m->num_active_counters) { - /* Create a query for each active counter before starting - * a new monitoring session. */ - if (!init_perf_monitor(ctx, m)) - goto fail; - } - - /* Start the query for each active counter. */ - for (i = 0; i < m->num_active_counters; ++i) { - struct pipe_query *query = m->active_counters[i].query; - if (query && !pipe->begin_query(pipe, query)) - goto fail; - } - - if (m->batch_query && !pipe->begin_query(pipe, m->batch_query)) - goto fail; - - return true; - -fail: - /* Failed to start the monitoring session. */ - reset_perf_monitor(m, pipe); - return false; -} - -void -st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - unsigned i; - - /* Stop the query for each active counter. */ - for (i = 0; i < m->num_active_counters; ++i) { - struct pipe_query *query = m->active_counters[i].query; - if (query) - pipe->end_query(pipe, query); - } - - if (m->batch_query) - pipe->end_query(pipe, m->batch_query); -} - -void -st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - - if (!m->Ended) - st_EndPerfMonitor(ctx, m); - - reset_perf_monitor(m, pipe); - - if (m->Active) - st_BeginPerfMonitor(ctx, m); -} - -GLboolean -st_IsPerfMonitorResultAvailable(struct gl_context *ctx, - struct gl_perf_monitor_object *m) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - unsigned i; - - if (!m->num_active_counters) - return false; - - /* The result of a monitoring session is only available if the query of - * each active counter is idle. */ - for (i = 0; i < m->num_active_counters; ++i) { - struct pipe_query *query = m->active_counters[i].query; - union pipe_query_result result; - if (query && !pipe->get_query_result(pipe, query, FALSE, &result)) { - /* The query is busy. */ - return false; - } - } - - if (m->batch_query && - !pipe->get_query_result(pipe, m->batch_query, FALSE, m->batch_result)) - return false; - - return true; -} - -void -st_GetPerfMonitorResult(struct gl_context *ctx, - struct gl_perf_monitor_object *m, - GLsizei dataSize, - GLuint *data, - GLint *bytesWritten) -{ - struct pipe_context *pipe = st_context(ctx)->pipe; - unsigned i; - - /* Copy data to the supplied array (data). - * - * The output data format is: <group ID, counter ID, value> for each - * active counter. The API allows counters to appear in any order. - */ - GLsizei offset = 0; - bool have_batch_query = false; - - if (m->batch_query) - have_batch_query = pipe->get_query_result(pipe, m->batch_query, TRUE, - m->batch_result); - - /* Read query results for each active counter. */ - for (i = 0; i < m->num_active_counters; ++i) { - struct gl_perf_counter_object *cntr = &m->active_counters[i]; - union pipe_query_result result = { 0 }; - int gid, cid; - GLenum type; - - cid = cntr->id; - gid = cntr->group_id; - type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type; - - if (cntr->query) { - if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result)) - continue; - } else { - if (!have_batch_query) - continue; - result.batch[0] = m->batch_result->batch[cntr->batch_index]; - } - - data[offset++] = gid; - data[offset++] = cid; - switch (type) { - case GL_UNSIGNED_INT64_AMD: - memcpy(&data[offset], &result.u64, sizeof(uint64_t)); - offset += sizeof(uint64_t) / sizeof(GLuint); - break; - case GL_UNSIGNED_INT: - memcpy(&data[offset], &result.u32, sizeof(uint32_t)); - offset += sizeof(uint32_t) / sizeof(GLuint); - break; - case GL_FLOAT: - case GL_PERCENTAGE_AMD: - memcpy(&data[offset], &result.f, sizeof(GLfloat)); - offset += sizeof(GLfloat) / sizeof(GLuint); - break; - } - } - - if (bytesWritten) - *bytesWritten = offset * sizeof(GLuint); -} - - bool st_have_perfmon(struct st_context *st) { diff --git a/src/mesa/state_tracker/st_cb_perfmon.h b/src/mesa/state_tracker/st_cb_perfmon.h index 84daa7b0335..69480d3c4a9 100644 --- a/src/mesa/state_tracker/st_cb_perfmon.h +++ b/src/mesa/state_tracker/st_cb_perfmon.h @@ -32,15 +32,4 @@ st_have_perfmon(struct st_context *st); void st_destroy_perfmon(struct st_context *st); -void st_DeletePerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m); -GLboolean st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m); -void st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m); -void st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m); -GLboolean st_IsPerfMonitorResultAvailable(struct gl_context *ctx, - struct gl_perf_monitor_object *m); -void st_GetPerfMonitorResult(struct gl_context *ctx, - struct gl_perf_monitor_object *m, - GLsizei dataSize, - GLuint *data, - GLint *bytesWritten); #endif
