101e04c3fSmrg/**************************************************************************** 201e04c3fSmrg * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg ***************************************************************************/ 2301e04c3fSmrg 2401e04c3fSmrg#include "pipe/p_defines.h" 2501e04c3fSmrg#include "util/u_memory.h" 2601e04c3fSmrg#include "util/os_time.h" 2701e04c3fSmrg#include "swr_context.h" 2801e04c3fSmrg#include "swr_fence.h" 2901e04c3fSmrg#include "swr_query.h" 3001e04c3fSmrg#include "swr_screen.h" 3101e04c3fSmrg#include "swr_state.h" 3201e04c3fSmrg#include "common/os.h" 3301e04c3fSmrg 3401e04c3fSmrgstatic struct swr_query * 3501e04c3fSmrgswr_query(struct pipe_query *p) 3601e04c3fSmrg{ 3701e04c3fSmrg return (struct swr_query *)p; 3801e04c3fSmrg} 3901e04c3fSmrg 4001e04c3fSmrgstatic struct pipe_query * 4101e04c3fSmrgswr_create_query(struct pipe_context *pipe, unsigned type, unsigned index) 4201e04c3fSmrg{ 4301e04c3fSmrg struct swr_query *pq; 4401e04c3fSmrg 4501e04c3fSmrg assert(type < PIPE_QUERY_TYPES); 4601e04c3fSmrg assert(index < MAX_SO_STREAMS); 4701e04c3fSmrg 4801e04c3fSmrg pq = (struct swr_query *) AlignedMalloc(sizeof(struct swr_query), 64); 4901e04c3fSmrg 5001e04c3fSmrg if (pq) { 517ec681f3Smrg memset(pq, 0, sizeof(*pq)); 5201e04c3fSmrg pq->type = type; 5301e04c3fSmrg pq->index = index; 5401e04c3fSmrg } 5501e04c3fSmrg 5601e04c3fSmrg return (struct pipe_query *)pq; 5701e04c3fSmrg} 5801e04c3fSmrg 5901e04c3fSmrg 6001e04c3fSmrgstatic void 6101e04c3fSmrgswr_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 6201e04c3fSmrg{ 6301e04c3fSmrg struct swr_query *pq = swr_query(q); 6401e04c3fSmrg 6501e04c3fSmrg if (pq->fence) { 6601e04c3fSmrg if (swr_is_fence_pending(pq->fence)) 6701e04c3fSmrg swr_fence_finish(pipe->screen, NULL, pq->fence, 0); 6801e04c3fSmrg swr_fence_reference(pipe->screen, &pq->fence, NULL); 6901e04c3fSmrg } 7001e04c3fSmrg 7101e04c3fSmrg AlignedFree(pq); 7201e04c3fSmrg} 7301e04c3fSmrg 7401e04c3fSmrg 757ec681f3Smrgstatic bool 7601e04c3fSmrgswr_get_query_result(struct pipe_context *pipe, 7701e04c3fSmrg struct pipe_query *q, 787ec681f3Smrg bool wait, 7901e04c3fSmrg union pipe_query_result *result) 8001e04c3fSmrg{ 8101e04c3fSmrg struct swr_query *pq = swr_query(q); 8201e04c3fSmrg unsigned index = pq->index; 8301e04c3fSmrg 8401e04c3fSmrg if (pq->fence) { 8501e04c3fSmrg if (!wait && !swr_is_fence_done(pq->fence)) 867ec681f3Smrg return false; 8701e04c3fSmrg 8801e04c3fSmrg swr_fence_finish(pipe->screen, NULL, pq->fence, 0); 8901e04c3fSmrg swr_fence_reference(pipe->screen, &pq->fence, NULL); 9001e04c3fSmrg } 9101e04c3fSmrg 9201e04c3fSmrg /* All values are reset to 0 at swr_begin_query, except starting timestamp. 9301e04c3fSmrg * Counters become simply end values. */ 9401e04c3fSmrg switch (pq->type) { 9501e04c3fSmrg /* Booleans */ 9601e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 9701e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 9801e04c3fSmrg result->b = pq->result.core.DepthPassCount != 0; 9901e04c3fSmrg break; 10001e04c3fSmrg case PIPE_QUERY_GPU_FINISHED: 1017ec681f3Smrg result->b = true; 10201e04c3fSmrg break; 10301e04c3fSmrg /* Counters */ 10401e04c3fSmrg case PIPE_QUERY_OCCLUSION_COUNTER: 10501e04c3fSmrg result->u64 = pq->result.core.DepthPassCount; 10601e04c3fSmrg break; 10701e04c3fSmrg case PIPE_QUERY_TIMESTAMP: 10801e04c3fSmrg case PIPE_QUERY_TIME_ELAPSED: 10901e04c3fSmrg result->u64 = pq->result.timestamp_end - pq->result.timestamp_start; 11001e04c3fSmrg break; 11101e04c3fSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 11201e04c3fSmrg result->u64 = pq->result.coreFE.IaPrimitives; 11301e04c3fSmrg break; 11401e04c3fSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 11501e04c3fSmrg result->u64 = pq->result.coreFE.SoNumPrimsWritten[index]; 11601e04c3fSmrg break; 11701e04c3fSmrg /* Structures */ 11801e04c3fSmrg case PIPE_QUERY_SO_STATISTICS: { 11901e04c3fSmrg struct pipe_query_data_so_statistics *so_stats = &result->so_statistics; 12001e04c3fSmrg so_stats->num_primitives_written = 12101e04c3fSmrg pq->result.coreFE.SoNumPrimsWritten[index]; 12201e04c3fSmrg so_stats->primitives_storage_needed = 12301e04c3fSmrg pq->result.coreFE.SoPrimStorageNeeded[index]; 12401e04c3fSmrg } break; 12501e04c3fSmrg case PIPE_QUERY_TIMESTAMP_DISJOINT: 12601e04c3fSmrg /* os_get_time_nano returns nanoseconds */ 12701e04c3fSmrg result->timestamp_disjoint.frequency = UINT64_C(1000000000); 12801e04c3fSmrg result->timestamp_disjoint.disjoint = FALSE; 12901e04c3fSmrg break; 13001e04c3fSmrg case PIPE_QUERY_PIPELINE_STATISTICS: { 13101e04c3fSmrg struct pipe_query_data_pipeline_statistics *p_stats = 13201e04c3fSmrg &result->pipeline_statistics; 13301e04c3fSmrg p_stats->ia_vertices = pq->result.coreFE.IaVertices; 13401e04c3fSmrg p_stats->ia_primitives = pq->result.coreFE.IaPrimitives; 13501e04c3fSmrg p_stats->vs_invocations = pq->result.coreFE.VsInvocations; 13601e04c3fSmrg p_stats->gs_invocations = pq->result.coreFE.GsInvocations; 13701e04c3fSmrg p_stats->gs_primitives = pq->result.coreFE.GsPrimitives; 13801e04c3fSmrg p_stats->c_invocations = pq->result.coreFE.CPrimitives; 13901e04c3fSmrg p_stats->c_primitives = pq->result.coreFE.CPrimitives; 14001e04c3fSmrg p_stats->ps_invocations = pq->result.core.PsInvocations; 14101e04c3fSmrg p_stats->hs_invocations = pq->result.coreFE.HsInvocations; 14201e04c3fSmrg p_stats->ds_invocations = pq->result.coreFE.DsInvocations; 14301e04c3fSmrg p_stats->cs_invocations = pq->result.core.CsInvocations; 14401e04c3fSmrg } break; 14501e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: { 14601e04c3fSmrg uint64_t num_primitives_written = 14701e04c3fSmrg pq->result.coreFE.SoNumPrimsWritten[index]; 14801e04c3fSmrg uint64_t primitives_storage_needed = 14901e04c3fSmrg pq->result.coreFE.SoPrimStorageNeeded[index]; 15001e04c3fSmrg result->b = num_primitives_written > primitives_storage_needed; 15101e04c3fSmrg } 15201e04c3fSmrg break; 15301e04c3fSmrg default: 15401e04c3fSmrg assert(0 && "Unsupported query"); 15501e04c3fSmrg break; 15601e04c3fSmrg } 15701e04c3fSmrg 1587ec681f3Smrg return true; 15901e04c3fSmrg} 16001e04c3fSmrg 1617ec681f3Smrgstatic bool 16201e04c3fSmrgswr_begin_query(struct pipe_context *pipe, struct pipe_query *q) 16301e04c3fSmrg{ 16401e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 16501e04c3fSmrg struct swr_query *pq = swr_query(q); 16601e04c3fSmrg 16701e04c3fSmrg /* Initialize Results */ 16801e04c3fSmrg memset(&pq->result, 0, sizeof(pq->result)); 16901e04c3fSmrg switch (pq->type) { 17001e04c3fSmrg case PIPE_QUERY_GPU_FINISHED: 17101e04c3fSmrg case PIPE_QUERY_TIMESTAMP: 17201e04c3fSmrg /* nothing to do, but don't want the default */ 17301e04c3fSmrg break; 17401e04c3fSmrg case PIPE_QUERY_TIME_ELAPSED: 17501e04c3fSmrg pq->result.timestamp_start = swr_get_timestamp(pipe->screen); 17601e04c3fSmrg break; 17701e04c3fSmrg default: 17801e04c3fSmrg /* Core counters required. Update draw context with location to 17901e04c3fSmrg * store results. */ 18001e04c3fSmrg swr_update_draw_context(ctx, &pq->result); 18101e04c3fSmrg 18201e04c3fSmrg /* Only change stat collection if there are no active queries */ 18301e04c3fSmrg if (ctx->active_queries == 0) { 18401e04c3fSmrg ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, TRUE); 18501e04c3fSmrg ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, TRUE); 18601e04c3fSmrg } 18701e04c3fSmrg ctx->active_queries++; 18801e04c3fSmrg break; 18901e04c3fSmrg } 19001e04c3fSmrg 19101e04c3fSmrg 19201e04c3fSmrg return true; 19301e04c3fSmrg} 19401e04c3fSmrg 19501e04c3fSmrgstatic bool 19601e04c3fSmrgswr_end_query(struct pipe_context *pipe, struct pipe_query *q) 19701e04c3fSmrg{ 19801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 19901e04c3fSmrg struct swr_query *pq = swr_query(q); 20001e04c3fSmrg 20101e04c3fSmrg switch (pq->type) { 20201e04c3fSmrg case PIPE_QUERY_GPU_FINISHED: 20301e04c3fSmrg /* nothing to do, but don't want the default */ 20401e04c3fSmrg break; 20501e04c3fSmrg case PIPE_QUERY_TIMESTAMP: 20601e04c3fSmrg case PIPE_QUERY_TIME_ELAPSED: 20701e04c3fSmrg pq->result.timestamp_end = swr_get_timestamp(pipe->screen); 20801e04c3fSmrg break; 20901e04c3fSmrg default: 21001e04c3fSmrg /* Stats are updated asynchronously, a fence is used to signal 21101e04c3fSmrg * completion. */ 21201e04c3fSmrg if (!pq->fence) { 21301e04c3fSmrg struct swr_screen *screen = swr_screen(pipe->screen); 21401e04c3fSmrg swr_fence_reference(pipe->screen, &pq->fence, screen->flush_fence); 21501e04c3fSmrg } 21601e04c3fSmrg swr_fence_submit(ctx, pq->fence); 21701e04c3fSmrg 21801e04c3fSmrg /* Only change stat collection if there are no active queries */ 21901e04c3fSmrg ctx->active_queries--; 22001e04c3fSmrg if (ctx->active_queries == 0) { 22101e04c3fSmrg ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, FALSE); 22201e04c3fSmrg ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, FALSE); 22301e04c3fSmrg } 22401e04c3fSmrg 22501e04c3fSmrg break; 22601e04c3fSmrg } 22701e04c3fSmrg 22801e04c3fSmrg return true; 22901e04c3fSmrg} 23001e04c3fSmrg 23101e04c3fSmrg 2327ec681f3Smrgbool 23301e04c3fSmrgswr_check_render_cond(struct pipe_context *pipe) 23401e04c3fSmrg{ 23501e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 2367ec681f3Smrg bool b, wait; 23701e04c3fSmrg uint64_t result; 23801e04c3fSmrg 23901e04c3fSmrg if (!ctx->render_cond_query) 2407ec681f3Smrg return true; /* no query predicate, draw normally */ 24101e04c3fSmrg 24201e04c3fSmrg wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT 24301e04c3fSmrg || ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); 24401e04c3fSmrg 24501e04c3fSmrg b = pipe->get_query_result( 24601e04c3fSmrg pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result); 24701e04c3fSmrg if (b) 24801e04c3fSmrg return ((!result) == ctx->render_cond_cond); 24901e04c3fSmrg else 2507ec681f3Smrg return true; 25101e04c3fSmrg} 25201e04c3fSmrg 25301e04c3fSmrg 25401e04c3fSmrgstatic void 2557ec681f3Smrgswr_set_active_query_state(struct pipe_context *pipe, bool enable) 25601e04c3fSmrg{ 25701e04c3fSmrg} 25801e04c3fSmrg 25901e04c3fSmrgvoid 26001e04c3fSmrgswr_query_init(struct pipe_context *pipe) 26101e04c3fSmrg{ 26201e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 26301e04c3fSmrg 26401e04c3fSmrg pipe->create_query = swr_create_query; 26501e04c3fSmrg pipe->destroy_query = swr_destroy_query; 26601e04c3fSmrg pipe->begin_query = swr_begin_query; 26701e04c3fSmrg pipe->end_query = swr_end_query; 26801e04c3fSmrg pipe->get_query_result = swr_get_query_result; 26901e04c3fSmrg pipe->set_active_query_state = swr_set_active_query_state; 27001e04c3fSmrg 27101e04c3fSmrg ctx->active_queries = 0; 27201e04c3fSmrg} 273