static void swr_destroy(struct pipe_context *pipe) { struct swr_context *ctx = swr_context(pipe); struct swr_screen *screen = swr_screen(pipe->screen); if (ctx->blitter) util_blitter_destroy(ctx->blitter); /* Idle core before deleting context */ SwrWaitForIdle(ctx->swrContext); for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL); } pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL); for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) { pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_FRAGMENT][i], NULL); } for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) { pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_VERTEX][i], NULL); } if (ctx->swrContext) SwrDestroyContext(ctx->swrContext); delete ctx->blendJIT; swr_destroy_scratch_buffers(ctx); /* Only update screen->pipe if current context is being destroyed */ assert(screen); if (screen->pipe == pipe) screen->pipe = NULL; FREE(ctx); }
// XXX Create a fence callback, rather than stalling SwrWaitForIdle static void swr_gather_stats(struct pipe_context *pipe, struct swr_query *pq) { struct swr_context *ctx = swr_context(pipe); assert(pq->result); union pipe_query_result *result = pq->result; boolean enable_stats = pq->enable_stats; SWR_STATS swr_stats = {0}; if (pq->fence) { if (!swr_is_fence_done(swr_fence(pq->fence))) { swr_fence_submit(ctx, pq->fence); swr_fence_finish(pipe->screen, pq->fence, 0); } swr_fence_reference(pipe->screen, &pq->fence, NULL); } /* * These queries don't need SWR Stats enabled in the core * Set and return. */ switch (pq->type) { case PIPE_QUERY_TIMESTAMP: case PIPE_QUERY_TIME_ELAPSED: result->u64 = swr_get_timestamp(pipe->screen); return; break; case PIPE_QUERY_TIMESTAMP_DISJOINT: /* nothing to do here */ return; break; case PIPE_QUERY_GPU_FINISHED: result->b = TRUE; /* XXX TODO Add an api func to SWR to compare drawId vs LastRetiredId? */ return; break; default: /* Any query that needs SwrCore stats */ break; } /* * All other results are collected from SwrCore counters */ /* XXX, Should turn this into a fence callback and skip the stall */ SwrGetStats(ctx->swrContext, &swr_stats); /* SwrGetStats returns immediately, wait for collection */ SwrWaitForIdle(ctx->swrContext); switch (pq->type) { case PIPE_QUERY_OCCLUSION_PREDICATE: case PIPE_QUERY_OCCLUSION_COUNTER: result->u64 = swr_stats.DepthPassCount; break; case PIPE_QUERY_PRIMITIVES_GENERATED: result->u64 = swr_stats.IaPrimitives; break; case PIPE_QUERY_PRIMITIVES_EMITTED: result->u64 = swr_stats.SoNumPrimsWritten[pq->index]; break; case PIPE_QUERY_SO_STATISTICS: case PIPE_QUERY_SO_OVERFLOW_PREDICATE: { struct pipe_query_data_so_statistics *so_stats = &result->so_statistics; so_stats->num_primitives_written = swr_stats.SoNumPrimsWritten[pq->index]; so_stats->primitives_storage_needed = swr_stats.SoPrimStorageNeeded[pq->index]; } break; case PIPE_QUERY_PIPELINE_STATISTICS: { struct pipe_query_data_pipeline_statistics *p_stats = &result->pipeline_statistics; p_stats->ia_vertices = swr_stats.IaVertices; p_stats->ia_primitives = swr_stats.IaPrimitives; p_stats->vs_invocations = swr_stats.VsInvocations; p_stats->gs_invocations = swr_stats.GsInvocations; p_stats->gs_primitives = swr_stats.GsPrimitives; p_stats->c_invocations = swr_stats.CPrimitives; p_stats->c_primitives = swr_stats.CPrimitives; p_stats->ps_invocations = swr_stats.PsInvocations; p_stats->hs_invocations = swr_stats.HsInvocations; p_stats->ds_invocations = swr_stats.DsInvocations; p_stats->cs_invocations = swr_stats.CsInvocations; } break; default: assert(0 && "Unsupported query"); break; } /* Only change stat collection if there are no active queries */ if (ctx->active_queries == 0) SwrEnableStats(ctx->swrContext, enable_stats); }