Example #1
0
/**
 * 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;
}
Example #2
0
static boolean
llvmpipe_get_query_result(struct pipe_context *pipe, 
                          struct pipe_query *q,
                          boolean wait,
                          union pipe_query_result *vresult)
{
   struct llvmpipe_query *pq = llvmpipe_query(q);
   uint64_t *result = (uint64_t *)vresult;
   int i;

   if (!pq->fence) {
      /* no fence because there was no scene, so results is zero */
      *result = 0;
      return TRUE;
   }

   if (!lp_fence_signalled(pq->fence)) {
      if (!lp_fence_issued(pq->fence))
         llvmpipe_flush(pipe, NULL, __FUNCTION__);

      if (!wait)
         return FALSE;

      lp_fence_wait(pq->fence);
   }

   /* Sum the results from each of the threads:
    */
   *result = 0;

   switch (pq->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      for (i = 0; i < LP_MAX_THREADS; i++) {
         *result += pq->count[i];
      }
      break;
   case PIPE_QUERY_TIMESTAMP:
      for (i = 0; i < LP_MAX_THREADS; i++) {
         if (pq->count[i] > *result) {
            *result = pq->count[i];
         }
         if (*result == 0)
            *result = os_time_get_nano();
      }
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
      *result = pq->num_primitives_generated;
      break;
   case PIPE_QUERY_PRIMITIVES_EMITTED:
      *result = pq->num_primitives_written;
      break;
   default:
      assert(0);
      break;
   }

   return TRUE;
}
Example #3
0
void
llvmpipe_finish( struct pipe_context *pipe,
                 const char *reason )
{
   struct pipe_fence_handle *fence = NULL;
   llvmpipe_flush(pipe, &fence, reason);
   if (fence) {
      pipe->screen->fence_finish(pipe->screen, fence, PIPE_TIMEOUT_INFINITE);
      pipe->screen->fence_reference(pipe->screen, &fence, NULL);
   }
}
Example #4
0
static void
llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
   struct llvmpipe_query *pq = llvmpipe_query(q);

   /* Ideally we would refcount queries & not get destroyed until the
    * last scene had finished with us.
    */
   if (pq->fence) {
      if (!lp_fence_issued(pq->fence))
         llvmpipe_flush(pipe, NULL, __FUNCTION__);

      if (!lp_fence_signalled(pq->fence))
         lp_fence_wait(pq->fence);

      lp_fence_reference(&pq->fence, NULL);
   }

   FREE(pq);
}
Example #5
0
static void
do_flush( struct pipe_context *pipe,
          struct pipe_fence_handle **fence)
{
   llvmpipe_flush(pipe, fence, __FUNCTION__);
}
Example #6
0
static boolean
llvmpipe_get_query_result(struct pipe_context *pipe, 
                          struct pipe_query *q,
                          boolean wait,
                          union pipe_query_result *vresult)
{
   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
   unsigned num_threads = MAX2(1, screen->num_threads);
   struct llvmpipe_query *pq = llvmpipe_query(q);
   uint64_t *result = (uint64_t *)vresult;
   int i;

   if (pq->fence) {
      /* only have a fence if there was a scene */
      if (!lp_fence_signalled(pq->fence)) {
         if (!lp_fence_issued(pq->fence))
            llvmpipe_flush(pipe, NULL, __FUNCTION__);

         if (!wait)
            return FALSE;

         lp_fence_wait(pq->fence);
      }
   }

   /* Sum the results from each of the threads:
    */
   *result = 0;

   switch (pq->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      for (i = 0; i < num_threads; i++) {
         *result += pq->end[i];
      }
      break;
   case PIPE_QUERY_OCCLUSION_PREDICATE:
      for (i = 0; i < num_threads; i++) {
         /* safer (still not guaranteed) when there's an overflow */
         vresult->b = vresult->b || pq->end[i];
      }
      break;
   case PIPE_QUERY_TIMESTAMP:
      for (i = 0; i < num_threads; i++) {
         if (pq->end[i] > *result) {
            *result = pq->end[i];
         }
      }
      break;
   case PIPE_QUERY_TIMESTAMP_DISJOINT: {
      struct pipe_query_data_timestamp_disjoint *td =
         (struct pipe_query_data_timestamp_disjoint *)vresult;
      /* os_get_time_nano return nanoseconds */
      td->frequency = UINT64_C(1000000000);
      td->disjoint = FALSE;
   }
      break;
   case PIPE_QUERY_GPU_FINISHED:
      vresult->b = TRUE;
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
      *result = pq->num_primitives_generated;
      break;
   case PIPE_QUERY_PRIMITIVES_EMITTED:
      *result = pq->num_primitives_written;
      break;
   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
      vresult->b = pq->num_primitives_generated > pq->num_primitives_written;
      break;
   case PIPE_QUERY_SO_STATISTICS: {
      struct pipe_query_data_so_statistics *stats =
         (struct pipe_query_data_so_statistics *)vresult;
      stats->num_primitives_written = pq->num_primitives_written;
      stats->primitives_storage_needed = pq->num_primitives_generated;
   }
      break;
   case PIPE_QUERY_PIPELINE_STATISTICS: {
      struct pipe_query_data_pipeline_statistics *stats =
         (struct pipe_query_data_pipeline_statistics *)vresult;
      /* only ps_invocations come from binned query */
      for (i = 0; i < num_threads; i++) {
         pq->stats.ps_invocations += pq->end[i];
      }
      pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
      *stats = pq->stats;
   }
      break;
   default:
      assert(0);
      break;
   }

   return TRUE;
}