#include <inttypes.h>
-static FILE *
+FILE *
dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number)
{
struct pipe_screen *screen = dscreen->screen;
else
return 1;
- tgsi_scan_shader(tokens, &info);
- return info.writes_viewport_index ? PIPE_MAX_VIEWPORTS : 1;
+ if (tokens) {
+ tgsi_scan_shader(tokens, &info);
+ if (info.writes_viewport_index)
+ return PIPE_MAX_VIEWPORTS;
+ }
+
+ return 1;
}
#define COLOR_RESET "\033[0m"
fprintf(f, "%u", i);
}
+static void
+util_dump_int(FILE *f, int i)
+{
+ fprintf(f, "%d", i);
+}
+
static void
util_dump_hex(FILE *f, unsigned i)
{
color->ui[0], color->ui[1], color->ui[2], color->ui[3]);
}
-static void
-util_dump_query(FILE *f, struct dd_query *query)
-{
- if (query->type >= PIPE_QUERY_DRIVER_SPECIFIC)
- fprintf(f, "PIPE_QUERY_DRIVER_SPECIFIC + %i",
- query->type - PIPE_QUERY_DRIVER_SPECIFIC);
- else
- fprintf(f, "%s", util_dump_query_type(query->type, false));
-}
-
static void
dd_dump_render_condition(struct dd_draw_state *dstate, FILE *f)
{
if (dstate->render_cond.query) {
fprintf(f, "render condition:\n");
- DUMP_M(query, &dstate->render_cond, query);
+ DUMP_M(query_type, &dstate->render_cond, query->type);
DUMP_M(uint, &dstate->render_cond, condition);
DUMP_M(uint, &dstate->render_cond, mode);
fprintf(f, "\n");
int sh, i;
DUMP(draw_info, info);
- if (info->indexed) {
- DUMP(index_buffer, &dstate->index_buffer);
- if (dstate->index_buffer.buffer)
- DUMP_M(resource, &dstate->index_buffer, buffer);
- }
if (info->count_from_stream_output)
DUMP_M(stream_output_target, info,
count_from_stream_output);
- if (info->indirect)
- DUMP_M(resource, info, indirect);
- if (info->indirect_params)
- DUMP_M(resource, info, indirect_params);
+ if (info->indirect) {
+ DUMP_M(resource, info, indirect->buffer);
+ if (info->indirect->indirect_draw_count)
+ DUMP_M(resource, info, indirect->indirect_draw_count);
+ }
+
fprintf(f, "\n");
/* TODO: dump active queries */
/* TODO */
}
+static void
+dd_dump_get_query_result_resource(struct call_get_query_result_resource *info, FILE *f)
+{
+ fprintf(f, "%s:\n", __func__ + 8);
+ DUMP_M(query_type, info, query_type);
+ DUMP_M(uint, info, wait);
+ DUMP_M(query_value_type, info, result_type);
+ DUMP_M(int, info, index);
+ DUMP_M(resource, info, resource);
+ DUMP_M(uint, info, offset);
+}
+
static void
dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res,
FILE *f)
{
switch (call->type) {
case CALL_DRAW_VBO:
- dd_dump_draw_vbo(state, &call->info.draw_vbo, f);
+ dd_dump_draw_vbo(state, &call->info.draw_vbo.draw, f);
break;
case CALL_LAUNCH_GRID:
dd_dump_launch_grid(state, &call->info.launch_grid, f);
case CALL_GENERATE_MIPMAP:
dd_dump_generate_mipmap(state, f);
break;
+ case CALL_GET_QUERY_RESULT_RESOURCE:
+ dd_dump_get_query_result_resource(&call->info.get_query_result_resource, f);
+ break;
}
}
dd_dump_call(f, &dctx->draw_state, call);
dd_dump_driver_state(dctx, f, flags);
+
+ fprintf(f,"\n\n**************************************************"
+ "***************************\n");
+ fprintf(f, "Context Log:\n\n");
+ u_log_new_page_print(&dctx->log, f);
+
if (dump_dmesg)
dd_dump_dmesg(f);
dd_close_file_stream(f);
if (f) {
fprintf(f, "dd: %s.\n", cause);
dd_dump_driver_state(dctx, f,
- PIPE_DUMP_DEVICE_STATUS_REGISTERS |
- PIPE_DUMP_CURRENT_STATES |
- PIPE_DUMP_CURRENT_SHADERS |
- PIPE_DUMP_LAST_COMMAND_BUFFER);
+ PIPE_DUMP_DEVICE_STATUS_REGISTERS);
dd_dump_dmesg(f);
dd_close_file_stream(f);
}
{
switch (dst->type) {
case CALL_DRAW_VBO:
- pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output, NULL);
- pipe_resource_reference(&dst->info.draw_vbo.indirect, NULL);
- pipe_resource_reference(&dst->info.draw_vbo.indirect_params, NULL);
+ pipe_so_target_reference(&dst->info.draw_vbo.draw.count_from_stream_output, NULL);
+ pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL);
+ pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL);
+ if (dst->info.draw_vbo.draw.index_size &&
+ !dst->info.draw_vbo.draw.has_user_indices)
+ pipe_resource_reference(&dst->info.draw_vbo.draw.index.resource, NULL);
+ else
+ dst->info.draw_vbo.draw.index.user = NULL;
break;
case CALL_LAUNCH_GRID:
pipe_resource_reference(&dst->info.launch_grid.indirect, NULL);
case CALL_GENERATE_MIPMAP:
pipe_resource_reference(&dst->info.generate_mipmap.res, NULL);
break;
+ case CALL_GET_QUERY_RESULT_RESOURCE:
+ pipe_resource_reference(&dst->info.get_query_result_resource.resource, NULL);
+ break;
}
}
switch (src->type) {
case CALL_DRAW_VBO:
- pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output,
- src->info.draw_vbo.count_from_stream_output);
- pipe_resource_reference(&dst->info.draw_vbo.indirect,
- src->info.draw_vbo.indirect);
- pipe_resource_reference(&dst->info.draw_vbo.indirect_params,
- src->info.draw_vbo.indirect_params);
+ pipe_so_target_reference(&dst->info.draw_vbo.draw.count_from_stream_output,
+ src->info.draw_vbo.draw.count_from_stream_output);
+ pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer,
+ src->info.draw_vbo.indirect.buffer);
+ pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count,
+ src->info.draw_vbo.indirect.indirect_draw_count);
+
+ if (dst->info.draw_vbo.draw.index_size &&
+ !dst->info.draw_vbo.draw.has_user_indices)
+ pipe_resource_reference(&dst->info.draw_vbo.draw.index.resource, NULL);
+ else
+ dst->info.draw_vbo.draw.index.user = NULL;
+
+ if (src->info.draw_vbo.draw.index_size &&
+ !src->info.draw_vbo.draw.has_user_indices) {
+ pipe_resource_reference(&dst->info.draw_vbo.draw.index.resource,
+ src->info.draw_vbo.draw.index.resource);
+ }
+
dst->info.draw_vbo = src->info.draw_vbo;
+ if (!src->info.draw_vbo.draw.indirect)
+ dst->info.draw_vbo.draw.indirect = NULL;
+ else
+ dst->info.draw_vbo.draw.indirect = &dst->info.draw_vbo.indirect;
break;
case CALL_LAUNCH_GRID:
pipe_resource_reference(&dst->info.launch_grid.indirect,
src->info.generate_mipmap.res);
dst->info.generate_mipmap = src->info.generate_mipmap;
break;
+ case CALL_GET_QUERY_RESULT_RESOURCE:
+ pipe_resource_reference(&dst->info.get_query_result_resource.resource,
+ src->info.get_query_result_resource.resource);
+ dst->info.get_query_result_resource = src->info.get_query_result_resource;
+ dst->info.get_query_result_resource.query = NULL;
+ break;
}
}
/* Just clear pointers to gallium objects. Don't clear the whole structure,
* because it would kill performance with its size of 130 KB.
*/
- memset(&state->base.index_buffer, 0,
- sizeof(state->base.index_buffer));
memset(state->base.vertex_buffers, 0,
sizeof(state->base.vertex_buffers));
memset(state->base.so_targets, 0,
struct dd_draw_state *dst = &state->base;
unsigned i,j;
- util_set_index_buffer(&dst->index_buffer, NULL);
-
for (i = 0; i < ARRAY_SIZE(dst->vertex_buffers); i++)
pipe_vertex_buffer_unreference(&dst->vertex_buffers[i]);
for (i = 0; i < ARRAY_SIZE(dst->so_targets); i++)
dst->render_cond.query = NULL;
}
- util_set_index_buffer(&dst->index_buffer, &src->index_buffer);
-
for (i = 0; i < ARRAY_SIZE(src->vertex_buffers); i++) {
pipe_vertex_buffer_reference(&dst->vertex_buffers[i],
&src->vertex_buffers[i]);
if (src->shaders[i]) {
dst->shaders[i]->state.shader = src->shaders[i]->state.shader;
- dst->shaders[i]->state.shader.tokens =
- tgsi_dup_tokens(src->shaders[i]->state.shader.tokens);
+ if (src->shaders[i]->state.shader.tokens) {
+ dst->shaders[i]->state.shader.tokens =
+ tgsi_dup_tokens(src->shaders[i]->state.shader.tokens);
+ } else {
+ dst->shaders[i]->state.shader.ir.nir = NULL;
+ }
} else {
dst->shaders[i] = NULL;
}
{
struct dd_draw_record *next = (*record)->next;
+ u_log_page_destroy((*record)->log_page);
dd_unreference_copy_of_call(&(*record)->call);
dd_unreference_copy_of_draw_state(&(*record)->draw_state);
- FREE((*record)->driver_state_log);
FREE(*record);
*record = next;
}
(now - record->timestamp) / 1000);
dd_dump_call(f, &record->draw_state.base, &record->call);
- fprintf(f, "%s\n", record->driver_state_log);
+
+ fprintf(f,"\n\n**************************************************"
+ "***************************\n");
+ fprintf(f, "Context Log:\n\n");
+ u_log_page_print(record->log_page, f);
dctx->pipe->dump_debug_state(dctx->pipe, f,
PIPE_DUMP_DEVICE_STATUS_REGISTERS);
return 0;
}
-static char *
-dd_get_driver_shader_log(struct dd_context *dctx)
-{
-#if defined(PIPE_OS_LINUX)
- FILE *f;
- char *buf;
- int written_bytes;
-
- if (!dctx->max_log_buffer_size)
- dctx->max_log_buffer_size = 16 * 1024;
-
- /* Keep increasing the buffer size until there is enough space.
- *
- * open_memstream can resize automatically, but it's VERY SLOW.
- * fmemopen is much faster.
- */
- while (1) {
- buf = malloc(dctx->max_log_buffer_size);
- buf[0] = 0;
-
- f = fmemopen(buf, dctx->max_log_buffer_size, "a");
- if (!f) {
- free(buf);
- return NULL;
- }
-
- dd_dump_driver_state(dctx, f, PIPE_DUMP_CURRENT_SHADERS);
- written_bytes = ftell(f);
- fclose(f);
-
- /* Return if the backing buffer is large enough. */
- if (written_bytes < dctx->max_log_buffer_size - 1)
- break;
-
- /* Try again. */
- free(buf);
- dctx->max_log_buffer_size *= 2;
- }
-
- return buf;
-#else
- /* Return an empty string. */
- return (char*)calloc(1, 4);
-#endif
-}
-
static void
dd_pipelined_process_draw(struct dd_context *dctx, struct dd_call *call)
{
struct pipe_context *pipe = dctx->pipe;
struct dd_draw_record *record;
- char *log;
/* Make a record of the draw call. */
record = MALLOC_STRUCT(dd_draw_record);
if (!record)
return;
- /* Create the log. */
- log = dd_get_driver_shader_log(dctx);
- if (!log) {
- FREE(record);
- return;
- }
-
/* Update the fence with the GPU.
*
* radeonsi/clear_buffer waits in the command processor until shaders are
/* Initialize the record. */
record->timestamp = os_time_get();
record->sequence_no = dctx->sequence_no;
- record->driver_state_log = log;
+ record->log_page = u_log_new_page(&dctx->log);
memset(&record->call, 0, sizeof(record->call));
dd_copy_call(&record->call, call);
if (!dscreen->no_flush &&
dd_flush_and_check_hang(dctx, NULL, 0)) {
dd_write_report(dctx, call,
- PIPE_DUMP_DEVICE_STATUS_REGISTERS |
- PIPE_DUMP_CURRENT_STATES |
- PIPE_DUMP_CURRENT_SHADERS |
- PIPE_DUMP_LAST_COMMAND_BUFFER,
+ PIPE_DUMP_DEVICE_STATUS_REGISTERS,
true);
/* Terminate the process to prevent future hangs. */
dd_kill_process();
+ } else {
+ u_log_page_destroy(u_log_new_page(&dctx->log));
}
break;
case DD_DETECT_HANGS_PIPELINED:
case DD_DUMP_ALL_CALLS:
if (!dscreen->no_flush)
pipe->flush(pipe, NULL, 0);
- dd_write_report(dctx, call,
- PIPE_DUMP_CURRENT_STATES |
- PIPE_DUMP_CURRENT_SHADERS |
- PIPE_DUMP_LAST_COMMAND_BUFFER,
- false);
+ dd_write_report(dctx, call, 0, false);
break;
case DD_DUMP_APITRACE_CALL:
if (dscreen->apitrace_dump_call ==
dctx->draw_state.apitrace_call_number) {
- dd_write_report(dctx, call,
- PIPE_DUMP_CURRENT_STATES |
- PIPE_DUMP_CURRENT_SHADERS,
- false);
+ dd_write_report(dctx, call, 0, false);
/* No need to continue. */
exit(0);
+ } else {
+ u_log_page_destroy(u_log_new_page(&dctx->log));
}
break;
default:
struct dd_call call;
call.type = CALL_DRAW_VBO;
- call.info.draw_vbo = *info;
+ call.info.draw_vbo.draw = *info;
+ if (info->indirect) {
+ call.info.draw_vbo.indirect = *info->indirect;
+ call.info.draw_vbo.draw.indirect = &call.info.draw_vbo.indirect;
+ } else {
+ memset(&call.info.draw_vbo.indirect, 0, sizeof(*info->indirect));
+ }
dd_before_draw(dctx);
pipe->draw_vbo(pipe, info);
return result;
}
+static void
+dd_context_get_query_result_resource(struct pipe_context *_pipe,
+ struct pipe_query *query,
+ boolean wait,
+ enum pipe_query_value_type result_type,
+ int index,
+ struct pipe_resource *resource,
+ unsigned offset)
+{
+ struct dd_context *dctx = dd_context(_pipe);
+ struct dd_query *dquery = dd_query(query);
+ struct pipe_context *pipe = dctx->pipe;
+ struct dd_call call;
+
+ call.type = CALL_GET_QUERY_RESULT_RESOURCE;
+ call.info.get_query_result_resource.query = query;
+ call.info.get_query_result_resource.wait = wait;
+ call.info.get_query_result_resource.result_type = result_type;
+ call.info.get_query_result_resource.index = index;
+ call.info.get_query_result_resource.resource = resource;
+ call.info.get_query_result_resource.offset = offset;
+
+ /* In pipelined mode, the query may be deleted by the time we need to
+ * print it.
+ */
+ call.info.get_query_result_resource.query_type = dquery->type;
+
+ dd_before_draw(dctx);
+ pipe->get_query_result_resource(pipe, dquery->query, wait,
+ result_type, index, resource, offset);
+ dd_after_draw(dctx, &call);
+}
+
static void
dd_context_flush_resource(struct pipe_context *_pipe,
struct pipe_resource *resource)
CTX_INIT(clear_texture);
CTX_INIT(flush_resource);
CTX_INIT(generate_mipmap);
+ CTX_INIT(get_query_result_resource);
}