summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2017-10-22 17:39:01 +0200
committerNicolai Hähnle <nicolai.haehnle@amd.com>2017-11-06 11:09:50 +0100
commit3638eff0dbf360b266f830aa896a4b7a1b37e05e (patch)
tree4bb7ffca34c2e2ae572d8350bd2f005a2b37fff4
parent9d0517c769d155073ff65772babeb668c774ca18 (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 <marek.olsak@amd.com>
-rw-r--r--src/gallium/drivers/ddebug/dd_context.c65
-rw-r--r--src/gallium/drivers/ddebug/dd_draw.c234
-rw-r--r--src/gallium/drivers/ddebug/dd_pipe.h46
-rw-r--r--src/gallium/drivers/ddebug/dd_screen.c9
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 558708df58..dd7b3e086c 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 182d6f297a..a25017114d 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 607ebbb2b9..07c4d55017 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 11d1d8c1e9..5b2be28a96 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;