diff options
-rw-r--r-- | src/gallium/auxiliary/os/os_time.c | 15 | ||||
-rw-r--r-- | src/gallium/auxiliary/os/os_time.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_query.c | 51 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_query.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.c | 53 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast_priv.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_screen.c | 13 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_derived.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.c | 2 |
13 files changed, 147 insertions, 43 deletions
diff --git a/src/gallium/auxiliary/os/os_time.c b/src/gallium/auxiliary/os/os_time.c index 3e9d50a598a..40551252b25 100644 --- a/src/gallium/auxiliary/os/os_time.c +++ b/src/gallium/auxiliary/os/os_time.c @@ -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 diff --git a/src/gallium/auxiliary/os/os_time.h b/src/gallium/auxiliary/os/os_time.h index 7e0f67a76b0..54101a1f546 100644 --- a/src/gallium/auxiliary/os/os_time.h +++ b/src/gallium/auxiliary/os/os_time.h @@ -58,6 +58,13 @@ os_time_get(void); /* + * Get the current time in nanoseconds from an unknown base. + */ +uint64_t +os_time_get_nano(void); + + +/* * Sleep. */ #if defined(PIPE_OS_UNIX) diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index fcdc0f82b12..fe6fa3f9390 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -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]; diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index 20c0a1e0bcb..e3021972566 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -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 diff --git a/src/gallium/drivers/llvmpipe/lp_query.h b/src/gallium/drivers/llvmpipe/lp_query.h index ef1bc307037..cacbd9d0b8c 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.h +++ b/src/gallium/drivers/llvmpipe/lp_query.h @@ -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_* */ }; diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 5c233c06a15..40a8591cabe 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -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 */ diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index dc9739e9ad0..afcf33382f4 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 3f207d713af..acbde9da983 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -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); diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 84defc65054..1d71a87319e 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -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__); } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 7fdd1e735c4..6c86b4b779a 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 97ca1727c9b..94a21a0158b 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -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 diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 5bb5a7a0b7e..3b826de80c9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -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 | diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index dcd11b65c8f..c56ce9ee71c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -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; } |