Exemple #1
0
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);
}
Exemple #5
0
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;
   }
}