/** * Has the fence been executed/finished? */ static boolean llvmpipe_fence_signalled(struct pipe_screen *screen, struct pipe_fence_handle *fence) { struct lp_fence *f = (struct lp_fence *) fence; return lp_fence_signalled(f); }
/** * Has the fence been executed/finished? */ static int llvmpipe_fence_signalled(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flag) { struct lp_fence *f = (struct lp_fence *) fence; return lp_fence_signalled(f); }
static boolean llvmpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, union pipe_query_result *vresult) { struct llvmpipe_query *pq = llvmpipe_query(q); uint64_t *result = (uint64_t *)vresult; int i; if (!pq->fence) { /* no fence because there was no scene, so results is zero */ *result = 0; return TRUE; } if (!lp_fence_signalled(pq->fence)) { if (!lp_fence_issued(pq->fence)) llvmpipe_flush(pipe, NULL, __FUNCTION__); if (!wait) return FALSE; lp_fence_wait(pq->fence); } /* Sum the results from each of the threads: */ *result = 0; switch (pq->type) { case PIPE_QUERY_OCCLUSION_COUNTER: for (i = 0; i < LP_MAX_THREADS; i++) { *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; case PIPE_QUERY_PRIMITIVES_GENERATED: *result = pq->num_primitives_generated; break; case PIPE_QUERY_PRIMITIVES_EMITTED: *result = pq->num_primitives_written; break; default: assert(0); break; } return TRUE; }
/** * Wait for the fence to finish. */ static boolean llvmpipe_fence_finish(struct pipe_screen *screen, struct pipe_context *ctx, struct pipe_fence_handle *fence_handle, uint64_t timeout) { struct lp_fence *f = (struct lp_fence *) fence_handle; if (!timeout) return lp_fence_signalled(f); if (!lp_fence_signalled(f)) { if (timeout != PIPE_TIMEOUT_INFINITE) return lp_fence_timedwait(f, timeout); lp_fence_wait(f); } return TRUE; }
/** * Wait for the fence to finish. */ static boolean llvmpipe_fence_finish(struct pipe_screen *screen, struct pipe_fence_handle *fence_handle, uint64_t timeout) { struct lp_fence *f = (struct lp_fence *) fence_handle; if (!timeout) return lp_fence_signalled(f); lp_fence_wait(f); return TRUE; }
static void llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_query *pq = llvmpipe_query(q); /* Ideally we would refcount queries & not get destroyed until the * last scene had finished with us. */ if (pq->fence) { if (!lp_fence_issued(pq->fence)) llvmpipe_flush(pipe, NULL, __FUNCTION__); if (!lp_fence_signalled(pq->fence)) lp_fence_wait(pq->fence); lp_fence_reference(&pq->fence, NULL); } FREE(pq); }
static boolean llvmpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, union pipe_query_result *vresult) { struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); unsigned num_threads = MAX2(1, screen->num_threads); struct llvmpipe_query *pq = llvmpipe_query(q); uint64_t *result = (uint64_t *)vresult; int i; if (pq->fence) { /* only have a fence if there was a scene */ if (!lp_fence_signalled(pq->fence)) { if (!lp_fence_issued(pq->fence)) llvmpipe_flush(pipe, NULL, __FUNCTION__); if (!wait) return FALSE; lp_fence_wait(pq->fence); } } /* Sum the results from each of the threads: */ *result = 0; switch (pq->type) { case PIPE_QUERY_OCCLUSION_COUNTER: for (i = 0; i < num_threads; i++) { *result += pq->end[i]; } break; case PIPE_QUERY_OCCLUSION_PREDICATE: for (i = 0; i < num_threads; i++) { /* safer (still not guaranteed) when there's an overflow */ vresult->b = vresult->b || pq->end[i]; } break; case PIPE_QUERY_TIMESTAMP: for (i = 0; i < num_threads; i++) { if (pq->end[i] > *result) { *result = pq->end[i]; } } break; case PIPE_QUERY_TIMESTAMP_DISJOINT: { struct pipe_query_data_timestamp_disjoint *td = (struct pipe_query_data_timestamp_disjoint *)vresult; /* os_get_time_nano return nanoseconds */ td->frequency = UINT64_C(1000000000); td->disjoint = FALSE; } break; case PIPE_QUERY_GPU_FINISHED: vresult->b = TRUE; break; case PIPE_QUERY_PRIMITIVES_GENERATED: *result = pq->num_primitives_generated; break; case PIPE_QUERY_PRIMITIVES_EMITTED: *result = pq->num_primitives_written; break; case PIPE_QUERY_SO_OVERFLOW_PREDICATE: vresult->b = pq->num_primitives_generated > pq->num_primitives_written; break; case PIPE_QUERY_SO_STATISTICS: { struct pipe_query_data_so_statistics *stats = (struct pipe_query_data_so_statistics *)vresult; stats->num_primitives_written = pq->num_primitives_written; stats->primitives_storage_needed = pq->num_primitives_generated; } break; case PIPE_QUERY_PIPELINE_STATISTICS: { struct pipe_query_data_pipeline_statistics *stats = (struct pipe_query_data_pipeline_statistics *)vresult; /* only ps_invocations come from binned query */ for (i = 0; i < num_threads; i++) { pq->stats.ps_invocations += pq->end[i]; } pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; *stats = pq->stats; } break; default: assert(0); break; } return TRUE; }