ddebug: optionally handle transfer commands like draws

Transfer commands can have associated GPU operations.

Enabled by passing GALLIUM_DDEBUG=transfers.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
Nicolai Hähnle
2017-10-22 17:39:01 +02:00
parent 18fd2a859d
commit b07569ad8b
4 changed files with 288 additions and 66 deletions
-65
View File
@@ -607,66 +607,6 @@ dd_context_destroy(struct pipe_context *_pipe)
}
/********************************************************************
* transfer
*/
static void *
dd_context_transfer_map(struct pipe_context *_pipe,
struct pipe_resource *resource, unsigned level,
unsigned usage, const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
return pipe->transfer_map(pipe, resource, level, usage, box, transfer);
}
static void
dd_context_transfer_flush_region(struct pipe_context *_pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->transfer_flush_region(pipe, transfer, box);
}
static void
dd_context_transfer_unmap(struct pipe_context *_pipe,
struct pipe_transfer *transfer)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->transfer_unmap(pipe, transfer);
}
static void
dd_context_buffer_subdata(struct pipe_context *_pipe,
struct pipe_resource *resource,
unsigned usage, unsigned offset,
unsigned size, const void *data)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->buffer_subdata(pipe, resource, usage, offset, size, data);
}
static void
dd_context_texture_subdata(struct pipe_context *_pipe,
struct pipe_resource *resource,
unsigned level, unsigned usage,
const struct pipe_box *box,
const void *data, unsigned stride,
unsigned layer_stride)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->texture_subdata(pipe, resource, level, usage, box, data,
stride, layer_stride);
}
/********************************************************************
* miscellaneous
*/
@@ -891,11 +831,6 @@ dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe)
CTX_INIT(sampler_view_destroy);
CTX_INIT(create_surface);
CTX_INIT(surface_destroy);
CTX_INIT(transfer_map);
CTX_INIT(transfer_flush_region);
CTX_INIT(transfer_unmap);
CTX_INIT(buffer_subdata);
CTX_INIT(texture_subdata);
CTX_INIT(texture_barrier);
CTX_INIT(memory_barrier);
CTX_INIT(resource_commit);
+234
View File
@@ -467,6 +467,56 @@ dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *inf
fprintf(f, "\n");
}
static void
dd_dump_transfer_map(struct call_transfer_map *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M_ADDR(transfer, info, transfer);
DUMP_M(ptr, info, transfer_ptr);
DUMP_M(ptr, info, ptr);
}
static void
dd_dump_transfer_flush_region(struct call_transfer_flush_region *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M_ADDR(transfer, info, transfer);
DUMP_M(ptr, info, transfer_ptr);
DUMP_M_ADDR(box, info, box);
}
static void
dd_dump_transfer_unmap(struct call_transfer_unmap *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M_ADDR(transfer, info, transfer);
DUMP_M(ptr, info, transfer_ptr);
}
static void
dd_dump_buffer_subdata(struct call_buffer_subdata *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M(resource, info, resource);
DUMP_M(transfer_usage, info, usage);
DUMP_M(uint, info, offset);
DUMP_M(uint, info, size);
DUMP_M(ptr, info, data);
}
static void
dd_dump_texture_subdata(struct call_texture_subdata *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M(resource, info, resource);
DUMP_M(uint, info, level);
DUMP_M(transfer_usage, info, usage);
DUMP_M_ADDR(box, info, box);
DUMP_M(ptr, info, data);
DUMP_M(uint, info, stride);
DUMP_M(uint, info, layer_stride);
}
static void
dd_dump_clear_texture(struct dd_draw_state *dstate, FILE *f)
{
@@ -540,6 +590,21 @@ dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
case CALL_GET_QUERY_RESULT_RESOURCE:
dd_dump_get_query_result_resource(&call->info.get_query_result_resource, f);
break;
case CALL_TRANSFER_MAP:
dd_dump_transfer_map(&call->info.transfer_map, f);
break;
case CALL_TRANSFER_FLUSH_REGION:
dd_dump_transfer_flush_region(&call->info.transfer_flush_region, f);
break;
case CALL_TRANSFER_UNMAP:
dd_dump_transfer_unmap(&call->info.transfer_unmap, f);
break;
case CALL_BUFFER_SUBDATA:
dd_dump_buffer_subdata(&call->info.buffer_subdata, f);
break;
case CALL_TEXTURE_SUBDATA:
dd_dump_texture_subdata(&call->info.texture_subdata, f);
break;
}
}
@@ -598,6 +663,21 @@ dd_unreference_copy_of_call(struct dd_call *dst)
case CALL_GET_QUERY_RESULT_RESOURCE:
pipe_resource_reference(&dst->info.get_query_result_resource.resource, NULL);
break;
case CALL_TRANSFER_MAP:
pipe_resource_reference(&dst->info.transfer_map.transfer.resource, NULL);
break;
case CALL_TRANSFER_FLUSH_REGION:
pipe_resource_reference(&dst->info.transfer_flush_region.transfer.resource, NULL);
break;
case CALL_TRANSFER_UNMAP:
pipe_resource_reference(&dst->info.transfer_unmap.transfer.resource, NULL);
break;
case CALL_BUFFER_SUBDATA:
pipe_resource_reference(&dst->info.buffer_subdata.resource, NULL);
break;
case CALL_TEXTURE_SUBDATA:
pipe_resource_reference(&dst->info.texture_subdata.resource, NULL);
break;
}
}
@@ -1392,6 +1472,155 @@ dd_context_clear_texture(struct pipe_context *_pipe,
dd_after_draw(dctx, record);
}
/********************************************************************
* transfer
*/
static void *
dd_context_transfer_map(struct pipe_context *_pipe,
struct pipe_resource *resource, unsigned level,
unsigned usage, const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_draw_record *record =
dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
if (record) {
record->call.type = CALL_TRANSFER_MAP;
dd_before_draw(dctx, record);
}
void *ptr = pipe->transfer_map(pipe, resource, level, usage, box, transfer);
if (record) {
record->call.info.transfer_map.transfer_ptr = *transfer;
record->call.info.transfer_map.ptr = ptr;
if (*transfer) {
record->call.info.transfer_map.transfer = **transfer;
record->call.info.transfer_map.transfer.resource = NULL;
pipe_resource_reference(&record->call.info.transfer_map.transfer.resource,
(*transfer)->resource);
} else {
memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer));
}
dd_after_draw(dctx, record);
}
return ptr;
}
static void
dd_context_transfer_flush_region(struct pipe_context *_pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_draw_record *record =
dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
if (record) {
record->call.type = CALL_TRANSFER_FLUSH_REGION;
record->call.info.transfer_flush_region.transfer_ptr = transfer;
record->call.info.transfer_flush_region.box = *box;
record->call.info.transfer_flush_region.transfer = *transfer;
record->call.info.transfer_flush_region.transfer.resource = NULL;
pipe_resource_reference(
&record->call.info.transfer_flush_region.transfer.resource,
transfer->resource);
dd_before_draw(dctx, record);
}
pipe->transfer_flush_region(pipe, transfer, box);
if (record)
dd_after_draw(dctx, record);
}
static void
dd_context_transfer_unmap(struct pipe_context *_pipe,
struct pipe_transfer *transfer)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_draw_record *record =
dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
if (record) {
record->call.type = CALL_TRANSFER_UNMAP;
record->call.info.transfer_unmap.transfer_ptr = transfer;
record->call.info.transfer_unmap.transfer = *transfer;
record->call.info.transfer_unmap.transfer.resource = NULL;
pipe_resource_reference(
&record->call.info.transfer_unmap.transfer.resource,
transfer->resource);
dd_before_draw(dctx, record);
}
pipe->transfer_unmap(pipe, transfer);
if (record)
dd_after_draw(dctx, record);
}
static void
dd_context_buffer_subdata(struct pipe_context *_pipe,
struct pipe_resource *resource,
unsigned usage, unsigned offset,
unsigned size, const void *data)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_draw_record *record =
dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
if (record) {
record->call.type = CALL_BUFFER_SUBDATA;
record->call.info.buffer_subdata.resource = NULL;
pipe_resource_reference(&record->call.info.buffer_subdata.resource, resource);
record->call.info.buffer_subdata.usage = usage;
record->call.info.buffer_subdata.offset = offset;
record->call.info.buffer_subdata.size = size;
record->call.info.buffer_subdata.data = data;
dd_before_draw(dctx, record);
}
pipe->buffer_subdata(pipe, resource, usage, offset, size, data);
if (record)
dd_after_draw(dctx, record);
}
static void
dd_context_texture_subdata(struct pipe_context *_pipe,
struct pipe_resource *resource,
unsigned level, unsigned usage,
const struct pipe_box *box,
const void *data, unsigned stride,
unsigned layer_stride)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_draw_record *record =
dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
if (record) {
record->call.type = CALL_TEXTURE_SUBDATA;
record->call.info.texture_subdata.resource = NULL;
pipe_resource_reference(&record->call.info.texture_subdata.resource, resource);
record->call.info.texture_subdata.level = level;
record->call.info.texture_subdata.usage = usage;
record->call.info.texture_subdata.box = *box;
record->call.info.texture_subdata.data = data;
record->call.info.texture_subdata.stride = stride;
record->call.info.texture_subdata.layer_stride = layer_stride;
dd_before_draw(dctx, record);
}
pipe->texture_subdata(pipe, resource, level, usage, box, data,
stride, layer_stride);
if (record)
dd_after_draw(dctx, record);
}
void
dd_init_draw_functions(struct dd_context *dctx)
{
@@ -1408,4 +1637,9 @@ dd_init_draw_functions(struct dd_context *dctx)
CTX_INIT(flush_resource);
CTX_INIT(generate_mipmap);
CTX_INIT(get_query_result_resource);
CTX_INIT(transfer_map);
CTX_INIT(transfer_flush_region);
CTX_INIT(transfer_unmap);
CTX_INIT(buffer_subdata);
CTX_INIT(texture_subdata);
}
+46
View File
@@ -52,6 +52,7 @@ struct dd_screen
unsigned timeout_ms;
enum dd_dump_mode dump_mode;
bool flush_always;
bool transfers;
bool verbose;
unsigned skip_count;
unsigned apitrace_dump_call;
@@ -71,6 +72,11 @@ enum call_type
CALL_CLEAR_DEPTH_STENCIL,
CALL_GENERATE_MIPMAP,
CALL_GET_QUERY_RESULT_RESOURCE,
CALL_TRANSFER_MAP,
CALL_TRANSFER_FLUSH_REGION,
CALL_TRANSFER_UNMAP,
CALL_BUFFER_SUBDATA,
CALL_TEXTURE_SUBDATA,
};
struct call_resource_copy_region
@@ -124,6 +130,41 @@ struct call_get_query_result_resource {
unsigned offset;
};
struct call_transfer_map {
struct pipe_transfer *transfer_ptr;
struct pipe_transfer transfer;
void *ptr;
};
struct call_transfer_flush_region {
struct pipe_transfer *transfer_ptr;
struct pipe_transfer transfer;
struct pipe_box box;
};
struct call_transfer_unmap {
struct pipe_transfer *transfer_ptr;
struct pipe_transfer transfer;
};
struct call_buffer_subdata {
struct pipe_resource *resource;
unsigned usage;
unsigned offset;
unsigned size;
const void *data;
};
struct call_texture_subdata {
struct pipe_resource *resource;
unsigned level;
unsigned usage;
struct pipe_box box;
const void *data;
unsigned stride;
unsigned layer_stride;
};
struct dd_call
{
enum call_type type;
@@ -138,6 +179,11 @@ struct dd_call
struct call_clear_buffer clear_buffer;
struct call_generate_mipmap generate_mipmap;
struct call_get_query_result_resource get_query_result_resource;
struct call_transfer_map transfer_map;
struct call_transfer_flush_region transfer_flush_region;
struct call_transfer_unmap transfer_unmap;
struct call_buffer_subdata buffer_subdata;
struct call_texture_subdata texture_subdata;
} info;
};
+8 -1
View File
@@ -428,6 +428,7 @@ ddebug_screen_create(struct pipe_screen *screen)
const char *option;
bool flush = false;
bool verbose = false;
bool transfers = false;
unsigned timeout = 1000;
unsigned apitrace_dump_call = 0;
enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS;
@@ -441,7 +442,7 @@ ddebug_screen_create(struct pipe_screen *screen)
puts("");
puts("Usage:");
puts("");
puts(" GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [verbose]\"");
puts(" GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\"");
puts(" GALLIUM_DDEBUG_SKIP=[count]");
puts("");
puts("Dump context and driver information of draw calls into");
@@ -455,6 +456,9 @@ ddebug_screen_create(struct pipe_screen *screen)
puts("always");
puts(" Dump information about all draw calls.");
puts("");
puts("transfers");
puts(" Also dump and do hang detection on transfers.");
puts("");
puts("apitrace <call#>");
puts(" Dump information about the draw call corresponding to the given");
puts(" apitrace call number and exit.");
@@ -485,6 +489,8 @@ ddebug_screen_create(struct pipe_screen *screen)
mode = DD_DUMP_ALL_CALLS;
} else if (match_word(&option, "flush")) {
flush = true;
} else if (match_word(&option, "transfers")) {
transfers = true;
} else if (match_word(&option, "verbose")) {
verbose = true;
} else if (match_word(&option, "apitrace")) {
@@ -556,6 +562,7 @@ ddebug_screen_create(struct pipe_screen *screen)
dscreen->timeout_ms = timeout;
dscreen->dump_mode = mode;
dscreen->flush_always = flush;
dscreen->transfers = transfers;
dscreen->verbose = verbose;
dscreen->apitrace_dump_call = apitrace_dump_call;