static void llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); struct llvmpipe_query *pq = llvmpipe_query(q); /* Check if the query is already in the scene. If so, we need to * flush the scene now. Real apps shouldn't re-use a query in a * frame of rendering. */ if (pq->fence && !lp_fence_issued(pq->fence)) { llvmpipe_finish(pipe, __FUNCTION__); } memset(pq->count, 0, sizeof(pq->count)); lp_setup_begin_query(llvmpipe->setup, pq); if (pq->type == PIPE_QUERY_PRIMITIVES_EMITTED) { pq->num_primitives_written = 0; llvmpipe->so_stats.num_primitives_written = 0; } if (pq->type == PIPE_QUERY_PRIMITIVES_GENERATED) { pq->num_primitives_generated = 0; llvmpipe->num_primitives_generated = 0; } if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) { llvmpipe->active_occlusion_query = TRUE; llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; } }
/** * Flush context if necessary. * * Returns FALSE if it would have block, but do_not_block was set, TRUE * otherwise. * * TODO: move this logic to an auxiliary library? */ boolean llvmpipe_flush_resource(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, boolean read_only, boolean cpu_access, boolean do_not_block, const char *reason) { unsigned referenced; referenced = llvmpipe_is_resource_referenced(pipe, resource, level); if ((referenced & LP_REFERENCED_FOR_WRITE) || ((referenced & LP_REFERENCED_FOR_READ) && !read_only)) { if (cpu_access) { /* * Flush and wait. */ if (do_not_block) return FALSE; llvmpipe_finish(pipe, reason); } else { /* * Just flush. */ llvmpipe_flush(pipe, NULL, reason); } } return TRUE; }
/** * Update fragment state. This is called just prior to drawing * something when some fragment-related state has changed. */ void llvmpipe_update_fs(struct llvmpipe_context *lp) { struct lp_fragment_shader *shader = lp->fs; struct lp_fragment_shader_variant_key key; struct lp_fragment_shader_variant *variant = NULL; struct lp_fs_variant_list_item *li; make_variant_key(lp, shader, &key); li = first_elem(&shader->variants); while(!at_end(&shader->variants, li)) { if(memcmp(&li->base->key, &key, shader->variant_key_size) == 0) { variant = li->base; break; } li = next_elem(li); } if (variant) { move_to_head(&lp->fs_variants_list, &variant->list_item_global); } else { int64_t t0, t1; int64_t dt; unsigned i; if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) { struct pipe_context *pipe = &lp->pipe; /* * XXX: we need to flush the context until we have some sort of reference * counting in fragment shaders as they may still be binned * Flushing alone might not be sufficient we need to wait on it too. */ llvmpipe_finish(pipe, __FUNCTION__); for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) { struct lp_fs_variant_list_item *item = last_elem(&lp->fs_variants_list); remove_shader_variant(lp, item->base); } } t0 = os_time_get(); variant = generate_variant(lp, shader, &key); t1 = os_time_get(); dt = t1 - t0; LP_COUNT_ADD(llvm_compile_time, dt); LP_COUNT_ADD(nr_llvm_compiles, 2); /* emit vs. omit in/out test */ if (variant) { insert_at_head(&shader->variants, &variant->list_item_local); insert_at_head(&lp->fs_variants_list, &variant->list_item_global); lp->nr_fs_variants++; shader->variants_cached++; } } lp_setup_set_fs_variant(lp->setup, variant); }
static void llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct lp_fragment_shader *shader = fs; struct lp_fs_variant_list_item *li; assert(fs != llvmpipe->fs); (void) llvmpipe; /* * XXX: we need to flush the context until we have some sort of reference * counting in fragment shaders as they may still be binned * Flushing alone might not sufficient we need to wait on it too. */ llvmpipe_finish(pipe, __FUNCTION__); li = first_elem(&shader->variants); while(!at_end(&shader->variants, li)) { struct lp_fs_variant_list_item *next = next_elem(li); remove_shader_variant(llvmpipe, li->base); li = next; } assert(shader->variants_cached == 0); FREE((void *) shader->base.tokens); FREE(shader); }
static void llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); struct llvmpipe_query *pq = llvmpipe_query(q); /* Check if the query is already in the scene. If so, we need to * flush the scene now. Real apps shouldn't re-use a query in a * frame of rendering. */ if (pq->fence && !lp_fence_issued(pq->fence)) { llvmpipe_finish(pipe, __FUNCTION__); } memset(pq->start, 0, sizeof(pq->start)); memset(pq->end, 0, sizeof(pq->end)); lp_setup_begin_query(llvmpipe->setup, pq); switch (pq->type) { case PIPE_QUERY_PRIMITIVES_EMITTED: pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; break; case PIPE_QUERY_PRIMITIVES_GENERATED: pq->num_primitives_generated = llvmpipe->so_stats.primitives_storage_needed; break; case PIPE_QUERY_SO_STATISTICS: pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; pq->num_primitives_generated = llvmpipe->so_stats.primitives_storage_needed; break; case PIPE_QUERY_SO_OVERFLOW_PREDICATE: pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; pq->num_primitives_generated = llvmpipe->so_stats.primitives_storage_needed; break; case PIPE_QUERY_PIPELINE_STATISTICS: /* reset our cache */ if (llvmpipe->active_statistics_queries == 0) { memset(&llvmpipe->pipeline_statistics, 0, sizeof(llvmpipe->pipeline_statistics)); } memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats)); llvmpipe->active_statistics_queries++; break; case PIPE_QUERY_OCCLUSION_COUNTER: case PIPE_QUERY_OCCLUSION_PREDICATE: llvmpipe->active_occlusion_queries++; llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; break; default: break; } }