summaryrefslogtreecommitdiffstats
path: root/src/amd/vulkan/radv_device.c
diff options
context:
space:
mode:
authorBas Nieuwenhuizen <[email protected]>2016-12-23 23:51:18 +0100
committerBas Nieuwenhuizen <[email protected]>2017-01-09 21:44:03 +0100
commit97dfff54105ac10b6e2daace020687eefdcc28c0 (patch)
tree52520f9bcb806f000d4ea52b9d1548200ed14183 /src/amd/vulkan/radv_device.c
parent0ef1b4d5b1a3af4ce7ae42ef4259d5db320724c5 (diff)
radv: Dump command buffer on hang.
v2: - Now use the filename specified by RADV_TRACE_FILE env var. - Use the same var to enable tracing. I thought we could as well always set the filename explicitly instead of having some arbitrary defaults, and at that point we don't need a separate feature enable. Signed-off-by: Bas Nieuwenhuizen <[email protected]> Reviewed-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/amd/vulkan/radv_device.c')
-rw-r--r--src/amd/vulkan/radv_device.c82
1 files changed, 73 insertions, 9 deletions
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index e57a419cfaf..ef8ca1a3755 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -760,16 +760,34 @@ VkResult radv_CreateDevice(
device->ws->cs_finalize(device->empty_cs[family]);
}
+ if (getenv("RADV_TRACE_FILE")) {
+ device->trace_bo = device->ws->buffer_create(device->ws, 4096, 8,
+ RADEON_DOMAIN_VRAM, RADEON_FLAG_CPU_ACCESS);
+ if (!device->trace_bo)
+ goto fail;
+
+ device->trace_id_ptr = device->ws->buffer_map(device->trace_bo);
+ if (!device->trace_id_ptr)
+ goto fail;
+ }
+
*pDevice = radv_device_to_handle(device);
return VK_SUCCESS;
fail:
+ if (device->trace_bo)
+ device->ws->buffer_destroy(device->trace_bo);
+
for (unsigned i = 0; i < RADV_MAX_QUEUE_FAMILIES; i++) {
for (unsigned q = 0; q < device->queue_count[i]; q++)
radv_queue_finish(&device->queues[i][q]);
if (device->queue_count[i])
vk_free(&device->alloc, device->queues[i]);
}
+
+ if (device->hw_ctx)
+ device->ws->ctx_destroy(device->hw_ctx);
+
vk_free(&device->alloc, device);
return result;
}
@@ -780,6 +798,9 @@ void radv_DestroyDevice(
{
RADV_FROM_HANDLE(radv_device, device, _device);
+ if (device->trace_bo)
+ device->ws->buffer_destroy(device->trace_bo);
+
device->ws->ctx_destroy(device->hw_ctx);
for (unsigned i = 0; i < RADV_MAX_QUEUE_FAMILIES; i++) {
for (unsigned q = 0; q < device->queue_count[i]; q++)
@@ -869,6 +890,21 @@ void radv_GetDeviceQueue(
*pQueue = radv_queue_to_handle(&device->queues[queueFamilyIndex][queueIndex]);
}
+static void radv_dump_trace(struct radv_device *device,
+ struct radeon_winsys_cs *cs)
+{
+ const char *filename = getenv("RADV_TRACE_FILE");
+ FILE *f = fopen(filename, "w");
+ if (!f) {
+ fprintf(stderr, "Failed to write trace dump to %s\n", filename);
+ return;
+ }
+
+ fprintf(f, "Trace ID: %x\n", *device->trace_id_ptr);
+ device->ws->cs_dump(cs, f, *device->trace_id_ptr);
+ fclose(f);
+}
+
VkResult radv_QueueSubmit(
VkQueue _queue,
uint32_t submitCount,
@@ -880,10 +916,12 @@ VkResult radv_QueueSubmit(
struct radeon_winsys_fence *base_fence = fence ? fence->fence : NULL;
struct radeon_winsys_ctx *ctx = queue->device->hw_ctx;
int ret;
+ uint32_t max_cs_submission = queue->device->trace_bo ? 1 : UINT32_MAX;
for (uint32_t i = 0; i < submitCount; i++) {
struct radeon_winsys_cs **cs_array;
bool can_patch = true;
+ uint32_t advance;
if (!pSubmits[i].commandBufferCount)
continue;
@@ -900,15 +938,41 @@ VkResult radv_QueueSubmit(
if ((cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT))
can_patch = false;
}
- ret = queue->device->ws->cs_submit(ctx, queue->queue_idx, cs_array,
- pSubmits[i].commandBufferCount,
- (struct radeon_winsys_sem **)pSubmits[i].pWaitSemaphores,
- pSubmits[i].waitSemaphoreCount,
- (struct radeon_winsys_sem **)pSubmits[i].pSignalSemaphores,
- pSubmits[i].signalSemaphoreCount,
- can_patch, base_fence);
- if (ret)
- radv_loge("failed to submit CS %d\n", i);
+
+ for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j += advance) {
+ advance = MIN2(max_cs_submission,
+ pSubmits[i].commandBufferCount - j);
+ bool b = j == 0;
+ bool e = j + advance == pSubmits[i].commandBufferCount;
+
+ if (queue->device->trace_bo)
+ *queue->device->trace_id_ptr = 0;
+
+ ret = queue->device->ws->cs_submit(ctx, queue->queue_idx, cs_array,
+ pSubmits[i].commandBufferCount,
+ (struct radeon_winsys_sem **)pSubmits[i].pWaitSemaphores,
+ b ? pSubmits[i].waitSemaphoreCount : 0,
+ (struct radeon_winsys_sem **)pSubmits[i].pSignalSemaphores,
+ e ? pSubmits[i].signalSemaphoreCount : 0,
+ can_patch, base_fence);
+
+ if (ret) {
+ radv_loge("failed to submit CS %d\n", i);
+ abort();
+ }
+ if (queue->device->trace_bo) {
+ bool success = queue->device->ws->ctx_wait_idle(
+ queue->device->hw_ctx,
+ radv_queue_family_to_ring(
+ queue->queue_family_index),
+ queue->queue_idx);
+
+ if (!success) { /* Hang */
+ radv_dump_trace(queue->device, cs_array[j]);
+ abort();
+ }
+ }
+ }
free(cs_array);
}