turnip/trace: refactor creation and usage of trace flush data
Fixes the case when last cmd buffer in submission doesn't have tracepoints leading to flush data not being freed. Added a few comments, renamed things, refactored allocations - now the data flow should be a bit more clean. Extracted submission data creation into tu_u_trace_submission_data_create which would be later used in in tu_kgsl. Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14391>
This commit is contained in:
parent
95896dee93
commit
f2c53c2a9b
|
@ -1414,11 +1414,11 @@ tu_trace_read_ts(struct u_trace_context *utctx,
|
|||
struct tu_device *device =
|
||||
container_of(utctx, struct tu_device, trace_context);
|
||||
struct tu_bo *bo = timestamps;
|
||||
struct tu_u_trace_flush_data *trace_flush_data = flush_data;
|
||||
struct tu_u_trace_submission_data *submission_data = flush_data;
|
||||
|
||||
/* Only need to stall on results for the first entry: */
|
||||
if (idx == 0) {
|
||||
tu_device_wait_u_trace(device, trace_flush_data->syncobj);
|
||||
tu_device_wait_u_trace(device, submission_data->syncobj);
|
||||
}
|
||||
|
||||
if (tu_bo_map(device, bo) != VK_SUCCESS) {
|
||||
|
@ -1439,12 +1439,9 @@ tu_trace_delete_flush_data(struct u_trace_context *utctx, void *flush_data)
|
|||
{
|
||||
struct tu_device *device =
|
||||
container_of(utctx, struct tu_device, trace_context);
|
||||
struct tu_u_trace_flush_data *trace_flush_data = flush_data;
|
||||
struct tu_u_trace_submission_data *submission_data = flush_data;
|
||||
|
||||
tu_u_trace_cmd_data_finish(device, trace_flush_data->cmd_trace_data,
|
||||
trace_flush_data->trace_count);
|
||||
vk_free(&device->vk.alloc, trace_flush_data->syncobj);
|
||||
vk_free(&device->vk.alloc, trace_flush_data);
|
||||
tu_u_trace_submission_data_finish(device, submission_data);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1502,23 +1499,93 @@ tu_create_copy_timestamp_cs(struct tu_cmd_buffer *cmdbuf, struct tu_cs** cs,
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_u_trace_cmd_data_finish(struct tu_device *device,
|
||||
struct tu_u_trace_cmd_data *trace_data,
|
||||
uint32_t entry_count)
|
||||
VkResult
|
||||
tu_u_trace_submission_data_create(
|
||||
struct tu_device *device,
|
||||
struct tu_cmd_buffer **cmd_buffers,
|
||||
uint32_t cmd_buffer_count,
|
||||
struct tu_u_trace_submission_data **submission_data)
|
||||
{
|
||||
for (uint32_t i = 0; i < entry_count; ++i) {
|
||||
/* Only if we had to create a copy of trace we should free it */
|
||||
if (trace_data[i].timestamp_copy_cs != NULL) {
|
||||
tu_cs_finish(trace_data[i].timestamp_copy_cs);
|
||||
vk_free(&device->vk.alloc, trace_data[i].timestamp_copy_cs);
|
||||
*submission_data =
|
||||
vk_zalloc(&device->vk.alloc,
|
||||
sizeof(struct tu_u_trace_submission_data), 8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
|
||||
u_trace_fini(trace_data[i].trace);
|
||||
vk_free(&device->vk.alloc, trace_data[i].trace);
|
||||
if (!(*submission_data)) {
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
struct tu_u_trace_submission_data *data = *submission_data;
|
||||
|
||||
data->cmd_trace_data =
|
||||
vk_zalloc(&device->vk.alloc,
|
||||
cmd_buffer_count * sizeof(struct tu_u_trace_cmd_data), 8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
|
||||
if (!data->cmd_trace_data) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data->cmd_buffer_count = cmd_buffer_count;
|
||||
data->last_buffer_with_tracepoints = -1;
|
||||
|
||||
for (uint32_t i = 0; i < cmd_buffer_count; ++i) {
|
||||
struct tu_cmd_buffer *cmdbuf = cmd_buffers[i];
|
||||
|
||||
if (!u_trace_has_points(&cmdbuf->trace))
|
||||
continue;
|
||||
|
||||
data->last_buffer_with_tracepoints = i;
|
||||
|
||||
if (!(cmdbuf->usage_flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)) {
|
||||
/* A single command buffer could be submitted several times, but we
|
||||
* already baked timestamp iova addresses and trace points are
|
||||
* single-use. Therefor we have to copy trace points and create
|
||||
* a new timestamp buffer on every submit of reusable command buffer.
|
||||
*/
|
||||
if (tu_create_copy_timestamp_cs(cmdbuf,
|
||||
&data->cmd_trace_data[i].timestamp_copy_cs,
|
||||
&data->cmd_trace_data[i].trace) != VK_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
assert(data->cmd_trace_data[i].timestamp_copy_cs->entry_count == 1);
|
||||
} else {
|
||||
data->cmd_trace_data[i].trace = &cmdbuf->trace;
|
||||
}
|
||||
}
|
||||
|
||||
vk_free(&device->vk.alloc, trace_data);
|
||||
assert(data->last_buffer_with_tracepoints != -1);
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
tu_u_trace_submission_data_finish(device, data);
|
||||
*submission_data = NULL;
|
||||
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
void
|
||||
tu_u_trace_submission_data_finish(
|
||||
struct tu_device *device,
|
||||
struct tu_u_trace_submission_data *submission_data)
|
||||
{
|
||||
for (uint32_t i = 0; i < submission_data->cmd_buffer_count; ++i) {
|
||||
/* Only if we had to create a copy of trace we should free it */
|
||||
struct tu_u_trace_cmd_data *cmd_data = &submission_data->cmd_trace_data[i];
|
||||
if (cmd_data->timestamp_copy_cs) {
|
||||
tu_cs_finish(cmd_data->timestamp_copy_cs);
|
||||
vk_free(&device->vk.alloc, cmd_data->timestamp_copy_cs);
|
||||
|
||||
u_trace_fini(cmd_data->trace);
|
||||
vk_free(&device->vk.alloc, cmd_data->trace);
|
||||
}
|
||||
}
|
||||
|
||||
vk_free(&device->vk.alloc, submission_data->cmd_trace_data);
|
||||
vk_free(&device->vk.alloc, submission_data->syncobj);
|
||||
vk_free(&device->vk.alloc, submission_data);
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
struct tu_queue_submit
|
||||
{
|
||||
struct vk_queue_submit *vk_submit;
|
||||
struct tu_u_trace_cmd_data *cmd_buffer_trace_data;
|
||||
struct tu_u_trace_submission_data *u_trace_submission_data;
|
||||
|
||||
struct drm_msm_gem_submit_cmd *cmds;
|
||||
struct drm_msm_gem_submit_syncobj *in_syncobjs;
|
||||
|
@ -751,35 +751,14 @@ tu_queue_submit_create_locked(struct tu_queue *queue,
|
|||
}
|
||||
|
||||
if (has_trace_points) {
|
||||
new_submit->cmd_buffer_trace_data = vk_zalloc(&queue->device->vk.alloc,
|
||||
vk_submit->command_buffer_count * sizeof(struct tu_u_trace_cmd_data),
|
||||
8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
result =
|
||||
tu_u_trace_submission_data_create(
|
||||
queue->device, cmd_buffers,
|
||||
vk_submit->command_buffer_count,
|
||||
&new_submit->u_trace_submission_data);
|
||||
|
||||
if (new_submit->cmd_buffer_trace_data == NULL) {
|
||||
result = vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto fail_cmd_trace_data;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < vk_submit->command_buffer_count; ++i) {
|
||||
struct tu_cmd_buffer *cmdbuf = cmd_buffers[i];
|
||||
|
||||
if (!(cmdbuf->usage_flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) &&
|
||||
u_trace_has_points(&cmdbuf->trace)) {
|
||||
/* A single command buffer could be submitted several times, but we
|
||||
* already backed timestamp iova addresses and trace points are
|
||||
* single-use. Therefor we have to copy trace points and create
|
||||
* a new timestamp buffer on every submit of reusable command buffer.
|
||||
*/
|
||||
if (tu_create_copy_timestamp_cs(cmdbuf,
|
||||
&new_submit->cmd_buffer_trace_data[i].timestamp_copy_cs,
|
||||
&new_submit->cmd_buffer_trace_data[i].trace) != VK_SUCCESS) {
|
||||
result = vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto fail_copy_timestamp_cs;
|
||||
}
|
||||
assert(new_submit->cmd_buffer_trace_data[i].timestamp_copy_cs->entry_count == 1);
|
||||
} else {
|
||||
new_submit->cmd_buffer_trace_data[i].trace = &cmdbuf->trace;
|
||||
}
|
||||
if (result != VK_SUCCESS) {
|
||||
goto fail_u_trace_submission_data;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -814,12 +793,10 @@ tu_queue_submit_create_locked(struct tu_queue *queue,
|
|||
fail_out_syncobjs:
|
||||
vk_free(&queue->device->vk.alloc, new_submit->in_syncobjs);
|
||||
fail_in_syncobjs:
|
||||
if (new_submit->cmd_buffer_trace_data)
|
||||
tu_u_trace_cmd_data_finish(queue->device, new_submit->cmd_buffer_trace_data,
|
||||
new_submit->vk_submit->command_buffer_count);
|
||||
fail_copy_timestamp_cs:
|
||||
vk_free(&queue->device->vk.alloc, new_submit->cmd_buffer_trace_data);
|
||||
fail_cmd_trace_data:
|
||||
if (new_submit->u_trace_submission_data)
|
||||
tu_u_trace_submission_data_finish(queue->device,
|
||||
new_submit->u_trace_submission_data);
|
||||
fail_u_trace_submission_data:
|
||||
vk_free(&queue->device->vk.alloc, new_submit->cmds);
|
||||
fail_cmds:
|
||||
return result;
|
||||
|
@ -873,8 +850,9 @@ tu_queue_build_msm_gem_submit_cmds(struct tu_queue *queue,
|
|||
cmds[entry_idx].relocs = 0;
|
||||
}
|
||||
|
||||
if (submit->cmd_buffer_trace_data) {
|
||||
struct tu_cs *ts_cs = submit->cmd_buffer_trace_data[j].timestamp_copy_cs;
|
||||
if (submit->u_trace_submission_data) {
|
||||
struct tu_cs *ts_cs =
|
||||
submit->u_trace_submission_data->cmd_trace_data[j].timestamp_copy_cs;
|
||||
if (ts_cs) {
|
||||
cmds[entry_idx].type = MSM_SUBMIT_CMD_BUF;
|
||||
cmds[entry_idx].submit_idx =
|
||||
|
@ -940,24 +918,29 @@ tu_queue_submit_locked(struct tu_queue *queue, struct tu_queue_submit *submit)
|
|||
tu_perfetto_submit(queue->device, queue->device->submit_count);
|
||||
#endif
|
||||
|
||||
if (submit->cmd_buffer_trace_data) {
|
||||
struct tu_u_trace_flush_data *flush_data =
|
||||
vk_alloc(&queue->device->vk.alloc, sizeof(struct tu_u_trace_flush_data),
|
||||
8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
flush_data->submission_id = queue->device->submit_count;
|
||||
flush_data->syncobj =
|
||||
if (submit->u_trace_submission_data) {
|
||||
struct tu_u_trace_submission_data *submission_data =
|
||||
submit->u_trace_submission_data;
|
||||
submission_data->submission_id = queue->device->submit_count;
|
||||
/* We have to allocate it here since it is different between drm/kgsl */
|
||||
submission_data->syncobj =
|
||||
vk_alloc(&queue->device->vk.alloc, sizeof(struct tu_u_trace_syncobj),
|
||||
8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
flush_data->syncobj->fence = req.fence;
|
||||
flush_data->syncobj->msm_queue_id = queue->msm_queue_id;
|
||||
submission_data->syncobj->fence = req.fence;
|
||||
submission_data->syncobj->msm_queue_id = queue->msm_queue_id;
|
||||
|
||||
flush_data->cmd_trace_data = submit->cmd_buffer_trace_data;
|
||||
flush_data->trace_count = submit->vk_submit->command_buffer_count;
|
||||
submit->cmd_buffer_trace_data = NULL;
|
||||
submit->u_trace_submission_data = NULL;
|
||||
|
||||
for (uint32_t i = 0; i < submit->vk_submit->command_buffer_count; i++) {
|
||||
bool free_data = i == (submit->vk_submit->command_buffer_count - 1);
|
||||
u_trace_flush(flush_data->cmd_trace_data[i].trace, flush_data, free_data);
|
||||
bool free_data = i == submission_data->last_buffer_with_tracepoints;
|
||||
if (submission_data->cmd_trace_data[i].trace)
|
||||
u_trace_flush(submission_data->cmd_trace_data[i].trace,
|
||||
submission_data, free_data);
|
||||
|
||||
if (!submission_data->cmd_trace_data[i].timestamp_copy_cs) {
|
||||
/* u_trace is owned by cmd_buffer */
|
||||
submission_data->cmd_trace_data[i].trace = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -275,11 +275,11 @@ tu_end_##event_name(struct tu_device *dev, uint64_t ts_ns, \
|
|||
const void *flush_data, \
|
||||
const struct trace_end_##event_name *payload) \
|
||||
{ \
|
||||
auto trace_flush_data = (const struct tu_u_trace_flush_data *) flush_data; \
|
||||
uint32_t submission_id = \
|
||||
tu_u_trace_flush_data_get_submit_id(trace_flush_data); \
|
||||
stage_end(dev, ts_ns, stage, submission_id, payload, \
|
||||
(trace_payload_as_extra_func) &trace_payload_as_extra_end_##event_name);\
|
||||
auto trace_flush_data = (const struct tu_u_trace_submission_data *) flush_data; \
|
||||
uint32_t submission_id = \
|
||||
tu_u_trace_submission_data_get_submit_id(trace_flush_data); \
|
||||
stage_end(dev, ts_ns, stage, submission_id, payload, \
|
||||
(trace_payload_as_extra_func) &trace_payload_as_extra_end_##event_name); \
|
||||
}
|
||||
|
||||
CREATE_EVENT_CALLBACK(render_pass, SURFACE_STAGE_ID)
|
||||
|
|
|
@ -103,9 +103,9 @@ tu_device_get_timestamp(struct tu_device *dev,
|
|||
uint64_t
|
||||
tu_device_ticks_to_ns(struct tu_device *dev, uint64_t ts);
|
||||
|
||||
struct tu_u_trace_flush_data;
|
||||
struct tu_u_trace_submission_data;
|
||||
uint32_t
|
||||
tu_u_trace_flush_data_get_submit_id(const struct tu_u_trace_flush_data *data);
|
||||
tu_u_trace_submission_data_get_submit_id(const struct tu_u_trace_submission_data *data);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ tu_device_get_timestamp(struct tu_device *dev,
|
|||
}
|
||||
|
||||
uint32_t
|
||||
tu_u_trace_flush_data_get_submit_id(const struct tu_u_trace_flush_data *data)
|
||||
tu_u_trace_submission_data_get_submit_id(const struct tu_u_trace_submission_data *data)
|
||||
{
|
||||
return data->submission_id;
|
||||
}
|
||||
|
|
|
@ -1759,25 +1759,41 @@ VkResult
|
|||
tu_create_copy_timestamp_cs(struct tu_cmd_buffer *cmdbuf, struct tu_cs** cs,
|
||||
struct u_trace **trace_copy);
|
||||
|
||||
/* If we copy trace and timestamps we will have to free them. */
|
||||
struct tu_u_trace_cmd_data
|
||||
{
|
||||
struct tu_cs *timestamp_copy_cs;
|
||||
struct u_trace *trace;
|
||||
};
|
||||
|
||||
void
|
||||
tu_u_trace_cmd_data_finish(struct tu_device *device,
|
||||
struct tu_u_trace_cmd_data *trace_data,
|
||||
uint32_t entry_count);
|
||||
|
||||
struct tu_u_trace_flush_data
|
||||
/* Data necessary to retrieve timestamps and clean all
|
||||
* associated resources afterwards.
|
||||
*/
|
||||
struct tu_u_trace_submission_data
|
||||
{
|
||||
uint32_t submission_id;
|
||||
/* We have to know when timestamps are available,
|
||||
* this sync object indicates it.
|
||||
*/
|
||||
struct tu_u_trace_syncobj *syncobj;
|
||||
uint32_t trace_count;
|
||||
|
||||
uint32_t cmd_buffer_count;
|
||||
uint32_t last_buffer_with_tracepoints;
|
||||
struct tu_u_trace_cmd_data *cmd_trace_data;
|
||||
};
|
||||
|
||||
VkResult
|
||||
tu_u_trace_submission_data_create(
|
||||
struct tu_device *device,
|
||||
struct tu_cmd_buffer **cmd_buffers,
|
||||
uint32_t cmd_buffer_count,
|
||||
struct tu_u_trace_submission_data **submission_data);
|
||||
|
||||
void
|
||||
tu_u_trace_submission_data_finish(
|
||||
struct tu_device *device,
|
||||
struct tu_u_trace_submission_data *submission_data);
|
||||
|
||||
#define TU_FROM_HANDLE(__tu_type, __name, __handle) \
|
||||
VK_FROM_HANDLE(__tu_type, __name, __handle)
|
||||
|
||||
|
|
Loading…
Reference in New Issue