1b8e80941Smrg/**************************************************************************** 2b8e80941Smrg * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg ***************************************************************************/ 23b8e80941Smrg 24b8e80941Smrg#include "pipe/p_defines.h" 25b8e80941Smrg#include "util/u_memory.h" 26b8e80941Smrg#include "util/os_time.h" 27b8e80941Smrg#include "swr_context.h" 28b8e80941Smrg#include "swr_fence.h" 29b8e80941Smrg#include "swr_query.h" 30b8e80941Smrg#include "swr_screen.h" 31b8e80941Smrg#include "swr_state.h" 32b8e80941Smrg#include "common/os.h" 33b8e80941Smrg 34b8e80941Smrgstatic struct swr_query * 35b8e80941Smrgswr_query(struct pipe_query *p) 36b8e80941Smrg{ 37b8e80941Smrg return (struct swr_query *)p; 38b8e80941Smrg} 39b8e80941Smrg 40b8e80941Smrgstatic struct pipe_query * 41b8e80941Smrgswr_create_query(struct pipe_context *pipe, unsigned type, unsigned index) 42b8e80941Smrg{ 43b8e80941Smrg struct swr_query *pq; 44b8e80941Smrg 45b8e80941Smrg assert(type < PIPE_QUERY_TYPES); 46b8e80941Smrg assert(index < MAX_SO_STREAMS); 47b8e80941Smrg 48b8e80941Smrg pq = (struct swr_query *) AlignedMalloc(sizeof(struct swr_query), 64); 49b8e80941Smrg memset(pq, 0, sizeof(*pq)); 50b8e80941Smrg 51b8e80941Smrg if (pq) { 52b8e80941Smrg pq->type = type; 53b8e80941Smrg pq->index = index; 54b8e80941Smrg } 55b8e80941Smrg 56b8e80941Smrg return (struct pipe_query *)pq; 57b8e80941Smrg} 58b8e80941Smrg 59b8e80941Smrg 60b8e80941Smrgstatic void 61b8e80941Smrgswr_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 62b8e80941Smrg{ 63b8e80941Smrg struct swr_query *pq = swr_query(q); 64b8e80941Smrg 65b8e80941Smrg if (pq->fence) { 66b8e80941Smrg if (swr_is_fence_pending(pq->fence)) 67b8e80941Smrg swr_fence_finish(pipe->screen, NULL, pq->fence, 0); 68b8e80941Smrg swr_fence_reference(pipe->screen, &pq->fence, NULL); 69b8e80941Smrg } 70b8e80941Smrg 71b8e80941Smrg AlignedFree(pq); 72b8e80941Smrg} 73b8e80941Smrg 74b8e80941Smrg 75b8e80941Smrgstatic boolean 76b8e80941Smrgswr_get_query_result(struct pipe_context *pipe, 77b8e80941Smrg struct pipe_query *q, 78b8e80941Smrg boolean wait, 79b8e80941Smrg union pipe_query_result *result) 80b8e80941Smrg{ 81b8e80941Smrg struct swr_query *pq = swr_query(q); 82b8e80941Smrg unsigned index = pq->index; 83b8e80941Smrg 84b8e80941Smrg if (pq->fence) { 85b8e80941Smrg if (!wait && !swr_is_fence_done(pq->fence)) 86b8e80941Smrg return FALSE; 87b8e80941Smrg 88b8e80941Smrg swr_fence_finish(pipe->screen, NULL, pq->fence, 0); 89b8e80941Smrg swr_fence_reference(pipe->screen, &pq->fence, NULL); 90b8e80941Smrg } 91b8e80941Smrg 92b8e80941Smrg /* All values are reset to 0 at swr_begin_query, except starting timestamp. 93b8e80941Smrg * Counters become simply end values. */ 94b8e80941Smrg switch (pq->type) { 95b8e80941Smrg /* Booleans */ 96b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 97b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 98b8e80941Smrg result->b = pq->result.core.DepthPassCount != 0; 99b8e80941Smrg break; 100b8e80941Smrg case PIPE_QUERY_GPU_FINISHED: 101b8e80941Smrg result->b = TRUE; 102b8e80941Smrg break; 103b8e80941Smrg /* Counters */ 104b8e80941Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 105b8e80941Smrg result->u64 = pq->result.core.DepthPassCount; 106b8e80941Smrg break; 107b8e80941Smrg case PIPE_QUERY_TIMESTAMP: 108b8e80941Smrg case PIPE_QUERY_TIME_ELAPSED: 109b8e80941Smrg result->u64 = pq->result.timestamp_end - pq->result.timestamp_start; 110b8e80941Smrg break; 111b8e80941Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 112b8e80941Smrg result->u64 = pq->result.coreFE.IaPrimitives; 113b8e80941Smrg break; 114b8e80941Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 115b8e80941Smrg result->u64 = pq->result.coreFE.SoNumPrimsWritten[index]; 116b8e80941Smrg break; 117b8e80941Smrg /* Structures */ 118b8e80941Smrg case PIPE_QUERY_SO_STATISTICS: { 119b8e80941Smrg struct pipe_query_data_so_statistics *so_stats = &result->so_statistics; 120b8e80941Smrg so_stats->num_primitives_written = 121b8e80941Smrg pq->result.coreFE.SoNumPrimsWritten[index]; 122b8e80941Smrg so_stats->primitives_storage_needed = 123b8e80941Smrg pq->result.coreFE.SoPrimStorageNeeded[index]; 124b8e80941Smrg } break; 125b8e80941Smrg case PIPE_QUERY_TIMESTAMP_DISJOINT: 126b8e80941Smrg /* os_get_time_nano returns nanoseconds */ 127b8e80941Smrg result->timestamp_disjoint.frequency = UINT64_C(1000000000); 128b8e80941Smrg result->timestamp_disjoint.disjoint = FALSE; 129b8e80941Smrg break; 130b8e80941Smrg case PIPE_QUERY_PIPELINE_STATISTICS: { 131b8e80941Smrg struct pipe_query_data_pipeline_statistics *p_stats = 132b8e80941Smrg &result->pipeline_statistics; 133b8e80941Smrg p_stats->ia_vertices = pq->result.coreFE.IaVertices; 134b8e80941Smrg p_stats->ia_primitives = pq->result.coreFE.IaPrimitives; 135b8e80941Smrg p_stats->vs_invocations = pq->result.coreFE.VsInvocations; 136b8e80941Smrg p_stats->gs_invocations = pq->result.coreFE.GsInvocations; 137b8e80941Smrg p_stats->gs_primitives = pq->result.coreFE.GsPrimitives; 138b8e80941Smrg p_stats->c_invocations = pq->result.coreFE.CPrimitives; 139b8e80941Smrg p_stats->c_primitives = pq->result.coreFE.CPrimitives; 140b8e80941Smrg p_stats->ps_invocations = pq->result.core.PsInvocations; 141b8e80941Smrg p_stats->hs_invocations = pq->result.coreFE.HsInvocations; 142b8e80941Smrg p_stats->ds_invocations = pq->result.coreFE.DsInvocations; 143b8e80941Smrg p_stats->cs_invocations = pq->result.core.CsInvocations; 144b8e80941Smrg } break; 145b8e80941Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: { 146b8e80941Smrg uint64_t num_primitives_written = 147b8e80941Smrg pq->result.coreFE.SoNumPrimsWritten[index]; 148b8e80941Smrg uint64_t primitives_storage_needed = 149b8e80941Smrg pq->result.coreFE.SoPrimStorageNeeded[index]; 150b8e80941Smrg result->b = num_primitives_written > primitives_storage_needed; 151b8e80941Smrg } 152b8e80941Smrg break; 153b8e80941Smrg default: 154b8e80941Smrg assert(0 && "Unsupported query"); 155b8e80941Smrg break; 156b8e80941Smrg } 157b8e80941Smrg 158b8e80941Smrg return TRUE; 159b8e80941Smrg} 160b8e80941Smrg 161b8e80941Smrgstatic boolean 162b8e80941Smrgswr_begin_query(struct pipe_context *pipe, struct pipe_query *q) 163b8e80941Smrg{ 164b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 165b8e80941Smrg struct swr_query *pq = swr_query(q); 166b8e80941Smrg 167b8e80941Smrg /* Initialize Results */ 168b8e80941Smrg memset(&pq->result, 0, sizeof(pq->result)); 169b8e80941Smrg switch (pq->type) { 170b8e80941Smrg case PIPE_QUERY_GPU_FINISHED: 171b8e80941Smrg case PIPE_QUERY_TIMESTAMP: 172b8e80941Smrg /* nothing to do, but don't want the default */ 173b8e80941Smrg break; 174b8e80941Smrg case PIPE_QUERY_TIME_ELAPSED: 175b8e80941Smrg pq->result.timestamp_start = swr_get_timestamp(pipe->screen); 176b8e80941Smrg break; 177b8e80941Smrg default: 178b8e80941Smrg /* Core counters required. Update draw context with location to 179b8e80941Smrg * store results. */ 180b8e80941Smrg swr_update_draw_context(ctx, &pq->result); 181b8e80941Smrg 182b8e80941Smrg /* Only change stat collection if there are no active queries */ 183b8e80941Smrg if (ctx->active_queries == 0) { 184b8e80941Smrg ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, TRUE); 185b8e80941Smrg ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, TRUE); 186b8e80941Smrg } 187b8e80941Smrg ctx->active_queries++; 188b8e80941Smrg break; 189b8e80941Smrg } 190b8e80941Smrg 191b8e80941Smrg 192b8e80941Smrg return true; 193b8e80941Smrg} 194b8e80941Smrg 195b8e80941Smrgstatic bool 196b8e80941Smrgswr_end_query(struct pipe_context *pipe, struct pipe_query *q) 197b8e80941Smrg{ 198b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 199b8e80941Smrg struct swr_query *pq = swr_query(q); 200b8e80941Smrg 201b8e80941Smrg switch (pq->type) { 202b8e80941Smrg case PIPE_QUERY_GPU_FINISHED: 203b8e80941Smrg /* nothing to do, but don't want the default */ 204b8e80941Smrg break; 205b8e80941Smrg case PIPE_QUERY_TIMESTAMP: 206b8e80941Smrg case PIPE_QUERY_TIME_ELAPSED: 207b8e80941Smrg pq->result.timestamp_end = swr_get_timestamp(pipe->screen); 208b8e80941Smrg break; 209b8e80941Smrg default: 210b8e80941Smrg /* Stats are updated asynchronously, a fence is used to signal 211b8e80941Smrg * completion. */ 212b8e80941Smrg if (!pq->fence) { 213b8e80941Smrg struct swr_screen *screen = swr_screen(pipe->screen); 214b8e80941Smrg swr_fence_reference(pipe->screen, &pq->fence, screen->flush_fence); 215b8e80941Smrg } 216b8e80941Smrg swr_fence_submit(ctx, pq->fence); 217b8e80941Smrg 218b8e80941Smrg /* Only change stat collection if there are no active queries */ 219b8e80941Smrg ctx->active_queries--; 220b8e80941Smrg if (ctx->active_queries == 0) { 221b8e80941Smrg ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, FALSE); 222b8e80941Smrg ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, FALSE); 223b8e80941Smrg } 224b8e80941Smrg 225b8e80941Smrg break; 226b8e80941Smrg } 227b8e80941Smrg 228b8e80941Smrg return true; 229b8e80941Smrg} 230b8e80941Smrg 231b8e80941Smrg 232b8e80941Smrgboolean 233b8e80941Smrgswr_check_render_cond(struct pipe_context *pipe) 234b8e80941Smrg{ 235b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 236b8e80941Smrg boolean b, wait; 237b8e80941Smrg uint64_t result; 238b8e80941Smrg 239b8e80941Smrg if (!ctx->render_cond_query) 240b8e80941Smrg return TRUE; /* no query predicate, draw normally */ 241b8e80941Smrg 242b8e80941Smrg wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT 243b8e80941Smrg || ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); 244b8e80941Smrg 245b8e80941Smrg b = pipe->get_query_result( 246b8e80941Smrg pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result); 247b8e80941Smrg if (b) 248b8e80941Smrg return ((!result) == ctx->render_cond_cond); 249b8e80941Smrg else 250b8e80941Smrg return TRUE; 251b8e80941Smrg} 252b8e80941Smrg 253b8e80941Smrg 254b8e80941Smrgstatic void 255b8e80941Smrgswr_set_active_query_state(struct pipe_context *pipe, boolean enable) 256b8e80941Smrg{ 257b8e80941Smrg} 258b8e80941Smrg 259b8e80941Smrgvoid 260b8e80941Smrgswr_query_init(struct pipe_context *pipe) 261b8e80941Smrg{ 262b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 263b8e80941Smrg 264b8e80941Smrg pipe->create_query = swr_create_query; 265b8e80941Smrg pipe->destroy_query = swr_destroy_query; 266b8e80941Smrg pipe->begin_query = swr_begin_query; 267b8e80941Smrg pipe->end_query = swr_end_query; 268b8e80941Smrg pipe->get_query_result = swr_get_query_result; 269b8e80941Smrg pipe->set_active_query_state = swr_set_active_query_state; 270b8e80941Smrg 271b8e80941Smrg ctx->active_queries = 0; 272b8e80941Smrg} 273