From aa0de724c7744d91e259ed6911ab8d1580d2f7da Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 15 Jan 2017 23:51:29 +0100 Subject: [PATCH] gallium/radeon: make the GPU load / GRBM_STATUS monitoring extensible MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The next patch will add SPI_BUSY monitoring. Reviewed-by: Nicolai Hähnle --- src/gallium/drivers/radeon/r600_gpu_load.c | 64 +++++++++++-------- src/gallium/drivers/radeon/r600_pipe_common.h | 15 +++-- src/gallium/drivers/radeon/r600_query.c | 6 +- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/src/gallium/drivers/radeon/r600_gpu_load.c b/src/gallium/drivers/radeon/r600_gpu_load.c index a653834b331..764d9b57262 100644 --- a/src/gallium/drivers/radeon/r600_gpu_load.c +++ b/src/gallium/drivers/radeon/r600_gpu_load.c @@ -44,12 +44,17 @@ #define GRBM_STATUS 0x8010 #define GUI_ACTIVE(x) (((x) >> 31) & 0x1) -static bool r600_is_gpu_busy(struct r600_common_screen *rscreen) +static void r600_update_grbm_counters(struct r600_common_screen *rscreen, + union r600_grbm_counters *counters) { uint32_t value = 0; rscreen->ws->read_registers(rscreen->ws, GRBM_STATUS, 1, &value); - return GUI_ACTIVE(value); + + if (GUI_ACTIVE(value)) + p_atomic_inc(&counters->named.gui_busy); + else + p_atomic_inc(&counters->named.gui_idle); } static PIPE_THREAD_ROUTINE(r600_gpu_load_thread, param) @@ -77,10 +82,7 @@ static PIPE_THREAD_ROUTINE(r600_gpu_load_thread, param) last_time = cur_time; /* Update the counters. */ - if (r600_is_gpu_busy(rscreen)) - p_atomic_inc(&rscreen->gpu_load_counter_busy); - else - p_atomic_inc(&rscreen->gpu_load_counter_idle); + r600_update_grbm_counters(rscreen, &rscreen->grbm_counters); } p_atomic_dec(&rscreen->gpu_load_stop_thread); return 0; @@ -96,7 +98,8 @@ void r600_gpu_load_kill_thread(struct r600_common_screen *rscreen) rscreen->gpu_load_thread = 0; } -static uint64_t r600_gpu_load_read_counter(struct r600_common_screen *rscreen) +static uint64_t r600_read_counter(struct r600_common_screen *rscreen, + unsigned busy_index) { /* Start the thread if needed. */ if (!rscreen->gpu_load_thread) { @@ -108,34 +111,45 @@ static uint64_t r600_gpu_load_read_counter(struct r600_common_screen *rscreen) pipe_mutex_unlock(rscreen->gpu_load_mutex); } - /* The busy counter is in the lower 32 bits. - * The idle counter is in the upper 32 bits. */ - return p_atomic_read(&rscreen->gpu_load_counter_busy) | - ((uint64_t)p_atomic_read(&rscreen->gpu_load_counter_idle) << 32); -} + unsigned busy = p_atomic_read(&rscreen->grbm_counters.array[busy_index]); + unsigned idle = p_atomic_read(&rscreen->grbm_counters.array[busy_index + 1]); -/** - * Just return the counters. - */ -uint64_t r600_gpu_load_begin(struct r600_common_screen *rscreen) -{ - return r600_gpu_load_read_counter(rscreen); + return busy | ((uint64_t)idle << 32); } -unsigned r600_gpu_load_end(struct r600_common_screen *rscreen, uint64_t begin) +static unsigned r600_end_counter(struct r600_common_screen *rscreen, + uint64_t begin, unsigned busy_index) { - uint64_t end = r600_gpu_load_read_counter(rscreen); + uint64_t end = r600_read_counter(rscreen, busy_index); unsigned busy = (end & 0xffffffff) - (begin & 0xffffffff); unsigned idle = (end >> 32) - (begin >> 32); - /* Calculate the GPU load. + /* Calculate the % of time the busy counter was being incremented. * - * If no counters have been incremented, return the current load. + * If no counters were incremented, return the current counter status. * It's for the case when the load is queried faster than * the counters are updated. */ - if (idle || busy) + if (idle || busy) { return busy*100 / (busy + idle); - else - return r600_is_gpu_busy(rscreen) ? 100 : 0; + } else { + union r600_grbm_counters counters; + + memset(&counters, 0, sizeof(counters)); + r600_update_grbm_counters(rscreen, &counters); + return counters.array[busy_index] ? 100 : 0; + } +} + +#define BUSY_INDEX(rscreen, field) (&rscreen->grbm_counters.named.field##_busy - \ + rscreen->grbm_counters.array) + +uint64_t r600_begin_counter_gui(struct r600_common_screen *rscreen) +{ + return r600_read_counter(rscreen, BUSY_INDEX(rscreen, gui)); +} + +unsigned r600_end_counter_gui(struct r600_common_screen *rscreen, uint64_t begin) +{ + return r600_end_counter(rscreen, begin, BUSY_INDEX(rscreen, gui)); } diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index 74f86dc3945..9f692985401 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -352,6 +352,14 @@ struct r600_surface { unsigned db_preload_control; /* EG and later */ }; +union r600_grbm_counters { + struct { + unsigned gui_busy; + unsigned gui_idle; + } named; + unsigned array[0]; +}; + struct r600_common_screen { struct pipe_screen b; struct radeon_winsys *ws; @@ -385,8 +393,7 @@ struct r600_common_screen { /* GPU load thread. */ pipe_mutex gpu_load_mutex; pipe_thread gpu_load_thread; - unsigned gpu_load_counter_busy; - unsigned gpu_load_counter_idle; + union r600_grbm_counters grbm_counters; volatile unsigned gpu_load_stop_thread; /* bool */ char renderer_string[100]; @@ -739,8 +746,8 @@ bool r600_check_device_reset(struct r600_common_context *rctx); /* r600_gpu_load.c */ void r600_gpu_load_kill_thread(struct r600_common_screen *rscreen); -uint64_t r600_gpu_load_begin(struct r600_common_screen *rscreen); -unsigned r600_gpu_load_end(struct r600_common_screen *rscreen, uint64_t begin); +uint64_t r600_begin_counter_gui(struct r600_common_screen *rscreen); +unsigned r600_end_counter_gui(struct r600_common_screen *rscreen, uint64_t begin); /* r600_perfcounters.c */ void r600_perfcounters_destroy(struct r600_common_screen *rscreen); diff --git a/src/gallium/drivers/radeon/r600_query.c b/src/gallium/drivers/radeon/r600_query.c index 3c72f27f151..b7fbd373b42 100644 --- a/src/gallium/drivers/radeon/r600_query.c +++ b/src/gallium/drivers/radeon/r600_query.c @@ -145,7 +145,7 @@ static bool r600_query_sw_begin(struct r600_common_context *rctx, break; } case R600_QUERY_GPU_LOAD: - query->begin_result = r600_gpu_load_begin(rctx->screen); + query->begin_result = r600_begin_counter_gui(rctx->screen); break; case R600_QUERY_NUM_COMPILATIONS: query->begin_result = p_atomic_read(&rctx->screen->num_compilations); @@ -236,8 +236,8 @@ static bool r600_query_sw_end(struct r600_common_context *rctx, break; } case R600_QUERY_GPU_LOAD: - query->end_result = r600_gpu_load_end(rctx->screen, - query->begin_result); + query->end_result = r600_end_counter_gui(rctx->screen, + query->begin_result); query->begin_result = 0; break; case R600_QUERY_NUM_COMPILATIONS: -- 2.30.2