llvmpipe: Implement PIPE_QUERY_TIMESTAMP and PIPE_QUERY_TIME_ELAPSED.

This required an update for the query storage in llvmpipe, there
can now be an active query per query type, so an occlusion query
can run at the same time as a time elapsed query.

Based on PIPE_QUERY_TIME_ELAPSED patch from Dave Airlie.

v2: fix up piglits for timers (also from Dave Airlie)

a) if we don't render anything the result is 0, so just
return the current time

b) add missing screen get_timestamp callback.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: José Fonseca <jfonseca@vmware.com>
This commit is contained in:
James Benton
2012-12-03 07:00:37 +00:00
committed by José Fonseca
parent 041966801e
commit 16f0d70ffe
13 changed files with 147 additions and 43 deletions
+15
View File
@@ -36,6 +36,7 @@
#include "pipe/p_config.h"
#if defined(PIPE_OS_UNIX)
# include <time.h> /* timeval */
# include <sys/time.h> /* timeval */
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <windows.h>
@@ -68,6 +69,20 @@ os_time_get(void)
}
uint64_t
os_time_get_nano(void)
{
#if defined(PIPE_OS_UNIX)
struct timespec tv;
clock_gettime(CLOCK_REALTIME, &tv);
return tv.tv_nsec + tv.tv_sec * 1000000000LL;
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
return os_time_get() * 1000;
#endif
}
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
void
+7
View File
@@ -57,6 +57,13 @@ int64_t
os_time_get(void);
/*
* Get the current time in nanoseconds from an unknown base.
*/
uint64_t
os_time_get_nano(void);
/*
* Sleep.
*/
+1 -1
View File
@@ -96,7 +96,7 @@ struct llvmpipe_context {
unsigned dirty; /**< Mask of LP_NEW_x flags */
int active_query_count;
unsigned active_occlusion_query;
/** Mapped vertex buffers */
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
+42 -9
View File
@@ -33,6 +33,7 @@
#include "draw/draw_context.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "os/os_time.h"
#include "lp_context.h"
#include "lp_flush.h"
#include "lp_fence.h"
@@ -51,10 +52,14 @@ llvmpipe_create_query(struct pipe_context *pipe,
{
struct llvmpipe_query *pq;
assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
assert(type < PIPE_QUERY_TYPES);
pq = CALLOC_STRUCT( llvmpipe_query );
if (pq) {
pq->type = type;
}
return (struct pipe_query *) pq;
}
@@ -100,7 +105,7 @@ llvmpipe_get_query_result(struct pipe_context *pipe,
if (!lp_fence_signalled(pq->fence)) {
if (!lp_fence_issued(pq->fence))
llvmpipe_flush(pipe, NULL, __FUNCTION__);
if (!wait)
return FALSE;
@@ -110,8 +115,32 @@ llvmpipe_get_query_result(struct pipe_context *pipe,
/* Sum the results from each of the threads:
*/
*result = 0;
for (i = 0; i < LP_MAX_THREADS; i++) {
*result += pq->count[i];
switch (pq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
for (i = 0; i < LP_MAX_THREADS; i++) {
*result += pq->count[i];
}
break;
case PIPE_QUERY_TIME_ELAPSED:
for (i = 0; i < LP_MAX_THREADS; i++) {
if (pq->count[i] > *result) {
*result = pq->count[i];
}
}
break;
case PIPE_QUERY_TIMESTAMP:
for (i = 0; i < LP_MAX_THREADS; i++) {
if (pq->count[i] > *result) {
*result = pq->count[i];
}
if (*result == 0)
*result = os_time_get_nano();
}
break;
default:
assert(0);
break;
}
return TRUE;
@@ -136,8 +165,10 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
memset(pq->count, 0, sizeof(pq->count));
lp_setup_begin_query(llvmpipe->setup, pq);
llvmpipe->active_query_count++;
llvmpipe->dirty |= LP_NEW_QUERY;
if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) {
llvmpipe->active_occlusion_query = TRUE;
llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
}
}
@@ -149,9 +180,11 @@ llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
lp_setup_end_query(llvmpipe->setup, pq);
assert(llvmpipe->active_query_count);
llvmpipe->active_query_count--;
llvmpipe->dirty |= LP_NEW_QUERY;
if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) {
assert(llvmpipe->active_occlusion_query);
llvmpipe->active_occlusion_query = FALSE;
llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
}
}
boolean
+3 -2
View File
@@ -42,8 +42,9 @@ struct llvmpipe_context;
struct llvmpipe_query {
uint64_t count[LP_MAX_THREADS]; /**< a counter for each thread */
struct lp_fence *fence; /* fence from last scene this was binned in */
uint64_t count[LP_MAX_THREADS]; /* a counter for each thread */
struct lp_fence *fence; /* fence from last scene this was binned in */
unsigned type; /* PIPE_QUERY_* */
};
+43 -10
View File
@@ -32,6 +32,8 @@
#include "util/u_surface.h"
#include "util/u_pack_color.h"
#include "os/os_time.h"
#include "lp_scene_queue.h"
#include "lp_debug.h"
#include "lp_fence.h"
@@ -429,9 +431,21 @@ lp_rast_begin_query(struct lp_rasterizer_task *task,
{
struct llvmpipe_query *pq = arg.query_obj;
assert(task->query == NULL);
task->vis_counter = 0;
task->query = pq;
assert(task->query[pq->type] == NULL);
switch (pq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
task->vis_counter = 0;
break;
case PIPE_QUERY_TIME_ELAPSED:
task->query_start = os_time_get_nano();
break;
default:
assert(0);
break;
}
task->query[pq->type] = pq;
}
@@ -444,10 +458,26 @@ static void
lp_rast_end_query(struct lp_rasterizer_task *task,
const union lp_rast_cmd_arg arg)
{
assert(task->query);
if (task->query) {
task->query->count[task->thread_index] += task->vis_counter;
task->query = NULL;
struct llvmpipe_query *pq = arg.query_obj;
assert(task->query[pq->type] == pq || pq->type == PIPE_QUERY_TIMESTAMP);
switch (pq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
pq->count[task->thread_index] += task->vis_counter;
break;
case PIPE_QUERY_TIME_ELAPSED:
pq->count[task->thread_index] = os_time_get_nano() - task->query_start;
break;
case PIPE_QUERY_TIMESTAMP:
pq->count[task->thread_index] = os_time_get_nano();
break;
default:
assert(0);
break;
}
if (task->query[pq->type] == pq) {
task->query[pq->type] = NULL;
}
}
@@ -467,9 +497,12 @@ lp_rast_set_state(struct lp_rasterizer_task *task,
static void
lp_rast_tile_end(struct lp_rasterizer_task *task)
{
if (task->query) {
union lp_rast_cmd_arg dummy = {0};
lp_rast_end_query(task, dummy);
unsigned i;
for (i = 0; i < PIPE_QUERY_TYPES; ++i) {
if (task->query[i]) {
lp_rast_end_query(task, lp_rast_arg_query(task->query[i]));
}
}
/* debug */
+2 -1
View File
@@ -96,7 +96,8 @@ struct lp_rasterizer_task
/* occlude counter for visiable pixels */
uint32_t vis_counter;
struct llvmpipe_query *query;
uint64_t query_start;
struct llvmpipe_query *query[PIPE_QUERY_TYPES];
pipe_semaphore work_ready;
pipe_semaphore work_done;
+10 -3
View File
@@ -37,6 +37,7 @@
#include "draw/draw_context.h"
#include "gallivm/lp_bld_type.h"
#include "os/os_time.h"
#include "lp_texture.h"
#include "lp_fence.h"
#include "lp_jit.h"
@@ -126,7 +127,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_TIMER_QUERY:
return 0;
case PIPE_CAP_QUERY_TIMESTAMP:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
@@ -210,7 +212,6 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 16;
case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_QUERY_TIMESTAMP:
case PIPE_CAP_TEXTURE_MULTISAMPLE:
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
case PIPE_CAP_CUBE_MAP_ARRAY:
@@ -446,7 +447,11 @@ llvmpipe_fence_finish(struct pipe_screen *screen,
return TRUE;
}
static uint64_t
llvmpipe_get_timestamp(struct pipe_screen *_screen)
{
return os_time_get_nano();
}
/**
* Create a new pipe_screen object
@@ -491,6 +496,8 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
screen->base.fence_signalled = llvmpipe_fence_signalled;
screen->base.fence_finish = llvmpipe_fence_finish;
screen->base.get_timestamp = llvmpipe_get_timestamp;
llvmpipe_init_screen_resource_funcs(&screen->base);
lp_jit_screen_init(screen);
+20 -13
View File
@@ -232,12 +232,14 @@ begin_binning( struct lp_setup_context *setup )
}
}
if (setup->active_query) {
ok = lp_scene_bin_everywhere( scene,
LP_RAST_OP_BEGIN_QUERY,
lp_rast_arg_query(setup->active_query) );
if (!ok)
return FALSE;
for (i = 0; i < PIPE_QUERY_TYPES; ++i) {
if (setup->active_query[i]) {
ok = lp_scene_bin_everywhere( scene,
LP_RAST_OP_BEGIN_QUERY,
lp_rast_arg_query(setup->active_query[i]) );
if (!ok)
return FALSE;
}
}
setup->clear.flags = 0;
@@ -1116,11 +1118,16 @@ lp_setup_begin_query(struct lp_setup_context *setup,
struct llvmpipe_query *pq)
{
/* init the query to its beginning state */
assert(setup->active_query == NULL);
assert(setup->active_query[pq->type] == NULL);
set_scene_state(setup, SETUP_ACTIVE, "begin_query");
setup->active_query = pq;
setup->active_query[pq->type] = pq;
/* XXX: It is possible that a query is created before the scene
* has been created. This means that setup->scene == NULL resulting
* in the query not being binned and thus is ignored.
*/
if (setup->scene) {
if (!lp_scene_bin_everywhere(setup->scene,
@@ -1146,12 +1153,12 @@ lp_setup_begin_query(struct lp_setup_context *setup,
void
lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
{
union lp_rast_cmd_arg dummy = { 0 };
set_scene_state(setup, SETUP_ACTIVE, "end_query");
assert(setup->active_query == pq);
setup->active_query = NULL;
if (pq->type != PIPE_QUERY_TIMESTAMP) {
assert(setup->active_query[pq->type] == pq);
setup->active_query[pq->type] = NULL;
}
/* Setup will automatically re-issue any query which carried over a
* scene boundary, and the rasterizer automatically "ends" queries
@@ -1166,7 +1173,7 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
if (!lp_scene_bin_everywhere(setup->scene,
LP_RAST_OP_END_QUERY,
dummy)) {
lp_rast_arg_query(pq))) {
lp_setup_flush(setup, NULL, __FUNCTION__);
}
}
@@ -89,7 +89,7 @@ struct lp_setup_context
struct lp_scene *scene; /**< current scene being built */
struct lp_fence *last_fence;
struct llvmpipe_query *active_query;
struct llvmpipe_query *active_query[PIPE_QUERY_TYPES];
boolean flatshade_first;
boolean ccw_is_frontface;
+1 -1
View File
@@ -51,7 +51,7 @@
#define LP_NEW_SAMPLER_VIEW 0x800
#define LP_NEW_VERTEX 0x1000
#define LP_NEW_VS 0x2000
#define LP_NEW_QUERY 0x4000
#define LP_NEW_OCCLUSION_QUERY 0x4000
#define LP_NEW_BLEND_COLOR 0x8000
#define LP_NEW_GS 0x10000
#define LP_NEW_SO 0x20000
@@ -152,7 +152,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
LP_NEW_RASTERIZER |
LP_NEW_SAMPLER |
LP_NEW_SAMPLER_VIEW |
LP_NEW_QUERY))
LP_NEW_OCCLUSION_QUERY))
llvmpipe_update_fs( llvmpipe );
if (llvmpipe->dirty & (LP_NEW_FS |
+1 -1
View File
@@ -2493,7 +2493,7 @@ make_variant_key(struct llvmpipe_context *lp,
/* alpha.ref_value is passed in jit_context */
key->flatshade = lp->rasterizer->flatshade;
if (lp->active_query_count) {
if (lp->active_occlusion_query) {
key->occlusion_count = TRUE;
}