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