virgl: Add perfetto performance calls conditionally

Author: Tomeu Vizoso <tomeu.vizoso@collabora.com> (v1)
v2: - Include perfetto_min.h only when perf tracing is enabled
    - Make stubs inline code so it can be optimized away.
    - Add compile with tracing info to configuration status
    - Use static for stubs (Chia-I Wu)
    - pass trace option as a string and add defines so that
      other tracing tools cold be accomodated
      (inspired by Chia-I Wu & Tomeu)
    - Use macros to wrap the trace calls

v3: - Use __attribute__((cleanup)) to handle trace_begin/trace_end
      instead of using macros to wrap the calls (Chia-I Wu)
    - remove cpp from language support

v4: - Fix __attribute__ check in meson.build
    - replace TRACE_FUNC macro to not take a paramter
    - move trace initialization to a seperate function
      (all suggestions by Chia-I Wu)

v5: use vsnprintf to avoid buffer overflow (John Bates)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com> (v4)
macos/master
Gert Wollny 4 years ago committed by Gert Wollny
parent 3ebb0ffba4
commit 19d65e83e3
  1. 1
      config.h.meson
  2. 15
      meson.build
  3. 8
      meson_options.txt
  4. 6
      src/meson.build
  5. 41
      src/virgl_util.c
  6. 27
      src/virgl_util.h
  7. 34
      src/virglrenderer.c
  8. 13
      src/vrend_decode.c

@ -7,3 +7,4 @@
#mesondefine HAVE_FUNC_ATTRIBUTE_VISIBILITY
#mesondefine HAVE_EVENTFD_H
#mesondefine HAVE_DLFCN_H
#mesondefine ENABLE_TRACING

@ -82,6 +82,20 @@ m_dep = cc.find_library('m')
conf_data = configuration_data()
conf_data.set('VERSION', '0.8.1')
with_tracing = get_option('tracing')
if with_tracing != 'none'
if not cc.compiles('void f(void* v){}; int main () { void *dummy __attribute__((cleanup (f))) = 0;}')
error('Tracing requires compiler support for __attribute__((cleanup))')
endif
endif
if with_tracing == 'perfetto'
vperfetto_min_dep = dependency('vperfetto_min')
conf_data.set('ENABLE_TRACING', 'TRACE_WITH_PERFETTO')
endif
if cc.has_header('sys/uio.h')
conf_data.set('HAVE_SYS_UIO_H', 1)
endif
@ -199,6 +213,7 @@ lines += 'minigbm_alloc: ' + (with_minigbm_allocation ? 'yes' : 'no' )
lines += ''
lines += 'tests: ' + (with_tests ? 'yes' : 'no' )
lines += 'fuzzer: ' + (with_fuzzer ? 'yes' : 'no' )
lines += 'tracing: ' + with_tracing
indent = ' '
summary = indent + ('\n' + indent).join(lines)

@ -58,3 +58,11 @@ option(
value : 'false',
description : 'enable running unit tests with valgrind'
)
option(
'tracing',
type : 'combo',
value : 'none',
choices : [ 'perfetto', 'none' ],
description : 'enable emitting traces for Perfetto'
)

@ -79,9 +79,13 @@ virgl_depends = [
epoxy_dep,
libdrm_dep,
thread_dep,
m_dep
m_dep,
]
if with_tracing == 'perfetto'
virgl_depends += [vperfetto_min_dep]
endif
virgl_sources += vrend_sources
if have_egl

@ -36,6 +36,17 @@
#include "util/u_pointer.h"
#include <stdarg.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if ENABLE_TRACING == TRACE_WITH_PERFETTO
#include <vperfetto-min.h>
#endif
unsigned hash_func_u32(void *key)
{
intptr_t ip = pointer_to_intptr(key);
@ -98,3 +109,33 @@ void flush_eventfd(int fd)
len = read(fd, &value, sizeof(value));
} while ((len == -1 && errno == EINTR) || len == sizeof(value));
}
#if ENABLE_TRACING == TRACE_WITH_PERFETTO
void trace_init(void)
{
struct vperfetto_min_config config = {
.init_flags = VPERFETTO_INIT_FLAG_USE_SYSTEM_BACKEND,
.filename = NULL,
.shmem_size_hint_kb = 32 * 1024,
};
vperfetto_min_startTracing(&config);
}
char *trace_begin(const char* format, ...)
{
char buffer[1024];
va_list args;
va_start (args, format);
vsnprintf (buffer, sizeof(buffer), format, args);
va_end (args);
vperfetto_min_beginTrackEvent_VMM(buffer);
return (void *)1;
}
void trace_end(char **dummy)
{
(void)dummy;
vperfetto_min_endTrackEvent_VMM();
}
#endif

@ -28,6 +28,13 @@
#include <stdint.h>
#include <stdbool.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define TRACE_WITH_PERFETTO 1
#define BIT(n) (UINT32_C(1) << (n))
static inline bool has_bit(uint32_t mask, uint32_t bit)
@ -54,4 +61,24 @@ int create_eventfd(unsigned int initval);
int write_eventfd(int fd, uint64_t val);
void flush_eventfd(int fd);
#ifdef ENABLE_TRACING
void trace_init(void);
char *trace_begin(const char* format, ...);
void trace_end(char **dummy);
#define TRACE_INIT() trace_init()
#define TRACE_FUNC() \
char *trace_dummy __attribute__((cleanup (trace_end), unused)) = \
trace_begin("%s", __func__)
#define TRACE_SCOPE(FORMAT, ...) \
char *trace_dummy __attribute__((cleanup (trace_end), unused)) = \
trace_begin(FORMAT, __VA_ARGS__)
#else
#define TRACE_INIT()
#define TRACE_FUNC()
#define TRACE_SCOPE(FORMAT, ...)
#endif
#endif /* VIRGL_UTIL_H */

@ -31,6 +31,7 @@
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/u_math.h"
@ -99,11 +100,13 @@ static int virgl_renderer_resource_create_internal(struct virgl_renderer_resourc
int virgl_renderer_resource_create(struct virgl_renderer_resource_create_args *args,
struct iovec *iov, uint32_t num_iovs)
{
TRACE_FUNC();
return virgl_renderer_resource_create_internal(args, iov, num_iovs, NULL);
}
int virgl_renderer_resource_import_eglimage(struct virgl_renderer_resource_create_args *args, void *image)
{
TRACE_FUNC();
return virgl_renderer_resource_create_internal(args, NULL, 0, image);
}
@ -165,6 +168,8 @@ int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char *na
struct virgl_context *ctx;
int ret;
TRACE_FUNC();
/* user context id must be greater than 0 */
if (handle == 0)
return EINVAL;
@ -187,6 +192,7 @@ int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char *na
void virgl_renderer_context_destroy(uint32_t handle)
{
TRACE_FUNC();
virgl_context_remove(handle);
}
@ -194,6 +200,7 @@ int virgl_renderer_submit_cmd(void *buffer,
int ctx_id,
int ndw)
{
TRACE_FUNC();
struct virgl_context *ctx = virgl_context_lookup(ctx_id);
if (!ctx)
return EINVAL;
@ -210,6 +217,8 @@ int virgl_renderer_transfer_write_iov(uint32_t handle,
struct iovec *iovec,
unsigned int iovec_cnt)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(handle);
struct vrend_transfer_info transfer_info;
@ -248,6 +257,7 @@ int virgl_renderer_transfer_read_iov(uint32_t handle, uint32_t ctx_id,
uint64_t offset, struct iovec *iovec,
int iovec_cnt)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(handle);
struct vrend_transfer_info transfer_info;
@ -282,6 +292,7 @@ int virgl_renderer_transfer_read_iov(uint32_t handle, uint32_t ctx_id,
int virgl_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
int num_iovs)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!res)
return EINVAL;
@ -291,6 +302,7 @@ int virgl_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
void virgl_renderer_resource_detach_iov(int res_handle, struct iovec **iov_p, int *num_iovs_p)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!res)
return;
@ -305,16 +317,19 @@ void virgl_renderer_resource_detach_iov(int res_handle, struct iovec **iov_p, in
int virgl_renderer_create_fence(int client_fence_id, uint32_t ctx_id)
{
TRACE_FUNC();
return vrend_renderer_create_fence(client_fence_id, ctx_id);
}
void virgl_renderer_force_ctx_0(void)
{
TRACE_FUNC();
vrend_renderer_force_ctx_0();
}
void virgl_renderer_ctx_attach_resource(int ctx_id, int res_handle)
{
TRACE_FUNC();
struct virgl_context *ctx = virgl_context_lookup(ctx_id);
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!ctx || !res)
@ -324,6 +339,7 @@ void virgl_renderer_ctx_attach_resource(int ctx_id, int res_handle)
void virgl_renderer_ctx_detach_resource(int ctx_id, int res_handle)
{
TRACE_FUNC();
struct virgl_context *ctx = virgl_context_lookup(ctx_id);
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!ctx || !res)
@ -334,6 +350,7 @@ void virgl_renderer_ctx_detach_resource(int ctx_id, int res_handle)
int virgl_renderer_resource_get_info(int res_handle,
struct virgl_renderer_resource_info *info)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!res || !res->pipe_resource)
@ -357,6 +374,7 @@ int virgl_renderer_resource_get_info(int res_handle,
void virgl_renderer_get_cap_set(uint32_t cap_set, uint32_t *max_ver,
uint32_t *max_size)
{
TRACE_FUNC();
switch (cap_set) {
case VIRGL_RENDERER_CAPSET_VIRGL:
case VIRGL_RENDERER_CAPSET_VIRGL2:
@ -372,6 +390,7 @@ void virgl_renderer_get_cap_set(uint32_t cap_set, uint32_t *max_ver,
void virgl_renderer_get_rect(int resource_id, struct iovec *iov, unsigned int num_iovs,
uint32_t offset, int x, int y, int width, int height)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(resource_id);
if (!res || !res->pipe_resource)
return;
@ -439,12 +458,14 @@ void *virgl_renderer_get_cursor_data(uint32_t resource_id, uint32_t *width, uint
void virgl_renderer_poll(void)
{
TRACE_FUNC();
if (state.vrend_initialized)
vrend_renderer_check_fences();
}
void virgl_renderer_cleanup(UNUSED void *cookie)
{
TRACE_FUNC();
if (state.vrend_initialized)
vrend_renderer_prepare_reset();
@ -465,6 +486,9 @@ void virgl_renderer_cleanup(UNUSED void *cookie)
int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cbs)
{
TRACE_INIT();
TRACE_FUNC();
int ret;
/* VIRGL_RENDERER_THREAD_SYNC is a hint and can be silently ignored */
@ -543,6 +567,7 @@ fail:
int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd)
{
TRACE_FUNC();
if (state.winsys_initialized)
return vrend_winsys_get_fd_for_texture(tex_id, fd);
return -1;
@ -550,6 +575,7 @@ int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd)
int virgl_renderer_get_fd_for_texture2(uint32_t tex_id, int *fd, int *stride, int *offset)
{
TRACE_FUNC();
if (state.winsys_initialized)
return vrend_winsys_get_fd_for_texture2(tex_id, fd, stride, offset);
return -1;
@ -557,6 +583,7 @@ int virgl_renderer_get_fd_for_texture2(uint32_t tex_id, int *fd, int *stride, in
void virgl_renderer_reset(void)
{
TRACE_FUNC();
if (state.vrend_initialized)
vrend_renderer_prepare_reset();
@ -572,6 +599,7 @@ void virgl_renderer_reset(void)
int virgl_renderer_get_poll_fd(void)
{
TRACE_FUNC();
if (state.vrend_initialized)
return vrend_renderer_get_poll_fd();
@ -622,6 +650,7 @@ static int virgl_renderer_supported_structures(void *execute_args, uint32_t exec
int virgl_renderer_execute(void *execute_args, uint32_t execute_size)
{
TRACE_FUNC();
struct virgl_renderer_hdr *hdr = execute_args;
if (hdr->stype_version != 0)
return -EINVAL;
@ -638,6 +667,7 @@ int virgl_renderer_execute(void *execute_args, uint32_t execute_size)
int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_create_blob_args *args)
{
TRACE_FUNC();
struct virgl_context *ctx;
struct virgl_context_blob blob;
bool has_host_storage;
@ -719,6 +749,7 @@ int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_cre
int virgl_renderer_resource_map(uint32_t res_handle, void **map, uint64_t *out_size)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!res || !res->pipe_resource)
return -EINVAL;
@ -728,6 +759,7 @@ int virgl_renderer_resource_map(uint32_t res_handle, void **map, uint64_t *out_s
int virgl_renderer_resource_unmap(uint32_t res_handle)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!res || !res->pipe_resource)
return -EINVAL;
@ -737,6 +769,7 @@ int virgl_renderer_resource_unmap(uint32_t res_handle)
int virgl_renderer_resource_get_map_info(uint32_t res_handle, uint32_t *map_info)
{
TRACE_FUNC();
struct virgl_resource *res = virgl_resource_lookup(res_handle);
if (!res || !res->pipe_resource)
return -EINVAL;
@ -768,5 +801,6 @@ virgl_renderer_resource_export_blob(uint32_t res_id, uint32_t *fd_type, int *fd)
int
virgl_renderer_export_fence(uint32_t client_fence_id, int *fd)
{
TRACE_FUNC();
return vrend_renderer_export_fence(client_fence_id, fd);
}

@ -26,6 +26,7 @@
#include <stdio.h>
#include <errno.h>
#include <epoxy/gl.h>
#include <fcntl.h>
#include "util/u_memory.h"
#include "pipe/p_defines.h"
@ -38,6 +39,7 @@
#include "tgsi/tgsi_text.h"
#include "vrend_debug.h"
#include "vrend_tweaks.h"
#include "virgl_util.h"
/* decode side */
#define DECODE_MAX_TOKENS 8000
@ -764,6 +766,8 @@ static int vrend_decode_create_object(struct vrend_decode_ctx *ctx, int length)
VREND_DEBUG(dbg_object, ctx->grctx," CREATE %-18s handle:0x%x len:%d\n",
vrend_get_object_type_name(obj_type), handle, length);
TRACE_SCOPE("CREATE %-18s", vrend_get_object_type_name(obj_type));
switch (obj_type){
case VIRGL_OBJECT_BLEND:
ret = vrend_decode_create_blend(ctx, handle, length);
@ -1466,6 +1470,7 @@ struct virgl_context *vrend_renderer_context_create(uint32_t handle,
static void vrend_decode_ctx_destroy(struct virgl_context *ctx)
{
TRACE_FUNC();
struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
vrend_destroy_context(dctx->grctx);
@ -1475,8 +1480,8 @@ static void vrend_decode_ctx_destroy(struct virgl_context *ctx)
static void vrend_decode_ctx_attach_resource(struct virgl_context *ctx,
struct virgl_resource *res)
{
TRACE_FUNC();
struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
/* in the future, we should import to create the pipe resource */
if (!res->pipe_resource)
return;
@ -1488,6 +1493,7 @@ static void vrend_decode_ctx_attach_resource(struct virgl_context *ctx,
static void vrend_decode_ctx_detach_resource(struct virgl_context *ctx,
struct virgl_resource *res)
{
TRACE_FUNC();
struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
vrend_renderer_detach_res_ctx(dctx->grctx, res->res_id);
}
@ -1497,6 +1503,7 @@ static int vrend_decode_ctx_transfer_3d(struct virgl_context *ctx,
const struct vrend_transfer_info *info,
int transfer_mode)
{
TRACE_FUNC();
struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
return vrend_renderer_transfer_iov(dctx->grctx, res->res_id, info,
transfer_mode);
@ -1507,6 +1514,7 @@ static int vrend_decode_ctx_get_blob(struct virgl_context *ctx,
UNUSED uint32_t blob_flags,
struct virgl_context_blob *blob)
{
TRACE_FUNC();
struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
blob->type = VIRGL_RESOURCE_FD_INVALID;
@ -1520,6 +1528,7 @@ static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,
const void *buffer,
size_t size)
{
TRACE_FUNC();
struct vrend_decode_ctx *gdctx = (struct vrend_decode_ctx *)ctx;
bool bret;
int ret;
@ -1546,6 +1555,8 @@ static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,
VREND_DEBUG(dbg_cmd, gdctx->grctx,"%-4d %-20s len:%d\n",
gdctx->ds->buf_offset, vrend_get_comand_name(header & 0xff), len);
TRACE_SCOPE("%s", vrend_get_comand_name(header & 0xff));
switch (header & 0xff) {
case VIRGL_CCMD_CREATE_OBJECT:
ret = vrend_decode_create_object(gdctx, len);

Loading…
Cancel
Save