intel: Add the ability to supply annotations for .aub files.

This patch adds a new function,
drm_intel_bufmgr_gem_set_aub_annotations(), which can be used to
annotate the type and subtype of data stored in various sections of
each buffer.  This data is used to populate type and subtype fields
when generating the .aub file, which improves the ability of later
debugging tools to analyze the contents of the .aub file.

If drm_intel_bufmgr_gem_set_aub_annotations() is not called, then we
fall back to the old set of annotations (annotate the portion of the
batchbuffer that is executed as AUB_TRACE_TYPE_BATCH, and everything
else as AUB_TRACE_TYPE_NOTYPE).

Reviewed-by: Eric Anholt <eric@anholt.net>
main
Paul Berry 2012-05-04 12:41:00 -07:00
parent cf7cc62a98
commit da02f72bc2
2 changed files with 119 additions and 22 deletions

View File

@ -92,6 +92,12 @@ enum aub_dump_bmp_format {
AUB_DUMP_BMP_FORMAT_ARGB_8888 = 7,
};
typedef struct _drm_intel_aub_annotation {
uint32_t type;
uint32_t subtype;
uint32_t ending_offset;
} drm_intel_aub_annotation;
#define BO_ALLOC_FOR_RENDER (1<<0)
drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
@ -169,6 +175,10 @@ void drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
int x1, int y1, int width, int height,
enum aub_dump_bmp_format format,
int pitch, int offset);
void
drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
drm_intel_aub_annotation *annotations,
unsigned count);
int drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id);

View File

@ -221,6 +221,9 @@ struct _drm_intel_bo_gem {
bool mapped_cpu_write;
uint32_t aub_offset;
drm_intel_aub_annotation *aub_annotations;
unsigned aub_annotation_count;
};
static unsigned int
@ -735,6 +738,8 @@ retry:
bo_gem->used_as_reloc_target = false;
bo_gem->has_error = false;
bo_gem->reusable = true;
bo_gem->aub_annotations = NULL;
bo_gem->aub_annotation_count = 0;
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
@ -926,6 +931,7 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
bo_gem->gem_handle, bo_gem->name, strerror(errno));
}
free(bo_gem->aub_annotations);
free(bo);
}
@ -1880,26 +1886,58 @@ aub_write_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
aub_write_bo_data(bo, offset, size);
}
/**
* Break up large objects into multiple writes. Otherwise a 128kb VBO
* would overflow the 16 bits of size field in the packet header and
* everything goes badly after that.
*/
static void
aub_write_bo(drm_intel_bo *bo)
aub_write_large_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
uint32_t offset, uint32_t size)
{
uint32_t block_size;
uint32_t offset;
uint32_t sub_offset;
aub_bo_get_address(bo);
/* Break up large objects into multiple writes. Otherwise a
* 128kb VBO would overflow the 16 bits of size field in the
* packet header and everything goes badly after that.
*/
for (offset = 0; offset < bo->size; offset += block_size) {
block_size = bo->size - offset;
for (sub_offset = 0; sub_offset < size; sub_offset += block_size) {
block_size = size - sub_offset;
if (block_size > 8 * 4096)
block_size = 8 * 4096;
aub_write_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
offset, block_size);
aub_write_trace_block(bo, type, subtype, offset + sub_offset,
block_size);
}
}
static void
aub_write_bo(drm_intel_bo *bo)
{
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
uint32_t offset = 0;
unsigned i;
aub_bo_get_address(bo);
/* Write out each annotated section separately. */
for (i = 0; i < bo_gem->aub_annotation_count; ++i) {
drm_intel_aub_annotation *annotation =
&bo_gem->aub_annotations[i];
uint32_t ending_offset = annotation->ending_offset;
if (ending_offset > bo->size)
ending_offset = bo->size;
if (ending_offset > offset) {
aub_write_large_trace_block(bo, annotation->type,
annotation->subtype,
offset,
ending_offset - offset);
offset = ending_offset;
}
}
/* Write out any remaining unannotated data */
if (offset < bo->size) {
aub_write_large_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
offset, bo->size - offset);
}
}
@ -1989,23 +2027,31 @@ aub_exec(drm_intel_bo *bo, int ring_flag, int used)
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
int i;
bool batch_buffer_needs_annotations;
if (!bufmgr_gem->aub_file)
return;
/* Write out all but the batchbuffer to AUB memory */
for (i = 0; i < bufmgr_gem->exec_count - 1; i++) {
if (bufmgr_gem->exec_bos[i] != bo)
/* If batch buffer is not annotated, annotate it the best we
* can.
*/
batch_buffer_needs_annotations = bo_gem->aub_annotation_count == 0;
if (batch_buffer_needs_annotations) {
drm_intel_aub_annotation annotations[2] = {
{ AUB_TRACE_TYPE_BATCH, 0, used },
{ AUB_TRACE_TYPE_NOTYPE, 0, bo->size }
};
drm_intel_bufmgr_gem_set_aub_annotations(bo, annotations, 2);
}
/* Write out all buffers to AUB memory */
for (i = 0; i < bufmgr_gem->exec_count; i++) {
aub_write_bo(bufmgr_gem->exec_bos[i]);
}
aub_bo_get_address(bo);
/* Dump the batchbuffer. */
aub_write_trace_block(bo, AUB_TRACE_TYPE_BATCH, 0,
0, used);
aub_write_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
used, bo->size - used);
/* Remove any annotations we added */
if (batch_buffer_needs_annotations)
drm_intel_bufmgr_gem_set_aub_annotations(bo, NULL, 0);
/* Dump ring buffer */
aub_build_dump_ringbuffer(bufmgr_gem, bo_gem->aub_offset, ring_flag);
@ -2723,6 +2769,47 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
}
}
/**
* Annotate the given bo for use in aub dumping.
*
* \param annotations is an array of drm_intel_aub_annotation objects
* describing the type of data in various sections of the bo. Each
* element of the array specifies the type and subtype of a section of
* the bo, and the past-the-end offset of that section. The elements
* of \c annotations must be sorted so that ending_offset is
* increasing.
*
* \param count is the number of elements in the \c annotations array.
* If \c count is zero, then \c annotations will not be dereferenced.
*
* Annotations are copied into a private data structure, so caller may
* re-use the memory pointed to by \c annotations after the call
* returns.
*
* Annotations are stored for the lifetime of the bo; to reset to the
* default state (no annotations), call this function with a \c count
* of zero.
*/
void
drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
drm_intel_aub_annotation *annotations,
unsigned count)
{
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
unsigned size = sizeof(*annotations) * count;
drm_intel_aub_annotation *new_annotations =
count > 0 ? realloc(bo_gem->aub_annotations, size) : NULL;
if (new_annotations == NULL) {
free(bo_gem->aub_annotations);
bo_gem->aub_annotations = NULL;
bo_gem->aub_annotation_count = 0;
return;
}
memcpy(new_annotations, annotations, size);
bo_gem->aub_annotations = new_annotations;
bo_gem->aub_annotation_count = count;
}
/**
* Initializes the GEM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.