freedreno: Remove fd_log()

Now that it is superceeded by u_trace

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7818>
This commit is contained in:
Rob Clark 2020-11-30 13:05:49 -08:00 committed by Marge Bot
parent d5bc39c9d0
commit 03e7c93b82
16 changed files with 3 additions and 641 deletions

View file

@ -30,7 +30,6 @@
#include "freedreno_blitter.h"
#include "freedreno_fence.h"
#include "freedreno_log.h"
#include "freedreno_resource.h"
#include "freedreno_tracepoints.h"
@ -820,8 +819,6 @@ handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
fd_batch_set_stage(batch, FD_STAGE_BLIT);
fd_log_stream(batch, stream, util_dump_blit_info(stream, info));
emit_setup(batch);
trace_start_blit(&batch->trace, info->src.resource->target, info->dst.resource->target);
@ -830,16 +827,12 @@ handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
(info->dst.resource->target == PIPE_BUFFER)) {
assert(fd_resource(info->src.resource)->layout.tile_mode == TILE6_LINEAR);
assert(fd_resource(info->dst.resource)->layout.tile_mode == TILE6_LINEAR);
fd_log(batch, "START BLIT (BUFFER)");
emit_blit_buffer(ctx, batch->draw, info);
fd_log(batch, "END BLIT (BUFFER)");
} else {
/* I don't *think* we need to handle blits between buffer <-> !buffer */
debug_assert(info->src.resource->target != PIPE_BUFFER);
debug_assert(info->dst.resource->target != PIPE_BUFFER);
fd_log(batch, "START BLIT (TEXTURE)");
emit_blit_texture(ctx, batch->draw, info);
fd_log(batch, "END BLIT (TEXTURE)");
}
trace_end_blit(&batch->trace);

View file

@ -28,7 +28,6 @@
#include "util/u_dump.h"
#include "u_tracepoints.h"
#include "freedreno_log.h"
#include "freedreno_resource.h"
#include "freedreno_tracepoints.h"
@ -197,9 +196,6 @@ fd6_launch_grid(struct fd_context *ctx, const struct pipe_grid_info *info)
trace_grid_info(&ctx->batch->trace, info);
trace_start_compute(&ctx->batch->trace);
fd_log(ctx->batch, "COMPUTE: START");
fd_log_stream(ctx->batch, stream, util_dump_grid_info(stream, info));
if (info->indirect) {
struct fd_resource *rsc = fd_resource(info->indirect);
@ -219,12 +215,9 @@ fd6_launch_grid(struct fd_context *ctx, const struct pipe_grid_info *info)
trace_end_compute(&ctx->batch->trace);
fd_log(ctx->batch, "COMPUTE: END");
OUT_WFI5(ring);
fd_log(ctx->batch, "..");
fd6_cache_flush(ctx->batch, ring);
fd_log(ctx->batch, "..");
}
void

View file

@ -32,7 +32,6 @@
#include "util/format/u_format.h"
#include "util/u_viewport.h"
#include "freedreno_log.h"
#include "freedreno_resource.h"
#include "freedreno_state.h"
#include "freedreno_tracepoints.h"
@ -1176,7 +1175,6 @@ fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring)
//struct fd_context *ctx = batch->ctx;
if (!batch->nondraw) {
fd_log(batch, "START RESTORE");
trace_start_state_restore(&batch->trace);
}
@ -1296,7 +1294,6 @@ fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring)
if (!batch->nondraw) {
trace_end_state_restore(&batch->trace);
fd_log(batch, "END RESTORE");
}
}

View file

@ -34,7 +34,6 @@
#include "util/format/u_format.h"
#include "freedreno_draw.h"
#include "freedreno_log.h"
#include "freedreno_state.h"
#include "freedreno_resource.h"
#include "freedreno_tracepoints.h"
@ -577,11 +576,9 @@ emit_binning_pass(struct fd_batch *batch)
A6XX_SP_TP_WINDOW_OFFSET_Y(0));
/* emit IB to binning drawcmds: */
fd_log(batch, "GMEM: START BINNING IB");
trace_start_binning_ib(&batch->trace);
fd6_emit_ib(ring, batch->draw);
trace_end_binning_ib(&batch->trace);
fd_log(batch, "GMEM: END BINNING IB");
fd_reset_wfi(batch);
@ -601,11 +598,9 @@ emit_binning_pass(struct fd_batch *batch)
OUT_PKT7(ring, CP_WAIT_FOR_ME, 0);
fd_log(batch, "START VSC OVERFLOW TEST");
trace_start_vsc_overflow_test(&batch->trace);
emit_vsc_overflow_test(batch);
trace_end_vsc_overflow_test(&batch->trace);
fd_log(batch, "END VSC OVERFLOW TEST");
OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
OUT_RING(ring, 0x0);
@ -662,11 +657,9 @@ fd6_emit_tile_init(struct fd_batch *batch)
fd6_emit_lrz_flush(ring);
if (batch->prologue) {
fd_log(batch, "START PROLOGUE");
trace_start_prologue(&batch->trace);
fd6_emit_ib(ring, batch->prologue);
trace_end_prologue(&batch->trace);
fd_log(batch, "END PROLOGUE");
}
fd6_cache_inv(batch, ring);
@ -1125,7 +1118,6 @@ fd6_emit_tile_renderprep(struct fd_batch *batch, const struct fd_tile *tile)
if (!batch->tile_setup)
return;
fd_log(batch, "TILE: START CLEAR/RESTORE");
trace_start_clear_restore(&batch->trace, batch->fast_cleared);
if (batch->fast_cleared || !use_hw_binning(batch)) {
fd6_emit_ib(batch->gmem, batch->tile_setup);
@ -1133,7 +1125,6 @@ fd6_emit_tile_renderprep(struct fd_batch *batch, const struct fd_tile *tile)
emit_conditional_ib(batch, tile, batch->tile_setup);
}
trace_end_clear_restore(&batch->trace);
fd_log(batch, "TILE: END CLEAR/RESTORE");
}
static void
@ -1253,7 +1244,6 @@ fd6_emit_tile_gmem2mem(struct fd_batch *batch, const struct fd_tile *tile)
OUT_RING(ring, A6XX_CP_SET_MARKER_0_MODE(RM6_RESOLVE));
emit_marker6(ring, 7);
fd_log(batch, "TILE: START RESOLVE");
trace_start_resolve(&batch->trace);
if (batch->fast_cleared || !use_hw_binning(batch)) {
fd6_emit_ib(batch->gmem, batch->tile_fini);
@ -1261,7 +1251,6 @@ fd6_emit_tile_gmem2mem(struct fd_batch *batch, const struct fd_tile *tile)
emit_conditional_ib(batch, tile, batch->tile_fini);
}
trace_end_resolve(&batch->trace);
fd_log(batch, "TILE: END RESOLVE");
}
static void
@ -1373,13 +1362,11 @@ fd6_emit_sysmem_prep(struct fd_batch *batch)
if (batch->prologue) {
if (!batch->nondraw) {
fd_log(batch, "START PROLOGUE");
trace_start_prologue(&batch->trace);
}
fd6_emit_ib(ring, batch->prologue);
if (!batch->nondraw) {
trace_end_prologue(&batch->trace);
fd_log(batch, "END PROLOGUE");
}
}

View file

@ -201,7 +201,7 @@ timestamp_pause(struct fd_acc_query *aq, struct fd_batch *batch)
/* We captured a timestamp in timestamp_resume(), nothing to do here. */
}
/* timestamp logging for fd_log(): */
/* timestamp logging for u_trace: */
static void
record_timestamp(struct fd_ringbuffer *ring, struct fd_bo *bo, unsigned offset)
{

View file

@ -110,8 +110,6 @@ batch_init(struct fd_batch *batch)
util_dynarray_init(&batch->samples, NULL);
list_inithead(&batch->log_chunks);
u_trace_init(&batch->trace, &ctx->trace_context);
batch->last_timestamp_cmd = NULL;
}
@ -224,8 +222,6 @@ batch_fini(struct fd_batch *batch)
}
util_dynarray_fini(&batch->samples);
assert(list_is_empty(&batch->log_chunks));
u_trace_fini(&batch->trace);
}

View file

@ -246,8 +246,6 @@ struct fd_batch {
uint32_t tessparam_size;
struct fd_ringbuffer *tess_addrs_constobj;
struct list_head log_chunks; /* list of unflushed log chunks in fifo order */
};
struct fd_batch * fd_batch_create(struct fd_context *ctx, bool nondraw);

View file

@ -28,7 +28,6 @@
#include "freedreno_blitter.h"
#include "freedreno_draw.h"
#include "freedreno_fence.h"
#include "freedreno_log.h"
#include "freedreno_program.h"
#include "freedreno_resource.h"
#include "freedreno_texture.h"
@ -39,12 +38,6 @@
#include "freedreno_util.h"
#include "util/u_upload_mgr.h"
#if DETECT_OS_ANDROID
#include "util/u_process.h"
#include <sys/stat.h>
#include <sys/types.h>
#endif
static void
fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
unsigned flags)
@ -113,9 +106,6 @@ out:
fd_batch_reference(&batch, NULL);
if (flags & PIPE_FLUSH_END_OF_FRAME)
fd_log_eof(ctx);
u_trace_context_process(&ctx->trace_context,
!!(flags & PIPE_FLUSH_END_OF_FRAME));
}
@ -302,9 +292,6 @@ fd_context_destroy(struct pipe_context *pctx)
list_del(&ctx->node);
fd_screen_unlock(ctx->screen);
fd_log_process(ctx, true);
assert(list_is_empty(&ctx->log_chunks));
fd_fence_ref(&ctx->last_fence, NULL);
if (ctx->in_fence_fd != -1)
@ -596,7 +583,6 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
list_inithead(&ctx->hw_active_queries);
list_inithead(&ctx->acc_active_queries);
list_inithead(&ctx->log_chunks);
fd_screen_lock(ctx->screen);
ctx->seqno = ++screen->ctx_seqno;
@ -605,29 +591,9 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
ctx->current_scissor = &ctx->disabled_scissor;
ctx->log_out = stdout;
u_trace_context_init(&ctx->trace_context, pctx,
fd_trace_record_ts, fd_trace_read_ts);
if ((fd_mesa_debug & FD_DBG_LOG) &&
!(ctx->record_timestamp && ctx->ts_to_ns)) {
printf("logging not supported!\n");
fd_mesa_debug &= ~FD_DBG_LOG;
}
#if DETECT_OS_ANDROID
if (fd_mesa_debug & FD_DBG_LOG) {
static unsigned idx = 0;
char *p;
asprintf(&p, "/data/fdlog/%s-%d.log", util_get_process_name(), idx++);
FILE *f = fopen(p, "w");
if (f)
ctx->log_out = f;
}
#endif
return pctx;
fail:

View file

@ -441,10 +441,6 @@ struct fd_context {
void (*record_timestamp)(struct fd_ringbuffer *ring, struct fd_bo *bo, unsigned offset);
uint64_t (*ts_to_ns)(uint64_t ts);
struct list_head log_chunks; /* list of flushed log chunks in fifo order */
unsigned frame_nr; /* frame counter (for fd_log) */
FILE *log_out;
/*
* Common pre-cooked VBO state (used for a3xx and later):
*/

View file

@ -37,7 +37,6 @@
#include "freedreno_gmem.h"
#include "freedreno_context.h"
#include "freedreno_fence.h"
#include "freedreno_log.h"
#include "freedreno_resource.h"
#include "freedreno_query_hw.h"
#include "freedreno_tracepoints.h"
@ -589,8 +588,6 @@ render_tiles(struct fd_batch *batch, struct fd_gmem_stateobj *gmem)
for (i = 0; i < (gmem->nbins_x * gmem->nbins_y); i++) {
struct fd_tile *tile = &gmem->tile[i];
fd_log(batch, "bin_h=%d, yoff=%d, bin_w=%d, xoff=%d",
tile->bin_h, tile->yoff, tile->bin_w, tile->xoff);
trace_start_tile(&batch->trace, tile->bin_h,
tile->yoff, tile->bin_w, tile->xoff);
@ -606,7 +603,6 @@ render_tiles(struct fd_batch *batch, struct fd_gmem_stateobj *gmem)
ctx->query_prepare_tile(batch, i, batch->gmem);
/* emit IB to drawcmds: */
fd_log(batch, "TILE[%d]: START DRAW IB", i);
trace_start_draw_ib(&batch->trace);
if (ctx->emit_tile) {
ctx->emit_tile(batch, tile);
@ -614,7 +610,6 @@ render_tiles(struct fd_batch *batch, struct fd_gmem_stateobj *gmem)
ctx->screen->emit_ib(batch->gmem, batch->draw);
}
trace_end_draw_ib(&batch->trace);
fd_log(batch, "TILE[%d]: END DRAW IB", i);
fd_reset_wfi(batch);
/* emit gmem2mem to transfer tile back to system memory: */
@ -638,7 +633,6 @@ render_sysmem(struct fd_batch *batch)
ctx->query_prepare_tile(batch, 0, batch->gmem);
if (!batch->nondraw) {
fd_log(batch, "SYSMEM: START DRAW IB");
trace_start_draw_ib(&batch->trace);
}
/* emit IB to drawcmds: */
@ -646,7 +640,6 @@ render_sysmem(struct fd_batch *batch)
if (!batch->nondraw) {
trace_end_draw_ib(&batch->trace);
fd_log(batch, "SYSMEM: END DRAW IB");
}
fd_reset_wfi(batch);
@ -669,7 +662,6 @@ flush_ring(struct fd_batch *batch)
&timestamp);
fd_fence_populate(batch->fence, timestamp, out_fence_fd);
fd_log_flush(batch);
}
void
@ -689,9 +681,6 @@ fd_gmem_render_tiles(struct fd_batch *batch)
if (batch->cleared || batch->gmem_reason ||
((batch->num_draws > 5) && !batch->blit) ||
(pfb->samples > 1)) {
fd_log(batch, "GMEM: cleared=%x, gmem_reason=%x, num_draws=%u, samples=%u",
batch->cleared, batch->gmem_reason, batch->num_draws,
pfb->samples);
} else if (!(fd_mesa_debug & FD_DBG_NOBYPASS)) {
sysmem = true;
}
@ -726,24 +715,11 @@ fd_gmem_render_tiles(struct fd_batch *batch)
ctx->stats.batch_total++;
if (unlikely(fd_mesa_debug & FD_DBG_LOG) && !batch->nondraw) {
fd_log_stream(batch, stream, util_dump_framebuffer_state(stream, pfb));
for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
fd_log_stream(batch, stream, util_dump_surface(stream, pfb->cbufs[i]));
}
fd_log_stream(batch, stream, util_dump_surface(stream, pfb->zsbuf));
}
if (batch->nondraw) {
DBG("%p: rendering non-draw", batch);
render_sysmem(batch);
ctx->stats.batch_nondraw++;
} else if (sysmem) {
fd_log(batch, "%p: rendering sysmem %ux%u (%s/%s), num_draws=%u",
batch, pfb->width, pfb->height,
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)),
batch->num_draws);
trace_render_sysmem(&batch->trace);
if (ctx->query_prepare)
ctx->query_prepare(batch, 1);
@ -752,10 +728,6 @@ fd_gmem_render_tiles(struct fd_batch *batch)
} else {
struct fd_gmem_stateobj *gmem = lookup_gmem_state(batch, false, false);
batch->gmem_state = gmem;
fd_log(batch, "%p: rendering %dx%d tiles %ux%u (%s/%s)",
batch, pfb->width, pfb->height, gmem->nbins_x, gmem->nbins_y,
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
trace_render_gmem(&batch->trace, gmem->nbins_x, gmem->nbins_y,
gmem->bin_w, gmem->bin_h);
if (ctx->query_prepare)

View file

@ -1,262 +0,0 @@
/*
* Copyright © 2020 Google, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <inttypes.h>
#include <stdarg.h>
#include "freedreno_log.h"
#include "freedreno_batch.h"
#include "freedreno_context.h"
#include "util/u_fifo.h"
/* A simple(ish) logging mechanism with timestamps recorded at the
* corresponding point in the cmdstream. The overall design is based
* on fd_log_chunk's, which buffer up up to 'msgs_per_chunk' log msgs
* and track an associated bo containing timestamps written from the
* GPU.
*
* The fd_batch tracks a list of fd_log_chunk's. When fd_log() is
* called, msgs are pushed into the last (most recent) chunk until
* it is full, at which point a new chunk is created. And cmds are
* inserted into the cmdstream to record the GPU timestamp that
* corresponds with the log msg.
*
* When the batch is flushed, the list of log chunks is transferred
* to the end of fd_context's list of chunks, and we attempt to pop
* chunks from the from of the list if their timestamp bo is idle (ie.
* the GPU has finished the batch that was writing the timestamps).
*
* NOTE: this is only appropriate for IB1 (ie. "gmem" level) cmdstream,
* the IB2 (draw/binning) cmdstream can be executed multiple times,
* which this mechanism is not designed to support. Other existing
* GL level queries (time-elapsed, amd-perfcntrs) are more appropriate
* for profiling at that level.
*/
enum {
bo_size = 0x1000,
msgs_per_chunk = bo_size / sizeof(uint64_t),
};
struct fd_log_chunk {
struct list_head node;
unsigned num_msgs;
struct util_fifo *msg_fifo;
/* list of recorded 64b timestamps */
struct fd_bo *timestamps_bo;
bool last; /* this chunk is last in submit */
bool eof; /* this chunk is last in frame */
uint32_t *ring_cur;
};
static struct fd_log_chunk *
get_chunk(struct fd_batch *batch)
{
struct fd_log_chunk *chunk;
/* do we currently have a non-full chunk to append msgs to? */
if (!list_is_empty(&batch->log_chunks)) {
chunk = list_last_entry(&batch->log_chunks,
struct fd_log_chunk, node);
if (chunk->num_msgs < msgs_per_chunk)
return chunk;
/* we need to expand to add another chunk to the batch, so
* the current one is no longer the last one of the batch:
*/
chunk->last = false;
}
/* .. if not, then create a new one: */
chunk = calloc(1, sizeof(*chunk));
chunk->msg_fifo = u_fifo_create(msgs_per_chunk);
chunk->timestamps_bo = fd_bo_new(batch->ctx->screen->dev, bo_size,
DRM_FREEDRENO_GEM_TYPE_KMEM, "timestamps");
chunk->last = true;
list_addtail(&chunk->node, &batch->log_chunks);
return chunk;
}
static void
free_chunk(struct fd_log_chunk *chunk)
{
assert(chunk->msg_fifo->num == 0);
u_fifo_destroy(chunk->msg_fifo);
fd_bo_del(chunk->timestamps_bo);
list_del(&chunk->node);
free(chunk);
}
/* state to accumulate time across N chunks associated with a single batch: */
struct times {
uint64_t last_time_ns;
uint64_t first_time_ns;
};
static void
process_chunk(struct fd_context *ctx, struct fd_log_chunk *chunk, struct times *t)
{
/* For first chunk of batch, accumulated times will be zerod: */
if (!t->last_time_ns) {
fprintf(ctx->log_out,
"+----- TS -----+ +----- NS -----+ +-- Δ --+ +----- MSG -----\n");
}
uint64_t *timestamps = fd_bo_map(chunk->timestamps_bo);
unsigned n = 0;
char *msg;
while (u_fifo_pop(chunk->msg_fifo, (void **)&msg)) {
uint64_t ts = timestamps[n++];
uint64_t ns = ctx->ts_to_ns(ts);
int32_t delta;
if (!t->first_time_ns)
t->first_time_ns = ns;
if (ns) {
delta = t->last_time_ns ? ns - t->last_time_ns : 0;
t->last_time_ns = ns;
} else {
/* we skipped recording the timestamp, so it should be
* the same as last msg:
*/
ns = t->last_time_ns;
delta = 0;
}
fprintf(ctx->log_out, "%016"PRIu64" %016"PRIu64" %+9d: %s\n",
ts, ns, delta, msg);
free(msg);
}
if (chunk->last) {
fprintf(ctx->log_out, "ELAPSED: %"PRIu64" ns\n",
t->last_time_ns - t->first_time_ns);
memset(t, 0, sizeof(*t));
}
if (chunk->eof)
fprintf(ctx->log_out, "END OF FRAME %u\n", ctx->frame_nr++);
}
void
fd_log_process(struct fd_context *ctx, bool wait)
{
struct times times = {0};
while (!list_is_empty(&ctx->log_chunks)) {
struct fd_log_chunk *chunk = list_first_entry(&ctx->log_chunks,
struct fd_log_chunk, node);
unsigned flags = DRM_FREEDRENO_PREP_READ;
if (!wait)
flags |= DRM_FREEDRENO_PREP_NOSYNC;
int ret = fd_bo_cpu_prep(chunk->timestamps_bo, ctx->pipe, flags);
if (ret)
break;
process_chunk(ctx, chunk, &times);
free_chunk(chunk);
}
/* We expect that the last processed chunk was the last in it's
* batch, which should reset the times:
*/
if (times.last_time_ns) {
fprintf(ctx->log_out, "WARNING: last processed chunk not last in batch?");
}
fflush(ctx->log_out);
}
void
fd_log_flush(struct fd_batch *batch)
{
/* transfer batch's log chunks to context: */
list_splicetail(&batch->log_chunks, &batch->ctx->log_chunks);
list_inithead(&batch->log_chunks);
}
void
_fd_log(struct fd_batch *batch, const char *fmt, ...)
{
struct fd_context *ctx = batch->ctx;
struct fd_ringbuffer *ring = batch->nondraw ? batch->draw : batch->gmem;
struct fd_log_chunk *chunk = get_chunk(batch);
char *msg;
va_list ap;
va_start(ap, fmt);
if (vasprintf(&msg, fmt, ap) < 0) {
va_end(ap);
return;
}
va_end(ap);
u_fifo_add(chunk->msg_fifo, msg);
assert(ctx->record_timestamp);
/* If nothing else has been emitted to the ring since the last log msg,
* skip emitting another timestamp.
*/
if (ring->cur == chunk->ring_cur) {
uint64_t *ts = fd_bo_map(chunk->timestamps_bo);
/* zero signifies an invalid timestamp to process_chunk(), so it
* will use the last valid timestamp for this msg instead.
*/
ts[chunk->num_msgs] = 0;
} else {
ctx->record_timestamp(ring, chunk->timestamps_bo,
chunk->num_msgs * sizeof(uint64_t));
}
chunk->num_msgs++;
chunk->ring_cur = ring->cur;
}
void fd_log_eof(struct fd_context *ctx)
{
if (!(fd_mesa_debug & FD_DBG_LOG))
return;
if (list_is_empty(&ctx->log_chunks)) {
fprintf(ctx->log_out, "WARNING: no log chunks!\n");
return;
}
struct fd_log_chunk *last_chunk = list_last_entry(&ctx->log_chunks,
struct fd_log_chunk, node);
last_chunk->eof = true;
/* and process any chunks that are now idle/ready: */
fd_log_process(ctx, false);
}

View file

@ -1,65 +0,0 @@
/*
* Copyright © 2020 Google, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef FREEDRENO_LOG_H_
#define FREEDRENO_LOG_H_
#include "freedreno_util.h"
struct fd_batch;
struct fd_context;
void fd_log_process(struct fd_context *ctx, bool wait);
void fd_log_flush(struct fd_batch *batch);
void _fd_log(struct fd_batch *batch, const char *fmt, ...)
_util_printf_format(2, 3);
/* macro wrapper so that arguments are not evaluated when logging is not
* enabled:
*/
#define fd_log(__batch, __fmt, ...) \
do { \
if (unlikely(fd_mesa_debug & FD_DBG_LOG)) { \
_fd_log(__batch, __fmt, ##__VA_ARGS__); \
} else { \
DBG(__fmt, ##__VA_ARGS__); \
} \
} while (0)
/* A variant of fd_log() which provides a FILE* stream to write the
* log msg into, mostly to make u_dump_state stuff useful
*/
#define fd_log_stream(__batch, __stream, __exp) \
do { \
if (unlikely(fd_mesa_debug & FD_DBG_LOG)) { \
char buf[1024]; \
FILE *__stream = fmemopen(buf, sizeof(buf), "w"); \
__exp; \
fclose(__stream); \
_fd_log(__batch, "%s", buf); \
} \
} while (0)
void fd_log_eof(struct fd_context *ctx);
#endif /* FREEDRENO_LOG_H_ */

View file

@ -72,7 +72,7 @@ static const struct debug_named_value debug_options[] = {
{"noscis", FD_DBG_NOSCIS, "Disable scissor optimization"},
{"direct", FD_DBG_DIRECT, "Force inline (SS_DIRECT) state loads"},
{"nobypass", FD_DBG_NOBYPASS, "Disable GMEM bypass"},
{"log", FD_DBG_LOG, "Enable GPU timestamp based logging (a6xx+)"},
/* BIT(7) */
{"nobin", FD_DBG_NOBIN, "Disable hw binning"},
{"nogmem", FD_DBG_NOGMEM, "Disable GMEM rendering (bypass only)"},
/* BIT(10) */

View file

@ -68,7 +68,7 @@ enum fd_debug_flag {
FD_DBG_NOSCIS = BITFIELD_BIT(4),
FD_DBG_DIRECT = BITFIELD_BIT(5),
FD_DBG_NOBYPASS = BITFIELD_BIT(6),
FD_DBG_LOG = BITFIELD_BIT(7),
/* BIT(7) */
FD_DBG_NOBIN = BITFIELD_BIT(8),
FD_DBG_NOGMEM = BITFIELD_BIT(9),
/* BIT(10) */

View file

@ -1,207 +0,0 @@
#!/usr/bin/env python3
import re
import sys
import gzip
import io
class GMEMPass:
def __init__(self):
self.cleared = None
self.gmem_reason = None
self.num_draws = None
self.samples = None
self.width = None
self.height = None
self.nbinx = None
self.nbiny = None
self.formats = [] # format per MRT + zsbuf
self.lrz_clear_time = 0
self.binning_time = 0
self.restore_clear_time = 0
self.draw_time = 0
self.resolve_time = 0
self.elapsed_time = 0
def dump_gmem_passes(gmem_passes, blit_time, sysmem_time, total_time):
i = 0
lrz_clear_time = 0
binning_time = 0
restore_clear_time = 0
draw_time = 0
resolve_time = 0
elapsed_time = 0
for gmem in gmem_passes:
print(" GMEM[{}]: {}x{} ({}x{} tiles), {} draws, lrz clear: {:,} ns, binning: {:,} ns, restore/clear: {:,} ns, draw: {:,} ns, resolve: {:,} ns, total: {:,} ns, rt/zs: {}".format(
i, gmem.width, gmem.height, gmem.nbinx, gmem.nbiny, gmem.num_draws,
gmem.lrz_clear_time, gmem.binning_time, gmem.restore_clear_time,
gmem.draw_time, gmem.resolve_time, gmem.elapsed_time,
", ".join(gmem.formats)
))
lrz_clear_time += gmem.lrz_clear_time
binning_time += gmem.binning_time
restore_clear_time += gmem.restore_clear_time
draw_time += gmem.draw_time
resolve_time += gmem.resolve_time
elapsed_time += gmem.elapsed_time
i += 1
print(" TOTAL: lrz clear: {:,} ns ({}%), binning: {:,} ns ({}%), restore/clear: {:,} ns ({}%), draw: {:,} ns ({}%), resolve: {:,} ns ({}%), blit: {:,} ns ({}%), sysmem: {:,} ns ({}%), total: {:,} ns\n".format(
lrz_clear_time, 100.0 * lrz_clear_time / total_time,
binning_time, 100.0 * binning_time / total_time,
restore_clear_time, 100.0 * restore_clear_time / total_time,
draw_time, 100.0 * draw_time / total_time,
resolve_time, 100.0 * resolve_time / total_time,
blit_time, 100.0 * blit_time / total_time,
sysmem_time, 100.0 * sysmem_time / total_time,
total_time
))
def main():
filename = sys.argv[1]
if filename.endswith(".gz"):
file = gzip.open(filename, "r")
file = io.TextIOWrapper(file)
else:
file = open(filename, "r")
lines = file.read().split('\n')
compute_match = re.compile(r"COMPUTE: START")
gmem_start_match = re.compile(r": GMEM: cleared=(\S+), gmem_reason=(\S+), num_draws=(\S+), samples=(\S+)")
gmem_match = re.compile(r": rendering (\S+)x(\S+) tiles (\S+)x(\S+)")
gmem_surf_match = re.compile(r": {format = (\S+),")
gmem_lrz_clear_match = re.compile(r"\+(\S+): END LRZ CLEAR")
gmem_binning_match = re.compile(r"\+(\S+): GMEM: END BINNING IB")
gmem_restore_clear_match = re.compile(r"\+(\S+): TILE: END CLEAR/RESTORE")
gmem_draw_match = re.compile(r"\+(\S+): TILE\[\S+\]: END DRAW IB")
gmem_resolve_match = re.compile(r"\+(\S+): TILE: END RESOLVE")
sysmem_match = re.compile(r": rendering sysmem (\S+)x(\S+)")
blit_match = re.compile(r": END BLIT")
elapsed_match = re.compile(r"ELAPSED: (\S+) ns")
eof_match = re.compile(r"END OF FRAME (\S+)")
# Times in ns:
times_blit = []
times_sysmem = []
times_gmem = []
times_compute = []
times = None
gmem_passes = [] # set of GMEM passes in frame
gmem = None # current GMEM pass
# Helper to set the appropriate times table for the current pass,
# which is expected to only happen once for a given render pass
def set_times(t):
nonlocal times
if times is not None:
print("expected times to not be set yet")
times = t
for line in lines:
match = re.search(compute_match, line)
if match is not None:
set_times(times_compute)
continue
match = re.search(gmem_start_match, line)
if match is not None:
if gmem is not None:
print("expected gmem to not be set yet")
set_times(times_gmem)
gmem = GMEMPass()
gmem.cleared = match.group(1)
gmem.gmem_reason = match.group(2)
gmem.num_draws = match.group(3)
gmem.samples = match.group(4)
if gmem is not None:
match = re.search(gmem_match, line)
if match is not None:
gmem.width = int(match.group(1))
gmem.height = int(match.group(2))
gmem.nbinx = int(match.group(3))
gmem.nbiny = int(match.group(4))
continue
match = re.search(gmem_surf_match, line)
if match is not None:
gmem.formats.append(match.group(1))
continue
match = re.search(gmem_lrz_clear_match, line)
if match is not None:
gmem.lrz_clear_time += int(match.group(1))
continue
match = re.search(gmem_binning_match, line)
if match is not None:
gmem.binning_time += int(match.group(1))
continue
match = re.search(gmem_restore_clear_match, line)
if match is not None:
gmem.restore_clear_time += int(match.group(1))
continue
match = re.search(gmem_draw_match, line)
if match is not None:
gmem.draw_time += int(match.group(1))
continue
match = re.search(gmem_resolve_match, line)
if match is not None:
gmem.resolve_time += int(match.group(1))
continue
match = re.search(sysmem_match, line)
if match is not None:
set_times(times_sysmem)
continue
match = re.search(blit_match, line)
if match is not None:
set_times(times_blit)
continue
match = re.search(eof_match, line)
if match is not None:
frame_nr = int(match.group(1))
print("FRAME[{}]: {} blits ({:,} ns), {} SYSMEM ({:,} ns), {} GMEM ({:,} ns), {} COMPUTE ({:,} ns)".format(
frame_nr,
len(times_blit), sum(times_blit),
len(times_sysmem), sum(times_sysmem),
len(times_gmem), sum(times_gmem),
len(times_compute), sum(times_compute)
))
if len(gmem_passes) > 0:
total_time = sum(times_blit) + sum(times_sysmem) + sum(times_gmem) + sum(times_compute)
dump_gmem_passes(gmem_passes, sum(times_blit), sum(times_sysmem), total_time)
times_blit = []
times_sysmem = []
times_gmem = []
times = None
gmem_passes = []
times_compute = []
gmem = None
continue
match = re.search(elapsed_match, line)
if match is not None:
time = int(match.group(1))
#print("ELAPSED: " + str(time) + " ns")
times.append(time)
times = None
if gmem is not None:
gmem.elapsed_time = time
gmem_passes.append(gmem)
gmem = None
continue
if __name__ == "__main__":
main()

View file

@ -33,8 +33,6 @@ files_libfreedreno = files(
'freedreno_fence.h',
'freedreno_gmem.c',
'freedreno_gmem.h',
'freedreno_log.c',
'freedreno_log.h',
'freedreno_program.c',
'freedreno_program.h',
'freedreno_query.c',