Commit 1fcd8306 authored by Mark Janes's avatar Mark Janes

intel: support secondary command buffers in INTEL_MEASURE

parent 1a76e7e5
Pipeline #256304 waiting for manual action with stages
in 9 seconds
......@@ -301,7 +301,7 @@ iris_use_pinned_bo(struct iris_batch *batch,
}
if (bo != batch->bo &&
(!batch->measure || bo != batch->measure->bo)) {
(!batch->measure || bo != batch->measure->base.bo)) {
/* This is the first time our batch has seen this BO. Before we use it,
* we may need to flush and synchronize with other batches.
*/
......
......@@ -31,6 +31,21 @@
#include "iris_context.h"
#include "iris_defines.h"
static uint64_t *
measure_mmap(void *_measure_batch)
{
struct intel_measure_batch *measure_batch = _measure_batch;
struct iris_bo *bo = measure_batch->bo;
return iris_bo_map(NULL, bo, MAP_READ);
}
static void
measure_unmap(void *_measure_batch, void *bo_mem)
{
struct intel_measure_batch *measure_batch = _measure_batch;
iris_bo_unmap(measure_batch->bo);
}
void
iris_init_screen_measure(struct iris_screen *screen)
{
......@@ -45,6 +60,9 @@ iris_init_screen_measure(struct iris_screen *screen)
list_inithead(&measure_device->queued_snapshots);
pthread_mutex_init(&measure_device->mutex, NULL);
config->mmap_fn = measure_mmap;
config->munmap_fn = measure_unmap;
/* the final member of intel_measure_ringbuffer is a zero-length array of
* intel_measure_buffered_result objects. Allocate additional space for
* the buffered objects based on the run-time configurable buffer_size
......@@ -106,7 +124,7 @@ iris_init_batch_measure(struct iris_context *ice, struct iris_batch *batch)
memset(batch->measure, 0, batch_bytes);
struct iris_measure_batch *measure = batch->measure;
measure->bo =
measure->base.bo =
iris_bo_alloc_tiled(bufmgr, "measure",
config->batch_size * sizeof(uint64_t),
1, /* alignment */
......@@ -123,7 +141,7 @@ iris_init_batch_measure(struct iris_context *ice, struct iris_batch *batch)
static bool
iris_measure_ready(struct iris_measure_batch *measure)
{
return !iris_bo_busy(measure->bo);
return !iris_bo_busy(measure->base.bo);
}
void
......@@ -132,8 +150,8 @@ iris_destroy_batch_measure(struct iris_measure_batch *batch)
if (!batch)
return;
iris_bo_unreference(batch->bo);
batch->bo = NULL;
iris_bo_unreference(batch->base.bo);
batch->base.bo = NULL;
free(batch);
}
......@@ -178,7 +196,7 @@ measure_start_snapshot(struct iris_context *ice,
iris_emit_pipe_control_write(batch, "measurement snapshot",
PIPE_CONTROL_WRITE_TIMESTAMP |
PIPE_CONTROL_CS_STALL,
batch->measure->bo, index * sizeof(uint64_t), 0ull);
batch->measure->base.bo, index * sizeof(uint64_t), 0ull);
if (event_name == NULL)
event_name = intel_measure_snapshot_string(type);
......@@ -213,7 +231,7 @@ measure_end_snapshot(struct iris_batch *batch,
iris_emit_pipe_control_write(batch, "measurement snapshot",
PIPE_CONTROL_WRITE_TIMESTAMP |
PIPE_CONTROL_CS_STALL,
batch->measure->bo,
batch->measure->base.bo,
index * sizeof(uint64_t), 0ull);
struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);
......@@ -359,20 +377,21 @@ iris_measure_gather(struct iris_context *ice)
* not started execution. The first timestamp will be non-zero if the
* buffer object is ready.
*/
uint64_t *map = iris_bo_map(NULL, measure->bo, MAP_READ);
if (map[0] == 0) {
uint64_t *map = iris_bo_map(NULL, measure->base.bo, MAP_READ);
const uint64_t first_ts = *map;
iris_bo_unmap(measure->base.bo);
if (first_ts == 0) {
/* The command buffer has not begun execution on the gpu. */
iris_bo_unmap(measure->bo);
break;
}
list_del(&measure->link);
assert(measure->bo);
assert(measure->base.bo);
assert(measure->base.index % 2 == 0);
intel_measure_push_result(measure_device, &measure->base, map);
intel_measure_push_result(measure_device, &measure->base);
iris_bo_unmap(measure->bo);
/* iris_bo_unmap(measure->bo); */
measure->base.index = 0;
measure->base.frame = 0;
iris_destroy_batch_measure(measure);
......
......@@ -29,7 +29,6 @@
struct iris_screen;
struct iris_measure_batch {
struct iris_bo *bo;
struct list_head link;
struct intel_measure_batch base;
};
......
......@@ -233,6 +233,7 @@ intel_measure_snapshot_string(enum intel_measure_snapshot_type type)
[INTEL_SNAPSHOT_MCS_PARTIAL_RESOLVE] = "mcs partial resolve",
[INTEL_SNAPSHOT_SLOW_COLOR_CLEAR] = "slow color clear",
[INTEL_SNAPSHOT_SLOW_DEPTH_CLEAR] = "slow depth clear",
[INTEL_SNAPSHOT_SECONDARY_BATCH] = "secondary command buffer",
[INTEL_SNAPSHOT_END] = "end",
};
assert(type < ARRAY_SIZE(names));
......@@ -377,16 +378,27 @@ raw_timestamp_delta(uint64_t time0, uint64_t time1)
*/
void
intel_measure_push_result(struct intel_measure_device *device,
struct intel_measure_batch *batch,
uint64_t *timestamps)
struct intel_measure_batch *batch)
{
struct intel_measure_ringbuffer *rb = device->ringbuffer;
uint64_t *timestamps = config.mmap_fn(batch);
assert(timestamps != NULL);
assert(timestamps[0] != 0);
for (int i = 0; i < batch->index; i += 2) {
const struct intel_measure_snapshot *begin = &batch->snapshots[i];
const struct intel_measure_snapshot *end = &batch->snapshots[i+1];
assert (end->type == INTEL_SNAPSHOT_END);
if (begin->type == INTEL_SNAPSHOT_SECONDARY_BATCH) {
assert(begin->secondary != NULL);
begin->secondary->batch_count = batch->batch_count;
intel_measure_push_result(device, begin->secondary);
continue;
}
const uint64_t prev_end_ts = rb->results[rb->head].end_ts;
/* advance ring buffer */
......@@ -402,7 +414,7 @@ intel_measure_push_result(struct intel_measure_device *device,
config.buffer_size);
warned = true;
}
return;
break;
}
struct intel_measure_buffered_result *buffered_result =
......@@ -420,6 +432,8 @@ intel_measure_push_result(struct intel_measure_device *device,
buffered_result->event_index = i / 2;
buffered_result->snapshot.event_count = end->event_count;
}
config.munmap_fn(batch, timestamps);
}
......
......@@ -48,6 +48,7 @@ enum intel_measure_snapshot_type {
INTEL_SNAPSHOT_MCS_PARTIAL_RESOLVE,
INTEL_SNAPSHOT_SLOW_COLOR_CLEAR,
INTEL_SNAPSHOT_SLOW_DEPTH_CLEAR,
INTEL_SNAPSHOT_SECONDARY_BATCH,
INTEL_SNAPSHOT_END,
};
......@@ -99,13 +100,20 @@ struct intel_measure_config {
/* true when snapshots are currently being collected */
bool enabled;
uint64_t *(*mmap_fn)(void *measure_batch);
void (*munmap_fn)(void *measure_batch, void *bo_mem);
};
struct intel_measure_batch;
struct intel_measure_snapshot {
enum intel_measure_snapshot_type type;
unsigned count, event_count;
const char* event_name;
uintptr_t framebuffer, vs, tcs, tes, gs, fs, cs;
/* for vulkan secondary command buffers */
struct intel_measure_batch *secondary;
};
struct intel_measure_buffered_result {
......@@ -139,6 +147,8 @@ struct intel_measure_batch {
unsigned index;
unsigned frame, batch_count, event_count;
uintptr_t framebuffer;
void *device; /* anv_device (not used in iris) */
void *bo; /* iris_bo or anv_bo */
struct intel_measure_snapshot snapshots[0];
};
......@@ -148,9 +158,9 @@ bool intel_measure_state_changed(const struct intel_measure_batch *batch,
uintptr_t vs, uintptr_t tcs, uintptr_t tes,
uintptr_t gs, uintptr_t fs, uintptr_t cs);
void intel_measure_frame_transition(unsigned frame);
void intel_measure_push_result(struct intel_measure_device *device,
struct intel_measure_batch *batch,
uint64_t *timestamps);
struct intel_measure_batch *batch);
struct gen_device_info;
void intel_measure_print(struct intel_measure_device *device,
......
......@@ -28,6 +28,7 @@
#include <fcntl.h>
#include "anv_private.h"
#include "anv_measure.h"
#include "genxml/gen8_pack.h"
#include "genxml/genX_bits.h"
......@@ -1013,6 +1014,7 @@ void
anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary,
struct anv_cmd_buffer *secondary)
{
anv_measure_add_secondary(primary, secondary);
switch (secondary->exec_mode) {
case ANV_CMD_BUFFER_EXEC_MODE_EMIT:
anv_batch_emit_batch(&primary->batch, &secondary->batch);
......
......@@ -31,11 +31,26 @@
#include "util/debug.h"
struct anv_measure_batch {
struct anv_bo *bo;
struct list_head link;
struct intel_measure_batch base;
};
static uint64_t *
measure_mmap(void *_measure_batch) {
struct intel_measure_batch *measure_batch = _measure_batch;
struct anv_device *device = measure_batch->device;
struct anv_bo *bo = (struct anv_bo *)measure_batch->bo;
return anv_gem_mmap(device, bo->gem_handle, 0,
measure_batch->index * sizeof(uint64_t), 0);
}
static void
measure_munmap(void *_measure_batch, void *bo_mem) {
struct intel_measure_batch *measure = _measure_batch;
struct anv_device *device = measure->device;
anv_gem_munmap(device, bo_mem, measure->index * sizeof(uint64_t));
}
void
anv_measure_device_init(struct anv_physical_device *device)
{
......@@ -81,6 +96,9 @@ anv_measure_device_init(struct anv_physical_device *device)
if (config == NULL)
return;
config->mmap_fn = measure_mmap;
config->munmap_fn = measure_munmap;
/* the final member of intel_measure_ringbuffer is a zero-length array of
* intel_measure_buffered_result objects. Allocate additional space for
* the buffered objects based on the run-time configurable buffer_size
......@@ -128,8 +146,12 @@ anv_measure_init(struct anv_cmd_buffer *cmd_buffer)
config->batch_size * sizeof(uint64_t),
ANV_BO_ALLOC_MAPPED,
0,
&measure->bo);
(struct anv_bo**)&measure->base.bo);
measure->base.device = device;
assert(result == VK_SUCCESS);
list_inithead(&measure->link);
cmd_buffer->measure = measure;
}
......@@ -138,7 +160,7 @@ anv_measure_ready(struct anv_device *device,
struct anv_measure_batch *measure)
{
/* anv_device_bo_busy returns VK_NOT_READY if the bo is busy */
return(VK_SUCCESS == anv_device_bo_busy(device, measure->bo));
return(VK_SUCCESS == anv_device_bo_busy(device, measure->base.bo));
}
/**
......@@ -165,25 +187,16 @@ anv_measure_gather(struct anv_device *device)
break;
}
uint64_t *map = anv_gem_mmap(device, measure->bo->gem_handle, 0,
measure->base.index * sizeof(uint64_t), 0);
if (map[0] == 0) {
/* The first timestamp is still zero. The Command buffer has not
* begun execution on the gpu. It was recently submitted, perhaps by
* another thread.
*/
anv_gem_munmap(device, map, measure->base.index * sizeof(uint64_t));
if (VK_SUCCESS != anv_device_wait(device, measure->base.bo, 0))
/* rendering not yet submitted */
break;
}
list_del(&measure->link);
assert(measure->bo);
assert(measure->base.bo);
assert(measure->base.index % 2 == 0);
intel_measure_push_result(measure_device, &measure->base, map);
intel_measure_push_result(measure_device, &measure->base);
anv_gem_munmap(device, map, measure->base.index * sizeof(uint64_t));
measure->base.index = 0;
measure->base.frame = 0;
}
......@@ -213,6 +226,11 @@ anv_measure_start_snapshot(struct anv_cmd_buffer *cmd_buffer,
uintptr_t framebuffer = (uintptr_t)cmd_buffer->state.framebuffer;
if (!measure->base.framebuffer &&
cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
/* secondary command buffer inherited the framebuffer from the primary */
measure->base.framebuffer = framebuffer;
/* verify framebuffer has been properly tracked */
assert(type == INTEL_SNAPSHOT_END ||
framebuffer == measure->base.framebuffer ||
......@@ -220,7 +238,7 @@ anv_measure_start_snapshot(struct anv_cmd_buffer *cmd_buffer,
unsigned index = measure->base.index++;
(*device->cmd_emit_timestamp)(batch, measure->bo, index * sizeof(uint64_t));
(*device->cmd_emit_timestamp)(batch, measure->base.bo, index * sizeof(uint64_t));
if (event_name == NULL)
event_name = intel_measure_snapshot_string(type);
......@@ -257,7 +275,7 @@ anv_measure_end_snapshot(struct anv_cmd_buffer *cmd_buffer,
unsigned index = measure->base.index++;
assert(index % 2 == 1);
(*device->cmd_emit_timestamp)(batch, measure->bo, index * sizeof(uint64_t));
(*device->cmd_emit_timestamp)(batch, measure->base.bo, index * sizeof(uint64_t));
struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[index]);
memset(snapshot, 0, sizeof(*snapshot));
......@@ -270,6 +288,11 @@ state_changed(struct anv_cmd_buffer *cmd_buffer,
enum intel_measure_snapshot_type type)
{
uintptr_t vs=0, tcs=0, tes=0, gs=0, fs=0, cs=0;
if (cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)
/* can't record timestamps in this mode */
return false;
if (type == INTEL_SNAPSHOT_COMPUTE) {
const struct anv_compute_pipeline *cs_pipe =
cmd_buffer->state.compute.pipeline;
......@@ -379,14 +402,16 @@ anv_measure_reset(struct anv_cmd_buffer *cmd_buffer)
measure->base.framebuffer = 0;
measure->base.frame = 0;
measure->base.event_count = 0;
list_inithead(&measure->link);
anv_device_release_bo(device, measure->bo);
anv_device_release_bo(device, measure->base.bo);
VkResult result =
anv_device_alloc_bo(device,
config->batch_size * sizeof(uint64_t),
ANV_BO_ALLOC_MAPPED,
0,
&measure->bo);
(struct anv_bo**)&measure->base.bo);
measure->base.bo = measure->base.bo;
assert(result == VK_SUCCESS);
}
......@@ -407,7 +432,7 @@ anv_measure_destroy(struct anv_cmd_buffer *cmd_buffer)
*/
anv_measure_gather(device);
anv_device_release_bo(device, measure->bo);
anv_device_release_bo(device, measure->base.bo);
vk_free(&cmd_buffer->pool->alloc, measure);
cmd_buffer->measure = NULL;
}
......@@ -533,3 +558,36 @@ _anv_measure_beginrenderpass(struct anv_cmd_buffer *cmd_buffer)
measure->base.framebuffer = (uintptr_t) cmd_buffer->state.framebuffer;
}
void
_anv_measure_add_secondary(struct anv_cmd_buffer *primary,
struct anv_cmd_buffer *secondary)
{
struct intel_measure_config *config = config_from_command_buffer(primary);
struct anv_measure_batch *measure = primary->measure;
if (!config)
return;
if (measure == NULL)
return;
if (config->flags & (INTEL_MEASURE_BATCH | INTEL_MEASURE_FRAME))
/* secondary timing will be contained within the primary */
return;
if (secondary->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
static bool warned = false;
if (unlikely(!warned)) {
fprintf(config->file,
"WARNING: INTEL_MEASURE cannot capture timings of commands "
"in secondary command buffers with "
"VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set.\n");
}
return;
}
if (measure->base.index % 2 == 1)
anv_measure_end_snapshot(primary, measure->base.event_count);
struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[measure->base.index]);
_anv_measure_snapshot(primary, INTEL_SNAPSHOT_SECONDARY_BATCH, NULL, 0);
snapshot->secondary = &secondary->measure->base;
}
......@@ -51,6 +51,10 @@ void anv_measure_acquire(struct anv_device *device);
/* should be combined with endcommandbuffer */
void _anv_measure_submit(struct anv_cmd_buffer *cmd_buffer);
void
_anv_measure_add_secondary(struct anv_cmd_buffer *primary,
struct anv_cmd_buffer *secondary);
#define anv_measure_snapshot(cmd_buffer, type, event_name, count) \
if (unlikely(cmd_buffer->measure)) \
_anv_measure_snapshot(cmd_buffer, type, event_name, count)
......@@ -67,5 +71,8 @@ void _anv_measure_submit(struct anv_cmd_buffer *cmd_buffer);
if (unlikely(cmd_buffer->measure)) \
_anv_measure_submit(cmd_buffer)
#define anv_measure_add_secondary(primary, secondary) \
if (unlikely(primary->measure)) \
_anv_measure_add_secondary(primary, secondary)
#endif /* ANV_MEASURE_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment