예제 #1
0
static bool
nv50_hw_query_allocate(struct nv50_context *nv50, struct nv50_query *q,
                       int size)
{
   struct nv50_screen *screen = nv50->screen;
   struct nv50_hw_query *hq = nv50_hw_query(q);
   int ret;

   if (hq->bo) {
      nouveau_bo_ref(NULL, &hq->bo);
      if (hq->mm) {
         if (hq->state == NV50_HW_QUERY_STATE_READY)
            nouveau_mm_free(hq->mm);
         else
            nouveau_fence_work(screen->base.fence.current,
                               nouveau_mm_free_work, hq->mm);
      }
   }
   if (size) {
      hq->mm = nouveau_mm_allocate(screen->base.mm_GART, size,
                                   &hq->bo, &hq->base_offset);
      if (!hq->bo)
         return false;
      hq->offset = hq->base_offset;

      ret = nouveau_bo_map(hq->bo, 0, screen->base.client);
      if (ret) {
         nv50_hw_query_allocate(nv50, q, 0);
         return false;
      }
      hq->data = (uint32_t *)((uint8_t *)hq->bo->map + hq->base_offset);
   }
   return true;
}
예제 #2
0
struct nv50_hw_query *
nv50_hw_sm_create_query(struct nv50_context *nv50, unsigned type)
{
   struct nv50_hw_sm_query *hsq;
   struct nv50_hw_query *hq;
   unsigned space;

   if (type < NV50_HW_SM_QUERY(0) || type > NV50_HW_SM_QUERY_LAST)
      return NULL;

   hsq = CALLOC_STRUCT(nv50_hw_sm_query);
   if (!hsq)
      return NULL;

   hq = &hsq->base;
   hq->funcs = &hw_sm_query_funcs;
   hq->base.type = type;

   /*
    * for each MP:
    * [00] = MP.C0
    * [04] = MP.C1
    * [08] = MP.C2
    * [0c] = MP.C3
    * [10] = MP.sequence
    */
   space = (4 + 1) * nv50->screen->MPsInTP * sizeof(uint32_t);

   if (!nv50_hw_query_allocate(nv50, &hq->base, space)) {
      FREE(hq);
      return NULL;
   }

   return hq;
}
예제 #3
0
static void
nv50_hw_destroy_query(struct nv50_context *nv50, struct nv50_query *q)
{
   struct nv50_hw_query *hq = nv50_hw_query(q);
   nv50_hw_query_allocate(nv50, q, 0);
   nouveau_fence_ref(NULL, &hq->fence);
   FREE(hq);
}
예제 #4
0
static void
nv50_hw_destroy_query(struct nv50_context *nv50, struct nv50_query *q)
{
   struct nv50_hw_query *hq = nv50_hw_query(q);

   if (hq->funcs && hq->funcs->destroy_query) {
      hq->funcs->destroy_query(nv50, hq);
      return;
   }

   nv50_hw_query_allocate(nv50, q, 0);
   nouveau_fence_ref(NULL, &hq->fence);
   FREE(hq);
}
예제 #5
0
struct nv50_query *
nv50_hw_create_query(struct nv50_context *nv50, unsigned type, unsigned index)
{
   struct nv50_hw_query *hq;
   struct nv50_query *q;

   hq = CALLOC_STRUCT(nv50_hw_query);
   if (!hq)
      return NULL;

   q = &hq->base;
   q->funcs = &hw_query_funcs;
   q->type = type;

   switch (q->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      hq->rotate = 32;
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
   case PIPE_QUERY_PRIMITIVES_EMITTED:
   case PIPE_QUERY_SO_STATISTICS:
   case PIPE_QUERY_PIPELINE_STATISTICS:
      hq->is64bit = true;
      break;
   case PIPE_QUERY_TIME_ELAPSED:
   case PIPE_QUERY_TIMESTAMP:
   case PIPE_QUERY_TIMESTAMP_DISJOINT:
   case PIPE_QUERY_GPU_FINISHED:
   case NVA0_HW_QUERY_STREAM_OUTPUT_BUFFER_OFFSET:
      break;
   default:
      debug_printf("invalid query type: %u\n", type);
      FREE(q);
      return NULL;
   }

   if (!nv50_hw_query_allocate(nv50, q, NV50_HW_QUERY_ALLOC_SPACE)) {
      FREE(hq);
      return NULL;
   }

   if (hq->rotate) {
      /* we advance before query_begin ! */
      hq->offset -= hq->rotate;
      hq->data -= hq->rotate / sizeof(*hq->data);
   }

   return q;
}
예제 #6
0
static boolean
nv50_hw_begin_query(struct nv50_context *nv50, struct nv50_query *q)
{
   struct nouveau_pushbuf *push = nv50->base.pushbuf;
   struct nv50_hw_query *hq = nv50_hw_query(q);

   /* For occlusion queries we have to change the storage, because a previous
    * query might set the initial render condition to false even *after* we re-
    * initialized it to true.
    */
   if (hq->rotate) {
      hq->offset += hq->rotate;
      hq->data += hq->rotate / sizeof(*hq->data);
      if (hq->offset - hq->base_offset == NV50_HW_QUERY_ALLOC_SPACE)
         nv50_hw_query_allocate(nv50, q, NV50_HW_QUERY_ALLOC_SPACE);

      /* XXX: can we do this with the GPU, and sync with respect to a previous
       *  query ?
       */
      hq->data[0] = hq->sequence; /* initialize sequence */
      hq->data[1] = 1; /* initial render condition = true */
      hq->data[4] = hq->sequence + 1; /* for comparison COND_MODE */
      hq->data[5] = 0;
   }
   if (!hq->is64bit)
      hq->data[0] = hq->sequence++; /* the previously used one */

   switch (q->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      hq->nesting = nv50->screen->num_occlusion_queries_active++;
      if (hq->nesting) {
         nv50_hw_query_get(push, q, 0x10, 0x0100f002);
      } else {
         PUSH_SPACE(push, 4);
         BEGIN_NV04(push, NV50_3D(COUNTER_RESET), 1);
         PUSH_DATA (push, NV50_3D_COUNTER_RESET_SAMPLECNT);
         BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1);
         PUSH_DATA (push, 1);
      }
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
      nv50_hw_query_get(push, q, 0x10, 0x06805002);
      break;
   case PIPE_QUERY_PRIMITIVES_EMITTED:
      nv50_hw_query_get(push, q, 0x10, 0x05805002);
      break;
   case PIPE_QUERY_SO_STATISTICS:
      nv50_hw_query_get(push, q, 0x20, 0x05805002);
      nv50_hw_query_get(push, q, 0x30, 0x06805002);
      break;
   case PIPE_QUERY_PIPELINE_STATISTICS:
      nv50_hw_query_get(push, q, 0x80, 0x00801002); /* VFETCH, VERTICES */
      nv50_hw_query_get(push, q, 0x90, 0x01801002); /* VFETCH, PRIMS */
      nv50_hw_query_get(push, q, 0xa0, 0x02802002); /* VP, LAUNCHES */
      nv50_hw_query_get(push, q, 0xb0, 0x03806002); /* GP, LAUNCHES */
      nv50_hw_query_get(push, q, 0xc0, 0x04806002); /* GP, PRIMS_OUT */
      nv50_hw_query_get(push, q, 0xd0, 0x07804002); /* RAST, PRIMS_IN */
      nv50_hw_query_get(push, q, 0xe0, 0x08804002); /* RAST, PRIMS_OUT */
      nv50_hw_query_get(push, q, 0xf0, 0x0980a002); /* ROP, PIXELS */
      break;
   case PIPE_QUERY_TIME_ELAPSED:
      nv50_hw_query_get(push, q, 0x10, 0x00005002);
      break;
   default:
      assert(0);
      return false;
   }
   hq->state = NV50_HW_QUERY_STATE_ACTIVE;
   return true;
}