diff options
author | Nicolai Hähnle <[email protected]> | 2017-10-22 17:39:01 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2017-11-09 14:01:03 +0100 |
commit | b07569ad8b7bbe6ea33c984013a2f2607cd7ddaf (patch) | |
tree | a5d01eaa12be38d6ed0b5af5b7089f28cb69f16a | |
parent | 18fd2a859de51353187f993ea2852bebe1ea5734 (diff) |
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 <[email protected]>
-rw-r--r-- | src/gallium/drivers/ddebug/dd_context.c | 65 | ||||
-rw-r--r-- | src/gallium/drivers/ddebug/dd_draw.c | 234 | ||||
-rw-r--r-- | src/gallium/drivers/ddebug/dd_pipe.h | 46 | ||||
-rw-r--r-- | src/gallium/drivers/ddebug/dd_screen.c | 9 |
4 files changed, 288 insertions, 66 deletions
diff --git a/src/gallium/drivers/ddebug/dd_context.c b/src/gallium/drivers/ddebug/dd_context.c index 558708df58d..dd7b3e086cd 100644 --- a/src/gallium/drivers/ddebug/dd_context.c +++ b/src/gallium/drivers/ddebug/dd_context.c @@ -608,66 +608,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); diff --git a/src/gallium/drivers/ddebug/dd_draw.c b/src/gallium/drivers/ddebug/dd_draw.c index 182d6f297a1..a25017114d8 100644 --- a/src/gallium/drivers/ddebug/dd_draw.c +++ b/src/gallium/drivers/ddebug/dd_draw.c @@ -468,6 +468,56 @@ dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *inf } 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) { fprintf(f, "%s:\n", __func__+8); @@ -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); } diff --git a/src/gallium/drivers/ddebug/dd_pipe.h b/src/gallium/drivers/ddebug/dd_pipe.h index 607ebbb2b96..07c4d55017f 100644 --- a/src/gallium/drivers/ddebug/dd_pipe.h +++ b/src/gallium/drivers/ddebug/dd_pipe.h @@ -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; }; diff --git a/src/gallium/drivers/ddebug/dd_screen.c b/src/gallium/drivers/ddebug/dd_screen.c index 11d1d8c1e9c..5b2be28a969 100644 --- a/src/gallium/drivers/ddebug/dd_screen.c +++ b/src/gallium/drivers/ddebug/dd_screen.c @@ -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; |