gallium/hud: add HUD sharing within a context share group
This is needed for profiling multi-context applications like Chrome. One context can record queries and another context can draw the HUD. Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
parent
11e25eb7f4
commit
bd57f45168
|
@ -680,12 +680,45 @@ hud_stop_queries(struct hud_context *hud, struct pipe_context *pipe)
|
||||||
u_upload_unmap(pipe->stream_uploader);
|
u_upload_unmap(pipe->stream_uploader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record queries and draw the HUD. The "cso" parameter acts as a filter.
|
||||||
|
* If "cso" is not the recording context, recording is skipped.
|
||||||
|
* If "cso" is not the drawing context, drawing is skipped.
|
||||||
|
* cso == NULL ignores the filter.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
hud_run(struct hud_context *hud, struct cso_context *cso,
|
hud_run(struct hud_context *hud, struct cso_context *cso,
|
||||||
struct pipe_resource *tex)
|
struct pipe_resource *tex)
|
||||||
{
|
{
|
||||||
|
struct pipe_context *pipe = cso ? cso_get_pipe_context(cso) : NULL;
|
||||||
|
|
||||||
|
/* If "cso" is the recording or drawing context or NULL, execute
|
||||||
|
* the operation. Otherwise, don't do anything.
|
||||||
|
*/
|
||||||
|
if (hud->record_pipe && (!pipe || pipe == hud->record_pipe))
|
||||||
hud_stop_queries(hud, hud->record_pipe);
|
hud_stop_queries(hud, hud->record_pipe);
|
||||||
|
|
||||||
|
if (hud->cso && (!cso || cso == hud->cso))
|
||||||
hud_draw_results(hud, tex);
|
hud_draw_results(hud, tex);
|
||||||
|
|
||||||
|
if (hud->record_pipe && (!pipe || pipe == hud->record_pipe))
|
||||||
|
hud_start_queries(hud, hud->record_pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record query results and assemble vertices if "pipe" is a recording but
|
||||||
|
* not drawing context.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hud_record_only(struct hud_context *hud, struct pipe_context *pipe)
|
||||||
|
{
|
||||||
|
assert(pipe);
|
||||||
|
|
||||||
|
/* If it's a drawing context, only hud_run() records query results. */
|
||||||
|
if (pipe == hud->pipe || pipe != hud->record_pipe)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hud_stop_queries(hud, hud->record_pipe);
|
||||||
hud_start_queries(hud, hud->record_pipe);
|
hud_start_queries(hud, hud->record_pipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1684,9 +1717,46 @@ hud_set_record_context(struct hud_context *hud, struct pipe_context *pipe)
|
||||||
hud->record_pipe = pipe;
|
hud->record_pipe = pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the HUD.
|
||||||
|
*
|
||||||
|
* If "share" is non-NULL and GALLIUM_HUD_SHARE=x,y is set, increment the
|
||||||
|
* reference counter of "share", set "cso" as the recording or drawing context
|
||||||
|
* according to the environment variable, and return "share".
|
||||||
|
* This allows sharing the HUD instance within a multi-context share group,
|
||||||
|
* record queries in one context and draw them in another.
|
||||||
|
*/
|
||||||
struct hud_context *
|
struct hud_context *
|
||||||
hud_create(struct cso_context *cso, struct hud_context *share)
|
hud_create(struct cso_context *cso, struct hud_context *share)
|
||||||
{
|
{
|
||||||
|
const char *share_env = debug_get_option("GALLIUM_HUD_SHARE", NULL);
|
||||||
|
unsigned record_ctx = 0, draw_ctx = 0;
|
||||||
|
|
||||||
|
if (share_env && sscanf(share_env, "%u,%u", &record_ctx, &draw_ctx) != 2)
|
||||||
|
share_env = NULL;
|
||||||
|
|
||||||
|
if (share && share_env) {
|
||||||
|
/* All contexts in a share group share the HUD instance.
|
||||||
|
* Only one context can record queries and only one context
|
||||||
|
* can draw the HUD.
|
||||||
|
*
|
||||||
|
* GALLIUM_HUD_SHARE=x,y determines the context indices.
|
||||||
|
*/
|
||||||
|
int context_id = p_atomic_inc_return(&share->refcount) - 1;
|
||||||
|
|
||||||
|
if (context_id == record_ctx) {
|
||||||
|
assert(!share->record_pipe);
|
||||||
|
hud_set_record_context(share, cso_get_pipe_context(cso));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context_id == draw_ctx) {
|
||||||
|
assert(!share->pipe);
|
||||||
|
hud_set_draw_context(share, cso);
|
||||||
|
}
|
||||||
|
|
||||||
|
return share;
|
||||||
|
}
|
||||||
|
|
||||||
struct pipe_screen *screen = cso_get_pipe_context(cso)->screen;
|
struct pipe_screen *screen = cso_get_pipe_context(cso)->screen;
|
||||||
struct hud_context *hud;
|
struct hud_context *hud;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -1717,6 +1787,7 @@ hud_create(struct cso_context *cso, struct hud_context *share)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hud->refcount = 1;
|
||||||
hud->has_srgb = screen->is_format_supported(screen,
|
hud->has_srgb = screen->is_format_supported(screen,
|
||||||
PIPE_FORMAT_B8G8R8A8_SRGB,
|
PIPE_FORMAT_B8G8R8A8_SRGB,
|
||||||
PIPE_TEXTURE_2D, 0,
|
PIPE_TEXTURE_2D, 0,
|
||||||
|
@ -1763,12 +1834,6 @@ hud_create(struct cso_context *cso, struct hud_context *share)
|
||||||
|
|
||||||
LIST_INITHEAD(&hud->pane_list);
|
LIST_INITHEAD(&hud->pane_list);
|
||||||
|
|
||||||
if (!hud_set_draw_context(hud, cso)) {
|
|
||||||
pipe_resource_reference(&hud->font.texture, NULL);
|
|
||||||
FREE(hud);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup sig handler once for all hud contexts */
|
/* setup sig handler once for all hud contexts */
|
||||||
#ifdef PIPE_OS_UNIX
|
#ifdef PIPE_OS_UNIX
|
||||||
if (!sig_handled && signo != 0) {
|
if (!sig_handled && signo != 0) {
|
||||||
|
@ -1785,18 +1850,32 @@ hud_create(struct cso_context *cso, struct hud_context *share)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (record_ctx == 0)
|
||||||
hud_set_record_context(hud, cso_get_pipe_context(cso));
|
hud_set_record_context(hud, cso_get_pipe_context(cso));
|
||||||
|
if (draw_ctx == 0)
|
||||||
|
hud_set_draw_context(hud, cso);
|
||||||
|
|
||||||
hud_parse_env_var(hud, screen, env);
|
hud_parse_env_var(hud, screen, env);
|
||||||
return hud;
|
return hud;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a HUD. If the HUD has several users, decrease the reference counter
|
||||||
|
* and detach the context from the HUD.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
hud_destroy(struct hud_context *hud, struct cso_context *cso)
|
hud_destroy(struct hud_context *hud, struct cso_context *cso)
|
||||||
{
|
{
|
||||||
|
if (!cso || hud->record_pipe == cso_get_pipe_context(cso))
|
||||||
hud_unset_record_context(hud);
|
hud_unset_record_context(hud);
|
||||||
|
|
||||||
|
if (!cso || hud->cso == cso)
|
||||||
hud_unset_draw_context(hud);
|
hud_unset_draw_context(hud);
|
||||||
|
|
||||||
|
if (p_atomic_dec_zero(&hud->refcount)) {
|
||||||
pipe_resource_reference(&hud->font.texture, NULL);
|
pipe_resource_reference(&hud->font.texture, NULL);
|
||||||
FREE(hud);
|
FREE(hud);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -44,6 +44,9 @@ void
|
||||||
hud_run(struct hud_context *hud, struct cso_context *cso,
|
hud_run(struct hud_context *hud, struct cso_context *cso,
|
||||||
struct pipe_resource *tex);
|
struct pipe_resource *tex);
|
||||||
|
|
||||||
|
void
|
||||||
|
hud_record_only(struct hud_context *hud, struct pipe_context *pipe);
|
||||||
|
|
||||||
void
|
void
|
||||||
hud_add_queue_for_monitoring(struct hud_context *hud,
|
hud_add_queue_for_monitoring(struct hud_context *hud,
|
||||||
struct util_queue_monitoring *queue_info);
|
struct util_queue_monitoring *queue_info);
|
||||||
|
|
|
@ -40,6 +40,8 @@ enum hud_counter {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hud_context {
|
struct hud_context {
|
||||||
|
int refcount;
|
||||||
|
|
||||||
/* Context where queries are executed. */
|
/* Context where queries are executed. */
|
||||||
struct pipe_context *record_pipe;
|
struct pipe_context *record_pipe;
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,10 @@ dri_create_context(gl_api api, const struct gl_config * visual,
|
||||||
&& (ctx_config->release_behavior == __DRI_CTX_RELEASE_BEHAVIOR_NONE))
|
&& (ctx_config->release_behavior == __DRI_CTX_RELEASE_BEHAVIOR_NONE))
|
||||||
attribs.flags |= ST_CONTEXT_FLAG_RELEASE_NONE;
|
attribs.flags |= ST_CONTEXT_FLAG_RELEASE_NONE;
|
||||||
|
|
||||||
|
struct dri_context *share_ctx = NULL;
|
||||||
if (sharedContextPrivate) {
|
if (sharedContextPrivate) {
|
||||||
st_share = ((struct dri_context *)sharedContextPrivate)->st;
|
share_ctx = (struct dri_context *)sharedContextPrivate;
|
||||||
|
st_share = share_ctx->st;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = CALLOC_STRUCT(dri_context);
|
ctx = CALLOC_STRUCT(dri_context);
|
||||||
|
@ -168,7 +170,8 @@ dri_create_context(gl_api api, const struct gl_config * visual,
|
||||||
|
|
||||||
if (ctx->st->cso_context) {
|
if (ctx->st->cso_context) {
|
||||||
ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context);
|
ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context);
|
||||||
ctx->hud = hud_create(ctx->st->cso_context, NULL);
|
ctx->hud = hud_create(ctx->st->cso_context,
|
||||||
|
share_ctx ? share_ctx->hud : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do this last. */
|
/* Do this last. */
|
||||||
|
@ -222,6 +225,7 @@ dri_destroy_context(__DRIcontext * cPriv)
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is called inside MakeCurrent to unbind the context. */
|
||||||
GLboolean
|
GLboolean
|
||||||
dri_unbind_context(__DRIcontext * cPriv)
|
dri_unbind_context(__DRIcontext * cPriv)
|
||||||
{
|
{
|
||||||
|
@ -236,6 +240,10 @@ dri_unbind_context(__DRIcontext * cPriv)
|
||||||
if (st->thread_finish)
|
if (st->thread_finish)
|
||||||
st->thread_finish(st);
|
st->thread_finish(st);
|
||||||
|
|
||||||
|
/* Record HUD queries for the duration the context was "current". */
|
||||||
|
if (ctx->hud)
|
||||||
|
hud_record_only(ctx->hud, st->pipe);
|
||||||
|
|
||||||
stapi->make_current(stapi, NULL, NULL, NULL);
|
stapi->make_current(stapi, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue