diff options
author | Dave Airlie <[email protected]> | 2019-11-22 14:47:59 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2019-11-25 12:37:32 +1000 |
commit | 506e51b8560f30bc67ee84def535a324b5748208 (patch) | |
tree | ad3ac1e875f0f244e84af5138673634703befc87 /src | |
parent | f54c4e85ce089964e4d2ed39157f07226a41d11f (diff) |
llvmpipe: initial query buffer object support. (v2)
This fails a couple of piglits due to other bugs in llvmpipe,
but it adds support for the feature properly.
v2: don't reset pipestats, just recalc, fix CI expectation
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_query.c | 151 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_screen.c | 3 |
2 files changed, 153 insertions, 1 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index 7f86c3791b4..8fd5ab52614 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -185,6 +185,156 @@ llvmpipe_get_query_result(struct pipe_context *pipe, return true; } +static void +llvmpipe_get_query_result_resource(struct pipe_context *pipe, + struct pipe_query *q, + bool wait, + enum pipe_query_value_type result_type, + int index, + struct pipe_resource *resource, + unsigned offset) +{ + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + unsigned num_threads = MAX2(1, screen->num_threads); + struct llvmpipe_query *pq = llvmpipe_query(q); + struct llvmpipe_resource *lpr = llvmpipe_resource(resource); + bool unflushed = false; + bool unsignalled = false; + if (pq->fence) { + /* only have a fence if there was a scene */ + if (!lp_fence_signalled(pq->fence)) { + unsignalled = true; + if (!lp_fence_issued(pq->fence)) + unflushed = true; + } + } + + + uint64_t value = 0; + if (index == -1) + if (unsignalled) + value = 0; + else + value = 1; + else { + unsigned i; + + if (unflushed) { + llvmpipe_flush(pipe, NULL, __FUNCTION__); + + if (!wait) + return; + + lp_fence_wait(pq->fence); + } + + switch (pq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + for (i = 0; i < num_threads; i++) { + value += pq->end[i]; + } + break; + case PIPE_QUERY_OCCLUSION_PREDICATE: + case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: + for (i = 0; i < num_threads; i++) { + /* safer (still not guaranteed) when there's an overflow */ + value = value || pq->end[i]; + } + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + value = pq->num_primitives_generated; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + value = pq->num_primitives_written; + break; + case PIPE_QUERY_TIMESTAMP: + for (i = 0; i < num_threads; i++) { + if (pq->end[i] > value) { + value = pq->end[i]; + } + } + break; + case PIPE_QUERY_SO_OVERFLOW_PREDICATE: + case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: + value = !!(pq->num_primitives_generated > pq->num_primitives_written); + break; + case PIPE_QUERY_PIPELINE_STATISTICS: + switch ((enum pipe_statistics_query_index)index) { + case PIPE_STAT_QUERY_IA_VERTICES: + value = pq->stats.ia_vertices; + break; + case PIPE_STAT_QUERY_IA_PRIMITIVES: + value = pq->stats.ia_primitives; + break; + case PIPE_STAT_QUERY_VS_INVOCATIONS: + value = pq->stats.vs_invocations; + break; + case PIPE_STAT_QUERY_GS_INVOCATIONS: + value = pq->stats.gs_invocations; + break; + case PIPE_STAT_QUERY_GS_PRIMITIVES: + value = pq->stats.gs_primitives; + break; + case PIPE_STAT_QUERY_C_INVOCATIONS: + value = pq->stats.c_invocations; + break; + case PIPE_STAT_QUERY_C_PRIMITIVES: + value = pq->stats.c_primitives; + break; + case PIPE_STAT_QUERY_PS_INVOCATIONS: + value = 0; + for (i = 0; i < num_threads; i++) { + value += pq->end[i]; + } + value *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; + break; + case PIPE_STAT_QUERY_HS_INVOCATIONS: + value = pq->stats.hs_invocations; + break; + case PIPE_STAT_QUERY_DS_INVOCATIONS: + value = pq->stats.ds_invocations; + break; + case PIPE_STAT_QUERY_CS_INVOCATIONS: + value = pq->stats.cs_invocations; + break; + } + break; + default: + fprintf(stderr, "Unknown query type %d\n", pq->type); + break; + } + } + + void *dst = (uint8_t *)lpr->data + offset; + switch (result_type) { + case PIPE_QUERY_TYPE_I32: { + int32_t *iptr = (int32_t *)dst; + if (value > 0x7fffffff) + *iptr = 0x7fffffff; + else + *iptr = (int32_t)value; + break; + } + case PIPE_QUERY_TYPE_U32: { + uint32_t *uptr = (uint32_t *)dst; + if (value > 0xffffffff) + *uptr = 0xffffffff; + else + *uptr = (uint32_t)value; + break; + } + case PIPE_QUERY_TYPE_I64: { + int64_t *iptr = (int64_t *)dst; + *iptr = (int64_t)value; + break; + } + case PIPE_QUERY_TYPE_U64: { + uint64_t *uptr = (uint64_t *)dst; + *uptr = (uint64_t)value; + break; + } + } +} static bool llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) @@ -341,6 +491,7 @@ void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) llvmpipe->pipe.begin_query = llvmpipe_begin_query; llvmpipe->pipe.end_query = llvmpipe_end_query; llvmpipe->pipe.get_query_result = llvmpipe_get_query_result; + llvmpipe->pipe.get_query_result_resource = llvmpipe_get_query_result_resource; llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state; } diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 7c35d148d26..d2364c183d7 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -318,6 +318,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 32; case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: return 1; + case PIPE_CAP_QUERY_BUFFER_OBJECT: + return 1; case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: @@ -337,7 +339,6 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_STRING_MARKER: case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY: case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS: - case PIPE_CAP_QUERY_BUFFER_OBJECT: case PIPE_CAP_QUERY_MEMORY_INFO: case PIPE_CAP_PCI_GROUP: case PIPE_CAP_PCI_BUS: |