From: Christoph Bumiller Date: Thu, 12 Jul 2012 11:59:52 +0000 (+0200) Subject: nouveau: implement missing timer query functionality X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9ed65301e044711de0db51b4986085fca170d764;p=mesa.git nouveau: implement missing timer query functionality --- diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index 9baa68ce151..d129a55b387 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -8,10 +8,14 @@ #include "util/u_format_s3tc.h" #include "util/u_string.h" +#include "os/os_time.h" + #include #include #include +#include + #include "nouveau_winsys.h" #include "nouveau_screen.h" #include "nouveau_fence.h" @@ -39,6 +43,16 @@ nouveau_screen_get_vendor(struct pipe_screen *pscreen) return "nouveau"; } +static uint64_t +nouveau_screen_get_timestamp(struct pipe_screen *pscreen) +{ + int64_t cpu_time = os_time_get() * 1000; + + /* getparam of PTIMER_TIME takes about x10 as long (several usecs) */ + + return cpu_time + nouveau_screen(pscreen)->cpu_gpu_time_delta; +} + static void nouveau_screen_fence_ref(struct pipe_screen *pscreen, struct pipe_fence_handle **ptr, @@ -108,6 +122,7 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) struct pipe_screen *pscreen = &screen->base; struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; struct nvc0_fifo nvc0_data = { }; + uint64_t time; int size, ret; void *data; union nouveau_bo_config mm_config; @@ -139,9 +154,18 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) if (ret) return ret; + /* getting CPU time first appears to be more accurate */ + screen->cpu_gpu_time_delta = os_time_get(); + + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_PTIMER_TIME, &time); + if (!ret) + screen->cpu_gpu_time_delta = time - screen->cpu_gpu_time_delta * 1000; + pscreen->get_name = nouveau_screen_get_name; pscreen->get_vendor = nouveau_screen_get_vendor; + pscreen->get_timestamp = nouveau_screen_get_timestamp; + pscreen->fence_reference = nouveau_screen_fence_ref; pscreen->fence_signalled = nouveau_screen_fence_signalled; pscreen->fence_finish = nouveau_screen_fence_finish; diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index 5a3cfab92e9..335b95820ab 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -39,6 +39,8 @@ struct nouveau_screen { struct nouveau_mman *mm_VRAM; struct nouveau_mman *mm_GART; + + int64_t cpu_gpu_time_delta; }; static INLINE struct nouveau_screen * diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c index fb4be31e6ad..001aba1e26c 100644 --- a/src/gallium/drivers/nv30/nv30_query.c +++ b/src/gallium/drivers/nv30/nv30_query.c @@ -114,6 +114,7 @@ nv30_query_create(struct pipe_context *pipe, unsigned type) q->type = type; switch (q->type) { + case PIPE_QUERY_TIMESTAMP: case PIPE_QUERY_TIME_ELAPSED: q->enable = 0x0000; q->report = 1; @@ -158,6 +159,8 @@ nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start); } break; + case PIPE_QUERY_TIMESTAMP: + return; default: BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1); PUSH_DATA (push, q->report); @@ -193,13 +196,13 @@ nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq) static boolean nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, void *result) + boolean wait, union pipe_query_result *result) { struct nv30_screen *screen = nv30_screen(pipe->screen); struct nv30_query *q = nv30_query(pq); volatile uint32_t *ntfy0 = nv30_ntfy(screen, q->qo[0]); volatile uint32_t *ntfy1 = nv30_ntfy(screen, q->qo[1]); - uint64_t *res64 = result; + uint64_t *res64 = &result->u64; if (ntfy1) { while (ntfy1[3] & 0xff000000) { @@ -208,6 +211,9 @@ nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq, } switch (q->type) { + case PIPE_QUERY_TIMESTAMP: + q->result = *(uint64_t *)&ntfy1[0]; + break; case PIPE_QUERY_TIME_ELAPSED: q->result = *(uint64_t *)&ntfy1[0] - *(uint64_t *)&ntfy0[0]; break; diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 88e428b6809..1752d10875e 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -70,6 +70,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_SCALED_RESOLVE: case PIPE_CAP_OCCLUSION_QUERY: case PIPE_CAP_TIMER_QUERY: + case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_TEXTURE_SWIZZLE: case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: @@ -116,7 +117,6 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: case PIPE_CAP_START_INSTANCE: - case PIPE_CAP_QUERY_TIMESTAMP: return 0; case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 8e62c5f11bc..f9ac33d2623 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -215,11 +215,15 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) nv50_query_get(push, q, 0x00, 0x05805002); nv50_query_get(push, q, 0x10, 0x06805002); break; + case PIPE_QUERY_TIMESTAMP: + q->sequence++; + /* fall through */ case PIPE_QUERY_TIMESTAMP_DISJOINT: case PIPE_QUERY_TIME_ELAPSED: nv50_query_get(push, q, 0, 0x00005002); break; case PIPE_QUERY_GPU_FINISHED: + q->sequence++; nv50_query_get(push, q, 0, 0x1000f010); break; case NVA0_QUERY_STREAM_OUTPUT_BUFFER_OFFSET: @@ -229,7 +233,7 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) assert(0); break; } - q->flushed = FALSE; + q->ready = q->flushed = FALSE; } static INLINE boolean @@ -280,9 +284,12 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, res64[0] = data64[0] - data64[4]; res64[1] = data64[2] - data64[6]; break; + case PIPE_QUERY_TIMESTAMP: + res64[0] = data64[1]; + break; case PIPE_QUERY_TIMESTAMP_DISJOINT: /* u32 sequence, u32 0, u64 time */ res64[0] = 1000000000; - res8[8] = (data64[0] == data64[2]) ? FALSE : TRUE; + res8[8] = (data64[1] == data64[3]) ? FALSE : TRUE; break; case PIPE_QUERY_TIME_ELAPSED: res64[0] = data64[1] - data64[3]; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index c7344a1a382..3d510ea5f35 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -128,6 +128,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: return 1; + case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_TIMER_QUERY: case PIPE_CAP_OCCLUSION_QUERY: return 1; @@ -172,7 +173,6 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: - case PIPE_CAP_QUERY_TIMESTAMP: return 0; default: NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index 02a408ecb25..eb74e955f52 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -108,6 +108,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: return 1; + case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_TIMER_QUERY: case PIPE_CAP_OCCLUSION_QUERY: case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: @@ -150,7 +151,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: - case PIPE_CAP_QUERY_TIMESTAMP: return 0; default: NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);