Commit 2e1cfcc4 authored by Charmaine Lee's avatar Charmaine Lee Committed by Brian Paul

svga: add guest statistic gathering interface

With this patch, guest statistic gathering interface is added to
svga winsys interface that can be used to gather svga driver
statistic. The winsys module can then share the statistic info with
the VMX host via the mksstats interface.

The statistic enums used in the svga driver are defined in
svga_stats_count and svga_stats_time in svga_winsys.h
Reviewed-by: Brian Paul's avatarBrian Paul <brianp@vmware.com>
parent 47919918
......@@ -307,6 +307,8 @@ void svga_context_flush( struct svga_context *svga,
struct pipe_fence_handle *fence = NULL;
uint64_t t0;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CONTEXTFLUSH);
svga->curr.nr_fbs = 0;
/* Ensure that texture dma uploads are processed
......@@ -355,6 +357,8 @@ void svga_context_flush( struct svga_context *svga,
svgascreen->sws->fence_reference(svgascreen->sws, pfence, fence);
svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL);
SVGA_STATS_TIME_POP(svga_sws(svga));
}
......@@ -413,6 +417,8 @@ void svga_surfaces_flush(struct svga_context *svga)
struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
unsigned i;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_SURFACEFLUSH);
/* Emit buffered drawing commands.
*/
svga_hwtnl_flush_retry( svga );
......@@ -427,6 +433,7 @@ void svga_surfaces_flush(struct svga_context *svga)
if (svga->curr.framebuffer.zsbuf)
svga_propagate_surface(svga, svga->curr.framebuffer.zsbuf);
SVGA_STATS_TIME_POP(svga_sws(svga));
}
......
......@@ -676,6 +676,11 @@ svga_context( struct pipe_context *pipe )
return (struct svga_context *)pipe;
}
static inline struct svga_winsys_screen *
svga_sws(struct svga_context *svga)
{
return svga_screen(svga->pipe.screen)->sws;
}
static inline boolean
svga_have_gb_objects(const struct svga_context *svga)
......
......@@ -703,11 +703,17 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
enum pipe_error
svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
{
enum pipe_error ret = PIPE_OK;
SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLFLUSH);
if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) {
/* we only queue up primitive for VGPU9 */
return draw_vgpu9(hwtnl);
ret = draw_vgpu9(hwtnl);
}
return PIPE_OK;
SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws);
return ret;
}
......@@ -881,6 +887,8 @@ svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
{
enum pipe_error ret = PIPE_OK;
SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLPRIM);
if (svga_have_vgpu10(hwtnl->svga)) {
/* draw immediately */
ret = draw_vgpu10(hwtnl, range, vcount, min_index, max_index, ib,
......@@ -905,7 +913,7 @@ svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
if (hwtnl->cmd.prim_count + 1 >= QSZ) {
ret = svga_hwtnl_flush(hwtnl);
if (ret != PIPE_OK)
return ret;
goto done;
}
/* min/max indices are relative to bias */
......@@ -919,5 +927,7 @@ svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
hwtnl->cmd.prim_count++;
}
done:
SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws);
return ret;
}
......@@ -100,6 +100,8 @@ retrieve_or_generate_indices(struct svga_hwtnl *hwtnl,
enum pipe_error ret = PIPE_OK;
int i;
SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_GENERATEINDICES);
for (i = 0; i < IDX_CACHE_MAX; i++) {
if (hwtnl->index_cache[prim][i].buffer != NULL &&
hwtnl->index_cache[prim][i].generate == generate) {
......@@ -110,7 +112,7 @@ retrieve_or_generate_indices(struct svga_hwtnl *hwtnl,
if (DBG)
debug_printf("%s retrieve %d/%d\n", __FUNCTION__, i, gen_nr);
return PIPE_OK;
goto done;
}
else if (gen_type == U_GENERATE_REUSABLE) {
pipe_resource_reference(&hwtnl->index_cache[prim][i].buffer,
......@@ -154,7 +156,7 @@ retrieve_or_generate_indices(struct svga_hwtnl *hwtnl,
ret = generate_indices(hwtnl, gen_nr, gen_size, generate, out_buf);
if (ret != PIPE_OK)
return ret;
goto done;
hwtnl->index_cache[prim][i].generate = generate;
hwtnl->index_cache[prim][i].gen_nr = gen_nr;
......@@ -164,7 +166,9 @@ retrieve_or_generate_indices(struct svga_hwtnl *hwtnl,
debug_printf("%s cache %d/%d\n", __FUNCTION__,
i, hwtnl->index_cache[prim][i].gen_nr);
return PIPE_OK;
done:
SVGA_STATS_TIME_POP(svga_sws(hwtnl->svga));
return ret;
}
......@@ -213,6 +217,8 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
unsigned api_pv = hwtnl->api_pv;
struct svga_context *svga = hwtnl->svga;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_HWTNLDRAWARRAYS);
if (svga->curr.rast->templ.fill_front !=
svga->curr.rast->templ.fill_back) {
assert(hwtnl->api_fillmode == PIPE_POLYGON_MODE_FILL);
......@@ -266,7 +272,7 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
}
if (gen_type == U_GENERATE_LINEAR) {
return simple_draw_arrays(hwtnl, gen_prim, start, count,
ret = simple_draw_arrays(hwtnl, gen_prim, start, count,
start_instance, instance_count);
}
else {
......@@ -296,13 +302,11 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
gen_prim, 0, gen_nr,
start_instance,
instance_count);
if (ret != PIPE_OK)
goto done;
done:
if (gen_buf)
pipe_resource_reference(&gen_buf, NULL);
return ret;
}
SVGA_STATS_TIME_POP(svga_sws(svga));
return ret;
}
......@@ -139,6 +139,9 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
u_translate_func gen_func;
enum pipe_error ret = PIPE_OK;
SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga),
SVGA_STATS_TIME_HWTNLDRAWELEMENTS);
if (svga_need_unfilled_fallback(hwtnl, prim)) {
gen_type = u_unfilled_translator(prim,
index_size,
......@@ -161,7 +164,7 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
if (gen_type == U_TRANSLATE_MEMCPY) {
/* No need for translation, just pass through to hardware:
*/
return svga_hwtnl_simple_draw_range_elements(hwtnl, index_buffer,
ret = svga_hwtnl_simple_draw_range_elements(hwtnl, index_buffer,
index_size,
index_bias,
min_index,
......@@ -196,13 +199,11 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
gen_prim, 0, gen_nr,
start_instance,
instance_count);
if (ret != PIPE_OK)
goto done;
done:
if (gen_buf)
pipe_resource_reference(&gen_buf, NULL);
return ret;
}
SVGA_STATS_TIME_POP(svga_sws(hwtnl->svga));
return ret;
}
......@@ -334,6 +334,8 @@ svga_create_blend_state(struct pipe_context *pipe,
}
svga->hud.num_blend_objects++;
SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
SVGA_STATS_COUNT_BLENDSTATE);
return blend;
}
......
......@@ -206,6 +206,9 @@ svga_create_depth_stencil_state(struct pipe_context *pipe,
svga->hud.num_depthstencil_objects++;
SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
SVGA_STATS_COUNT_DEPTHSTENCILSTATE);
return ds;
}
......
......@@ -59,6 +59,8 @@ retry_draw_range_elements( struct svga_context *svga,
{
enum pipe_error ret = PIPE_OK;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS);
svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
......@@ -81,20 +83,22 @@ retry_draw_range_elements( struct svga_context *svga,
if (ret != PIPE_OK)
goto retry;
return PIPE_OK;
goto done;
retry:
svga_context_flush( svga, NULL );
if (do_retry)
{
return retry_draw_range_elements( svga,
index_buffer, index_size, index_bias,
min_index, max_index,
prim, start, count,
start_instance, instance_count, FALSE );
ret = retry_draw_range_elements(svga,
index_buffer, index_size, index_bias,
min_index, max_index,
prim, start, count,
start_instance, instance_count, FALSE);
}
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
return ret;
}
......@@ -107,6 +111,8 @@ retry_draw_arrays( struct svga_context *svga,
{
enum pipe_error ret;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWARRAYS);
svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
......@@ -126,18 +132,20 @@ retry_draw_arrays( struct svga_context *svga,
if (ret != PIPE_OK)
goto retry;
return PIPE_OK;
goto done;
retry:
if (ret == PIPE_ERROR_OUT_OF_MEMORY && do_retry)
{
svga_context_flush( svga, NULL );
return retry_draw_arrays(svga, prim, start, count,
start_instance, instance_count,
FALSE );
ret = retry_draw_arrays(svga, prim, start, count,
start_instance, instance_count,
FALSE);
}
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
return ret;
}
......@@ -177,11 +185,13 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
enum pipe_error ret = 0;
boolean needed_swtnl;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWVBO);
svga->hud.num_draw_calls++; /* for SVGA_QUERY_NUM_DRAW_CALLS */
if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES &&
svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK)
return;
goto done;
/*
* Mark currently bound target surfaces as dirty
......@@ -202,11 +212,11 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
r = util_draw_vbo_without_prim_restart(pipe, &svga->curr.ib, info);
assert(r == PIPE_OK);
(void) r;
return;
goto done;
}
if (!u_trim_pipe_prim( info->mode, &count ))
return;
goto done;
needed_swtnl = svga->state.sw.need_swtnl;
......@@ -215,7 +225,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
#ifdef DEBUG
if (svga->curr.vs->base.id == svga->debug.disable_shader ||
svga->curr.fs->base.id == svga->debug.disable_shader)
return;
goto done;
#endif
if (svga->state.sw.need_swtnl) {
......@@ -270,6 +280,10 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
svga_hwtnl_flush_retry( svga );
svga_context_flush(svga, NULL);
}
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
;
}
......
......@@ -48,6 +48,8 @@ svga_create_fs_state(struct pipe_context *pipe,
if (!fs)
return NULL;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATEFS);
fs->base.tokens = tgsi_dup_tokens(templ->tokens);
/* Collect basic info that we'll need later:
......@@ -62,6 +64,7 @@ svga_create_fs_state(struct pipe_context *pipe,
fs->draw_shader = draw_create_fragment_shader(svga->swtnl.draw, templ);
SVGA_STATS_TIME_POP(svga_sws(svga));
return fs;
}
......
......@@ -46,6 +46,8 @@ svga_create_gs_state(struct pipe_context *pipe,
if (!gs)
return NULL;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATEGS);
gs->base.tokens = tgsi_dup_tokens(templ->tokens);
/* Collect basic info that we'll need later:
......@@ -64,6 +66,7 @@ svga_create_gs_state(struct pipe_context *pipe,
&templ->stream_output);
}
SVGA_STATS_TIME_POP(svga_sws(svga));
return gs;
}
......
......@@ -365,6 +365,8 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
}
svga->hud.num_rasterizer_objects++;
SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
SVGA_STATS_COUNT_RASTERIZERSTATE);
return rast;
}
......
......@@ -277,6 +277,8 @@ svga_create_sampler_state(struct pipe_context *pipe,
cso->mipfilter == SVGA3D_TEX_FILTER_NONE ? "SVGA3D_TEX_FILTER_NONE" : "SOMETHING");
svga->hud.num_sampler_objects++;
SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
SVGA_STATS_COUNT_SAMPLER);
return cso;
}
......@@ -367,6 +369,8 @@ svga_create_sampler_view(struct pipe_context *pipe,
sv->id = SVGA3D_INVALID_ID;
svga->hud.num_samplerview_objects++;
SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
SVGA_STATS_COUNT_SAMPLERVIEW);
return &sv->base;
}
......@@ -433,6 +437,8 @@ svga_set_sampler_views(struct pipe_context *pipe,
if (!svga_have_vgpu10(svga) && shader != PIPE_SHADER_FRAGMENT)
return;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_SETSAMPLERVIEWS);
/* This bit of code works around a quirk in the CSO module.
* If start=num=0 it means all sampler views should be released.
* Note that the CSO module treats sampler views for fragment shaders
......@@ -475,7 +481,7 @@ svga_set_sampler_views(struct pipe_context *pipe,
}
if (!any_change) {
return;
goto done;
}
/* find highest non-null sampler_views[] entry */
......@@ -527,6 +533,9 @@ svga_set_sampler_views(struct pipe_context *pipe,
}
}
}
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
}
......
......@@ -276,6 +276,8 @@ svga_create_vertex_elements_state(struct pipe_context *pipe,
}
svga->hud.num_vertexelement_objects++;
SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
SVGA_STATS_COUNT_VERTEXELEMENT);
return velems;
}
......
......@@ -104,6 +104,8 @@ svga_create_vs_state(struct pipe_context *pipe,
if (!vs)
return NULL;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATEVS);
/* substitute a debug shader?
*/
vs->base.tokens = tgsi_dup_tokens(substitute_vs(svga->debug.shader_id,
......@@ -132,6 +134,7 @@ svga_create_vs_state(struct pipe_context *pipe,
&templ->stream_output);
}
SVGA_STATS_TIME_POP(svga_sws(svga));
return vs;
}
......
......@@ -76,9 +76,11 @@ svga_buffer_transfer_map(struct pipe_context *pipe,
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_buffer *sbuf = svga_buffer(resource);
struct pipe_transfer *transfer;
uint8_t *map;
uint8_t *map = NULL;
int64_t begin = svga_get_time(svga);
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERTRANSFERMAP);
assert(box->y == 0);
assert(box->z == 0);
assert(box->height == 1);
......@@ -86,7 +88,7 @@ svga_buffer_transfer_map(struct pipe_context *pipe,
transfer = MALLOC_STRUCT(pipe_transfer);
if (!transfer) {
return NULL;
goto done;
}
transfer->resource = resource;
......@@ -203,7 +205,7 @@ svga_buffer_transfer_map(struct pipe_context *pipe,
*/
FREE(transfer);
return NULL;
goto done;
}
svga_context_flush(svga, NULL);
......@@ -230,7 +232,7 @@ svga_buffer_transfer_map(struct pipe_context *pipe,
sbuf->swbuf = align_malloc(sbuf->b.b.width0, 16);
if (!sbuf->swbuf) {
FREE(transfer);
return NULL;
goto done;
}
}
}
......@@ -267,6 +269,8 @@ svga_buffer_transfer_map(struct pipe_context *pipe,
svga->hud.map_buffer_time += (svga_get_time(svga) - begin);
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
return map;
}
......@@ -299,6 +303,8 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe,
struct svga_context *svga = svga_context(pipe);
struct svga_buffer *sbuf = svga_buffer(transfer->resource);
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERTRANSFERUNMAP);
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.count);
......@@ -328,6 +334,7 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe,
pipe_mutex_unlock(ss->swc_mutex);
FREE(transfer);
SVGA_STATS_TIME_POP(svga_sws(svga));
}
......@@ -381,6 +388,8 @@ svga_buffer_create(struct pipe_screen *screen,
struct svga_screen *ss = svga_screen(screen);
struct svga_buffer *sbuf;
SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATEBUFFER);
sbuf = CALLOC_STRUCT(svga_buffer);
if (!sbuf)
goto error1;
......@@ -437,12 +446,14 @@ svga_buffer_create(struct pipe_screen *screen,
ss->hud.total_resource_bytes += sbuf->size;
ss->hud.num_resources++;
SVGA_STATS_TIME_POP(ss->sws);
return &sbuf->b.b;
error2:
FREE(sbuf);
error1:
SVGA_STATS_TIME_POP(ss->sws);
return NULL;
}
......
......@@ -835,6 +835,8 @@ svga_context_flush_buffers(struct svga_context *svga)
{
struct list_head *curr, *next;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERSFLUSH);
curr = svga->dirty_buffers.next;
next = curr->next;
while (curr != &svga->dirty_buffers) {
......@@ -848,4 +850,6 @@ svga_context_flush_buffers(struct svga_context *svga)
curr = next;
next = curr->next;
}
SVGA_STATS_TIME_POP(svga_sws(svga));
}
......@@ -334,20 +334,22 @@ svga_texture_transfer_map(struct pipe_context *pipe,
boolean use_direct_map = svga_have_gb_objects(svga) &&
!svga_have_gb_dma(svga);
unsigned d;
void *returnVal;
void *returnVal = NULL;
int64_t begin = svga_get_time(svga);
SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_TEXTRANSFERMAP);
/* We can't map texture storage directly unless we have GB objects */
if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
if (svga_have_gb_objects(svga))
use_direct_map = TRUE;
else
return NULL;
goto done;
}
st = CALLOC_STRUCT(svga_transfer);
if (!st)
return NULL;
goto done;
st->base.level = level;
st->base.usage = usage;
......@@ -415,7 +417,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
if (!st->hwbuf) {
FREE(st);
return NULL;
goto done;
}
if (st->hw_nblocksy < nblocksy) {
......@@ -434,7 +436,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
if (!st->swbuf) {
sws->buffer_destroy(sws, st->hwbuf);
FREE(st);
return NULL;
goto done;
}
}
......@@ -449,7 +451,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
if (!surf) {
FREE(st);
return NULL;
goto done;
}
/* If this is the first time mapping to the surface in this
......@@ -472,6 +474,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
}