示例#1
0
void
nve4_p2mf_push_linear(struct nouveau_context *nv,
                      struct nouveau_bo *dst, unsigned offset, unsigned domain,
                      unsigned size, const void *data)
{
   struct nvc0_context *nvc0 = nvc0_context(&nv->pipe);
   struct nouveau_pushbuf *push = nv->pushbuf;
   uint32_t *src = (uint32_t *)data;
   unsigned count = (size + 3) / 4;

   nouveau_bufctx_refn(nvc0->bufctx, 0, dst, domain | NOUVEAU_BO_WR);
   nouveau_pushbuf_bufctx(push, nvc0->bufctx);
   nouveau_pushbuf_validate(push);

   while (count) {
      unsigned nr = MIN2(count, (NV04_PFIFO_MAX_PACKET_LEN - 1));

      if (!PUSH_SPACE(push, nr + 10))
         break;

      BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2);
      PUSH_DATAh(push, dst->offset + offset);
      PUSH_DATA (push, dst->offset + offset);
      BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN), 2);
      PUSH_DATA (push, MIN2(size, nr * 4));
      PUSH_DATA (push, 1);
      /* must not be interrupted (trap on QUERY fence, 0x50 works however) */
      BEGIN_1IC0(push, NVE4_P2MF(UPLOAD_EXEC), nr + 1);
      PUSH_DATA (push, 0x1001);
      PUSH_DATAp(push, src, nr);

      count -= nr;
      src += nr;
      offset += nr * 4;
      size -= nr * 4;
   }

   nouveau_bufctx_reset(nvc0->bufctx, 0);
}
示例#2
0
static void
nv50_set_index_buffer(struct pipe_context *pipe,
                      const struct pipe_index_buffer *ib)
{
   struct nv50_context *nv50 = nv50_context(pipe);

   if (nv50->idxbuf.buffer)
      nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_INDEX);

   if (ib) {
      pipe_resource_reference(&nv50->idxbuf.buffer, ib->buffer);
      nv50->idxbuf.index_size = ib->index_size;
      if (ib->buffer) {
         nv50->idxbuf.offset = ib->offset;
         BCTX_REFN(nv50->bufctx_3d, INDEX, nv04_resource(ib->buffer), RD);
      } else {
         nv50->idxbuf.user_buffer = ib->user_buffer;
      }
   } else {
      pipe_resource_reference(&nv50->idxbuf.buffer, NULL);
   }
}
static void
nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
                         struct pipe_constant_buffer *cb)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   struct pipe_resource *res = cb ? cb->buffer : NULL;
   const unsigned s = nv50_context_shader_stage(shader);
   const unsigned i = index;

   if (shader == PIPE_SHADER_COMPUTE)
      return;

   assert(i < NV50_MAX_PIPE_CONSTBUFS);
   if (nv50->constbuf[s][i].user)
      nv50->constbuf[s][i].u.buf = NULL;
   else
   if (nv50->constbuf[s][i].u.buf)
      nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i));

   pipe_resource_reference(&nv50->constbuf[s][i].u.buf, res);

   nv50->constbuf[s][i].user = (cb && cb->user_buffer) ? TRUE : FALSE;
   if (nv50->constbuf[s][i].user) {
      nv50->constbuf[s][i].u.data = cb->user_buffer;
      nv50->constbuf[s][i].size = MIN2(cb->buffer_size, 0x10000);
      nv50->constbuf_valid[s] |= 1 << i;
   } else
   if (res) {
      nv50->constbuf[s][i].offset = cb->buffer_offset;
      nv50->constbuf[s][i].size = MIN2(align(cb->buffer_size, 0x100), 0x10000);
      nv50->constbuf_valid[s] |= 1 << i;
   } else {
      nv50->constbuf_valid[s] &= ~(1 << i);
   }
   nv50->constbuf_dirty[s] |= 1 << i;

   nv50->dirty |= NV50_NEW_CONSTBUF;
}
static void
nv50_set_framebuffer_state(struct pipe_context *pipe,
                           const struct pipe_framebuffer_state *fb)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   unsigned i;

   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);

   for (i = 0; i < fb->nr_cbufs; ++i)
      pipe_surface_reference(&nv50->framebuffer.cbufs[i], fb->cbufs[i]);
   for (; i < nv50->framebuffer.nr_cbufs; ++i)
      pipe_surface_reference(&nv50->framebuffer.cbufs[i], NULL);

   nv50->framebuffer.nr_cbufs = fb->nr_cbufs;

   nv50->framebuffer.width = fb->width;
   nv50->framebuffer.height = fb->height;

   pipe_surface_reference(&nv50->framebuffer.zsbuf, fb->zsbuf);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
示例#5
0
static void
nvc0_m2mf_copy_linear(struct nouveau_context *nv,
                      struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
                      struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
                      unsigned size)
{
   struct nouveau_pushbuf *push = nv->pushbuf;
   struct nouveau_bufctx *bctx = nvc0_context(&nv->pipe)->bufctx;

   nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD);
   nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR);
   nouveau_pushbuf_bufctx(push, bctx);
   nouveau_pushbuf_validate(push);

   while (size) {
      unsigned bytes = MIN2(size, 1 << 17);

      BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2);
      PUSH_DATAh(push, dst->offset + dstoff);
      PUSH_DATA (push, dst->offset + dstoff);
      BEGIN_NVC0(push, NVC0_M2MF(OFFSET_IN_HIGH), 2);
      PUSH_DATAh(push, src->offset + srcoff);
      PUSH_DATA (push, src->offset + srcoff);
      BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2);
      PUSH_DATA (push, bytes);
      PUSH_DATA (push, 1);
      BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1);
      PUSH_DATA (push, (1 << NVC0_M2MF_EXEC_INC__SHIFT) |
                 NVC0_M2MF_EXEC_LINEAR_IN | NVC0_M2MF_EXEC_LINEAR_OUT);

      srcoff += bytes;
      dstoff += bytes;
      size -= bytes;
   }

   nouveau_bufctx_reset(bctx, 0);
}
示例#6
0
void
nvc0_cb_push(struct nouveau_context *nv,
             struct nouveau_bo *bo, unsigned domain,
             unsigned base, unsigned size,
             unsigned offset, unsigned words, const uint32_t *data)
{
   struct nouveau_bufctx *bctx = nvc0_context(&nv->pipe)->bufctx;
   struct nouveau_pushbuf *push = nv->pushbuf;

   assert(!(offset & 3));
   size = align(size, 0x100);

   nouveau_bufctx_refn(bctx, 0, bo, NOUVEAU_BO_WR | domain);
   nouveau_pushbuf_bufctx(push, bctx);
   nouveau_pushbuf_validate(push);

   BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
   PUSH_DATA (push, size);
   PUSH_DATAh(push, bo->offset + base);
   PUSH_DATA (push, bo->offset + base);

   while (words) {
      unsigned nr = PUSH_AVAIL(push);
      nr = MIN2(nr, words);
      nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);

      BEGIN_1IC0(push, NVC0_3D(CB_POS), nr + 1);
      PUSH_DATA (push, offset);
      PUSH_DATAp(push, data, nr);

      words -= nr;
      data += nr;
      offset += nr * 4;
   }

   nouveau_bufctx_reset(bctx, 0);
}
static void
nv50_set_vertex_buffers(struct pipe_context *pipe,
                        unsigned start_slot, unsigned count,
                        const struct pipe_vertex_buffer *vb)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   unsigned i;

   util_set_vertex_buffers_count(nv50->vtxbuf, &nv50->num_vtxbufs, vb,
                                 start_slot, count);

   if (!vb) {
      nv50->vbo_user &= ~(((1ull << count) - 1) << start_slot);
      nv50->vbo_constant &= ~(((1ull << count) - 1) << start_slot);
      return;
   }

   for (i = 0; i < count; ++i) {
      unsigned dst_index = start_slot + i;

      if (!vb[i].buffer && vb[i].user_buffer) {
         nv50->vbo_user |= 1 << dst_index;
         if (!vb[i].stride)
            nv50->vbo_constant |= 1 << dst_index;
         else
            nv50->vbo_constant &= ~(1 << dst_index);
      } else {
         nv50->vbo_user &= ~(1 << dst_index);
         nv50->vbo_constant &= ~(1 << dst_index);
      }
   }

   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX);

   nv50->dirty |= NV50_NEW_ARRAYS;
}
示例#8
0
static void
nvc0_set_index_buffer(struct pipe_context *pipe,
                      const struct pipe_index_buffer *ib)
{
    struct nvc0_context *nvc0 = nvc0_context(pipe);

    if (nvc0->idxbuf.buffer)
       nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_IDX);

    if (ib) {
       pipe_resource_reference(&nvc0->idxbuf.buffer, ib->buffer);
       nvc0->idxbuf.index_size = ib->index_size;
       if (ib->buffer) {
          nvc0->idxbuf.offset = ib->offset;
          nvc0->dirty_3d |= NVC0_NEW_3D_IDXBUF;
       } else {
          nvc0->idxbuf.user_buffer = ib->user_buffer;
          nvc0->dirty_3d &= ~NVC0_NEW_3D_IDXBUF;
       }
    } else {
       nvc0->dirty_3d &= ~NVC0_NEW_3D_IDXBUF;
       pipe_resource_reference(&nvc0->idxbuf.buffer, NULL);
    }
}
示例#9
0
void
nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
{
   struct push_context ctx;
   unsigned i, index_size;
   unsigned inst_count = info->instance_count;
   unsigned vert_count = info->count;
   unsigned prim;

   nvc0_push_context_init(nvc0, &ctx);

   nvc0_vertex_configure_translate(nvc0, info->index_bias);

   if (nvc0->state.index_bias) {
      /* this is already taken care of by translate */
      IMMED_NVC0(ctx.push, NVC0_3D(VB_ELEMENT_BASE), 0);
      nvc0->state.index_bias = 0;
   }

   if (unlikely(ctx.edgeflag.enabled))
      nvc0_push_map_edgeflag(&ctx, nvc0, info->index_bias);

   ctx.prim_restart = info->primitive_restart;
   ctx.restart_index = info->restart_index;

   if (info->primitive_restart) {
      /* NOTE: I hope we won't ever need that last index (~0).
       * If we do, we have to disable primitive restart here always and
       * use END,BEGIN to restart. (XXX: would that affect PrimitiveID ?)
       * We could also deactive PRIM_RESTART_WITH_DRAW_ARRAYS temporarily,
       * and add manual restart to disp_vertices_seq.
       */
      BEGIN_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 2);
      PUSH_DATA (ctx.push, 1);
      PUSH_DATA (ctx.push, info->indexed ? 0xffffffff : info->restart_index);
   } else
   if (nvc0->state.prim_restart) {
      IMMED_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 0);
   }
   nvc0->state.prim_restart = info->primitive_restart;

   if (info->indexed) {
      nvc0_push_map_idxbuf(&ctx, nvc0);
      index_size = nvc0->idxbuf.index_size;
   } else {
      if (unlikely(info->count_from_stream_output)) {
         struct pipe_context *pipe = &nvc0->base.pipe;
         struct nvc0_so_target *targ;
         targ = nvc0_so_target(info->count_from_stream_output);
         pipe->get_query_result(pipe, targ->pq, true, (void *)&vert_count);
         vert_count /= targ->stride;
      }
      ctx.idxbuf = NULL; /* shut up warnings */
      index_size = 0;
   }

   ctx.instance_id = info->start_instance;

   prim = nvc0_prim_gl(info->mode);
   do {
      PUSH_SPACE(ctx.push, 9);

      ctx.dest = nvc0_push_setup_vertex_array(nvc0, vert_count);
      if (unlikely(!ctx.dest))
         break;

      if (unlikely(ctx.need_vertex_id))
         nvc0_push_upload_vertex_ids(&ctx, nvc0, info);

      if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS)
         IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0);
      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1);
      PUSH_DATA (ctx.push, prim);
      switch (index_size) {
      case 1:
         disp_vertices_i08(&ctx, info->start, vert_count);
         break;
      case 2:
         disp_vertices_i16(&ctx, info->start, vert_count);
         break;
      case 4:
         disp_vertices_i32(&ctx, info->start, vert_count);
         break;
      default:
         assert(index_size == 0);
         disp_vertices_seq(&ctx, info->start, vert_count);
         break;
      }
      PUSH_SPACE(ctx.push, 1);
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0);

      if (--inst_count) {
         prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
         ++ctx.instance_id;
      }
      nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX_TMP);
      nouveau_scratch_done(&nvc0->base);
   } while (inst_count);


   /* reset state and unmap buffers (no-op) */

   if (unlikely(!ctx.edgeflag.value)) {
      PUSH_SPACE(ctx.push, 1);
      IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1);
   }

   if (unlikely(ctx.need_vertex_id)) {
      PUSH_SPACE(ctx.push, 4);
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0);
      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(1)), 1);
      PUSH_DATA (ctx.push,
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST |
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 0);
   }

   if (info->indexed)
      nouveau_resource_unmap(nv04_resource(nvc0->idxbuf.buffer));
   for (i = 0; i < nvc0->num_vtxbufs; ++i)
      nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer));

   NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_fallback_count, 1);
}
void
nvc0_tfb_validate(struct nvc0_context *nvc0)
{
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nvc0_transform_feedback_state *tfb;
   unsigned b;

   if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb;
   else
   if (nvc0->tevlprog) tfb = nvc0->tevlprog->tfb;
   else
      tfb = nvc0->vertprog->tfb;

   IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0);

   if (tfb && tfb != nvc0->state.tfb) {
      for (b = 0; b < 4; ++b) {
         if (tfb->varying_count[b]) {
            unsigned n = (tfb->varying_count[b] + 3) / 4;

            BEGIN_NVC0(push, NVC0_3D(TFB_STREAM(b)), 3);
            PUSH_DATA (push, 0);
            PUSH_DATA (push, tfb->varying_count[b]);
            PUSH_DATA (push, tfb->stride[b]);
            BEGIN_NVC0(push, NVC0_3D(TFB_VARYING_LOCS(b, 0)), n);
            PUSH_DATAp(push, tfb->varying_index[b], n);

            if (nvc0->tfbbuf[b])
               nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b];
         } else {
            IMMED_NVC0(push, NVC0_3D(TFB_VARYING_COUNT(b)), 0);
         }
      }
   }
   nvc0->state.tfb = tfb;

   if (!(nvc0->dirty & NVC0_NEW_TFB_TARGETS))
      return;
   nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TFB);

   for (b = 0; b < nvc0->num_tfbbufs; ++b) {
      struct nvc0_so_target *targ = nvc0_so_target(nvc0->tfbbuf[b]);
      struct nv04_resource *buf = nv04_resource(targ->pipe.buffer);

      if (tfb)
         targ->stride = tfb->stride[b];

      if (!(nvc0->tfbbuf_dirty & (1 << b)))
         continue;

      if (!targ->clean)
         nvc0_query_fifo_wait(push, targ->pq);
      BEGIN_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 5);
      PUSH_DATA (push, 1);
      PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset);
      PUSH_DATA (push, buf->address + targ->pipe.buffer_offset);
      PUSH_DATA (push, targ->pipe.buffer_size);
      if (!targ->clean) {
         nvc0_query_pushbuf_submit(push, targ->pq, 0x4);
      } else {
         PUSH_DATA(push, 0); /* TFB_BUFFER_OFFSET */
         targ->clean = FALSE;
      }
      BCTX_REFN(nvc0->bufctx_3d, TFB, buf, WR);
   }
   for (; b < 4; ++b)
      IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0);
}
示例#11
0
static void
nvc0_resource_copy_region(struct pipe_context *pipe,
                          struct pipe_resource *dst, unsigned dst_level,
                          unsigned dstx, unsigned dsty, unsigned dstz,
                          struct pipe_resource *src, unsigned src_level,
                          const struct pipe_box *src_box)
{
   struct nvc0_context *nvc0 = nvc0_context(pipe);
   int ret;
   boolean m2mf;
   unsigned dst_layer = dstz, src_layer = src_box->z;

   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
      nouveau_copy_buffer(&nvc0->base,
                          nv04_resource(dst), dstx,
                          nv04_resource(src), src_box->x, src_box->width);
      NOUVEAU_DRV_STAT(&nvc0->screen->base, buf_copy_bytes, src_box->width);
      return;
   }
   NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_copy_count, 1);

   /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
   assert((src->nr_samples | 1) == (dst->nr_samples | 1));

   m2mf = (src->format == dst->format) ||
      (util_format_get_blocksizebits(src->format) ==
       util_format_get_blocksizebits(dst->format));

   nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;

   if (m2mf) {
      struct nv50_m2mf_rect drect, srect;
      unsigned i;
      unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
      unsigned ny = util_format_get_nblocksy(src->format, src_box->height);

      nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
      nv50_m2mf_rect_setup(&srect, src, src_level,
                           src_box->x, src_box->y, src_box->z);

      for (i = 0; i < src_box->depth; ++i) {
         nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny);

         if (nv50_miptree(dst)->layout_3d)
            drect.z++;
         else
            drect.base += nv50_miptree(dst)->layer_stride;

         if (nv50_miptree(src)->layout_3d)
            srect.z++;
         else
            srect.base += nv50_miptree(src)->layer_stride;
      }
      return;
   }

   assert(nv50_2d_dst_format_faithful(dst->format));
   assert(nv50_2d_src_format_faithful(src->format));

   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD);
   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR);
   nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
   nouveau_pushbuf_validate(nvc0->base.pushbuf);

   for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
      ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf,
                                    nv50_miptree(dst), dst_level,
                                    dstx, dsty, dst_layer,
                                    nv50_miptree(src), src_level,
                                    src_box->x, src_box->y, src_layer,
                                    src_box->width, src_box->height);
      if (ret)
         break;
   }
   nouveau_bufctx_reset(nvc0->bufctx, 0);
}
示例#12
0
static bool
nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s,
                       unsigned start, unsigned nr,
                       struct pipe_image_view *pimages)
{
   const unsigned end = start + nr;
   unsigned mask = 0;
   unsigned i;

   assert(s < 6);

   if (pimages) {
      for (i = start; i < end; ++i) {
         struct pipe_image_view *img = &nvc0->images[s][i];
         const unsigned p = i - start;

         if (img->resource == pimages[p].resource &&
             img->format == pimages[p].format &&
             img->access == pimages[p].access) {
            if (img->resource == NULL)
               continue;
            if (img->resource->target == PIPE_BUFFER &&
                img->u.buf.first_element == pimages[p].u.buf.first_element &&
                img->u.buf.last_element == pimages[p].u.buf.last_element)
               continue;
            if (img->resource->target != PIPE_BUFFER &&
                img->u.tex.first_layer == pimages[p].u.tex.first_layer &&
                img->u.tex.last_layer == pimages[p].u.tex.last_layer &&
                img->u.tex.level == pimages[p].u.tex.level)
               continue;
         }

         mask |= (1 << i);
         if (pimages[p].resource)
            nvc0->images_valid[s] |= (1 << i);
         else
            nvc0->images_valid[s] &= ~(1 << i);

         img->format = pimages[p].format;
         img->access = pimages[p].access;
         if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER)
            img->u.buf = pimages[p].u.buf;
         else
            img->u.tex = pimages[p].u.tex;

         pipe_resource_reference(
               &img->resource, pimages[p].resource);
      }
      if (!mask)
         return false;
   } else {
      mask = ((1 << nr) - 1) << start;
      if (!(nvc0->images_valid[s] & mask))
         return false;
      for (i = start; i < end; ++i)
         pipe_resource_reference(&nvc0->images[s][i].resource, NULL);
      nvc0->images_valid[s] &= ~mask;
   }
   nvc0->images_dirty[s] |= mask;

   if (s == 5)
      nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
   else
      nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF);

   return true;
}
示例#13
0
static int
nv50_invalidate_resource_storage(struct nouveau_context *ctx,
                                 struct pipe_resource *res,
                                 int ref)
{
   struct nv50_context *nv50 = nv50_context(&ctx->pipe);
   unsigned s, i;

   if (res->bind & PIPE_BIND_RENDER_TARGET) {
      for (i = 0; i < nv50->framebuffer.nr_cbufs; ++i) {
         if (nv50->framebuffer.cbufs[i] &&
             nv50->framebuffer.cbufs[i]->texture == res) {
            nv50->dirty |= NV50_NEW_FRAMEBUFFER;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
            if (!--ref)
               return ref;
         }
      }
   }
   if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
      if (nv50->framebuffer.zsbuf &&
          nv50->framebuffer.zsbuf->texture == res) {
         nv50->dirty |= NV50_NEW_FRAMEBUFFER;
         nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
         if (!--ref)
            return ref;
      }
   }

   if (res->bind & PIPE_BIND_VERTEX_BUFFER) {
      for (i = 0; i < nv50->num_vtxbufs; ++i) {
         if (nv50->vtxbuf[i].buffer == res) {
            nv50->dirty |= NV50_NEW_ARRAYS;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX);
            if (!--ref)
               return ref;
         }
      }
   }
   if (res->bind & PIPE_BIND_INDEX_BUFFER) {
      if (nv50->idxbuf.buffer == res)
         if (!--ref)
            return ref;
   }

   if (res->bind & PIPE_BIND_SAMPLER_VIEW) {
      for (s = 0; s < 5; ++s) {
      for (i = 0; i < nv50->num_textures[s]; ++i) {
         if (nv50->textures[s][i] &&
             nv50->textures[s][i]->texture == res) {
            nv50->dirty |= NV50_NEW_TEXTURES;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
            if (!--ref)
               return ref;
         }
      }
      }
   }

   if (res->bind & PIPE_BIND_CONSTANT_BUFFER) {
      for (s = 0; s < 5; ++s) {
      for (i = 0; i < nv50->num_vtxbufs; ++i) {
         if (!nv50->constbuf[s][i].user &&
             nv50->constbuf[s][i].u.buf == res) {
            nv50->dirty |= NV50_NEW_CONSTBUF;
            nv50->constbuf_dirty[s] |= 1 << i;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i));
            if (!--ref)
               return ref;
         }
      }
      }
   }

   return ref;
}
static void
nv50_hw_sm_end_query(struct nv50_context *nv50, struct nv50_hw_query *hq)
{
   struct nv50_screen *screen = nv50->screen;
   struct pipe_context *pipe = &nv50->base.pipe;
   struct nouveau_pushbuf *push = nv50->base.pushbuf;
   struct nv50_hw_sm_query *hsq = nv50_hw_sm_query(hq);
   struct pipe_grid_info info = {};
   uint32_t mask;
   uint32_t input[3];
   const uint block[3] = { 32, 1, 1 };
   const uint grid[3] = { screen->MPsInTP, screen->TPs, 1 };
   int c, i;

   if (unlikely(!screen->pm.prog)) {
      struct nv50_program *prog = CALLOC_STRUCT(nv50_program);
      prog->type = PIPE_SHADER_COMPUTE;
      prog->translated = true;
      prog->max_gpr = 7;
      prog->parm_size = 8;
      prog->code = (uint32_t *)nv50_read_hw_sm_counters_code;
      prog->code_size = sizeof(nv50_read_hw_sm_counters_code);
      screen->pm.prog = prog;
   }

   /* disable all counting */
   PUSH_SPACE(push, 8);
   for (c = 0; c < 4; c++) {
      if (screen->pm.mp_counter[c]) {
         BEGIN_NV04(push, NV50_COMPUTE(MP_PM_CONTROL(c)), 1);
         PUSH_DATA (push, 0);
      }
   }

   /* release counters for this query */
   for (c = 0; c < 4; c++) {
      if (screen->pm.mp_counter[c] == hsq) {
         screen->pm.num_hw_sm_active--;
         screen->pm.mp_counter[c] = NULL;
      }
   }

   BCTX_REFN_bo(nv50->bufctx_cp, CP_QUERY, NOUVEAU_BO_GART | NOUVEAU_BO_WR,
                hq->bo);

   PUSH_SPACE(push, 2);
   BEGIN_NV04(push, SUBC_COMPUTE(NV50_GRAPH_SERIALIZE), 1);
   PUSH_DATA (push, 0);

   pipe->bind_compute_state(pipe, screen->pm.prog);
   input[0] = hq->bo->offset + hq->base_offset;
   input[1] = hq->sequence;

   for (i = 0; i < 3; i++) {
      info.block[i] = block[i];
      info.grid[i] = grid[i];
   }
   info.pc = 0;
   info.input = input;
   pipe->launch_grid(pipe, &info);

   nouveau_bufctx_reset(nv50->bufctx_cp, NV50_BIND_CP_QUERY);

   /* re-active other counters */
   PUSH_SPACE(push, 8);
   mask = 0;
   for (c = 0; c < 4; c++) {
      const struct nv50_hw_sm_query_cfg *cfg;
      unsigned i;

      hsq = screen->pm.mp_counter[c];
      if (!hsq)
         continue;

      cfg = nv50_hw_sm_query_get_cfg(nv50, &hsq->base);
      for (i = 0; i < cfg->num_counters; i++) {
         uint16_t func;

         if (mask & (1 << hsq->ctr[i]))
            break;

         mask |= 1 << hsq->ctr[i];
         func  = nv50_hw_sm_get_func(hsq->ctr[i]);

         BEGIN_NV04(push, NV50_COMPUTE(MP_PM_CONTROL(hsq->ctr[i])), 1);
         PUSH_DATA (push, (cfg->ctr[i].sig << 24) | (func << 8)
                    | cfg->ctr[i].unit | cfg->ctr[i].mode);
      }
   }
}
示例#15
0
static bool
nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s,
                       unsigned start, unsigned nr,
                       const struct pipe_image_view *pimages)
{
   const unsigned end = start + nr;
   unsigned mask = 0;
   unsigned i;

   assert(s < 6);

   if (pimages) {
      for (i = start; i < end; ++i) {
         struct pipe_image_view *img = &nvc0->images[s][i];
         const unsigned p = i - start;

         if (img->resource == pimages[p].resource &&
             img->format == pimages[p].format &&
             img->access == pimages[p].access) {
            if (img->resource == NULL)
               continue;
            if (img->resource->target == PIPE_BUFFER &&
                img->u.buf.offset == pimages[p].u.buf.offset &&
                img->u.buf.size == pimages[p].u.buf.size)
               continue;
            if (img->resource->target != PIPE_BUFFER &&
                img->u.tex.first_layer == pimages[p].u.tex.first_layer &&
                img->u.tex.last_layer == pimages[p].u.tex.last_layer &&
                img->u.tex.level == pimages[p].u.tex.level)
               continue;
         }

         mask |= (1 << i);
         if (pimages[p].resource)
            nvc0->images_valid[s] |= (1 << i);
         else
            nvc0->images_valid[s] &= ~(1 << i);

         img->format = pimages[p].format;
         img->access = pimages[p].access;
         if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER)
            img->u.buf = pimages[p].u.buf;
         else
            img->u.tex = pimages[p].u.tex;

         pipe_resource_reference(
               &img->resource, pimages[p].resource);

         if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) {
            if (nvc0->images_tic[s][i]) {
               struct nv50_tic_entry *old =
                  nv50_tic_entry(nvc0->images_tic[s][i]);
               nvc0_screen_tic_unlock(nvc0->screen, old);
               pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL);
            }

            nvc0->images_tic[s][i] =
               gm107_create_texture_view_from_image(&nvc0->base.pipe,
                                                    &pimages[p]);
         }
      }
      if (!mask)
         return false;
   } else {
      mask = ((1 << nr) - 1) << start;
      if (!(nvc0->images_valid[s] & mask))
         return false;
      for (i = start; i < end; ++i) {
         pipe_resource_reference(&nvc0->images[s][i].resource, NULL);
         if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) {
            struct nv50_tic_entry *old = nv50_tic_entry(nvc0->images_tic[s][i]);
            if (old) {
               nvc0_screen_tic_unlock(nvc0->screen, old);
               pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL);
            }
         }
      }
      nvc0->images_valid[s] &= ~mask;
   }
   nvc0->images_dirty[s] |= mask;

   if (s == 5)
      nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
   else
      nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF);

   return true;
}
void
nv30_vbo_validate(struct nv30_context *nv30)
{
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nv30_vertex_stateobj *vertex = nv30->vertex;
   struct pipe_vertex_element *ve;
   struct pipe_vertex_buffer *vb;
   unsigned i, redefine;

   nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
   if (!nv30->vertex || nv30->draw_flags)
      return;

   if (unlikely(vertex->need_conversion)) {
      nv30->vbo_fifo = ~0;
      nv30->vbo_user = 0;
   } else {
      nv30_prevalidate_vbufs(nv30);
   }

   if (!PUSH_SPACE(push, 128))
      return;

   redefine = MAX2(vertex->num_elements, nv30->state.num_vtxelts);
   BEGIN_NV04(push, NV30_3D(VTXFMT(0)), redefine);

   for (i = 0; i < vertex->num_elements; i++) {
      ve = &vertex->pipe[i];
      vb = &nv30->vtxbuf[ve->vertex_buffer_index];

      if (likely(vb->stride) || nv30->vbo_fifo)
         PUSH_DATA (push, (vb->stride << 8) | vertex->element[i].state);
      else
         PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
   }

   for (; i < nv30->state.num_vtxelts; i++) {
      PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
   }

   for (i = 0; i < vertex->num_elements; i++) {
      struct nv04_resource *res;
      unsigned offset;
      boolean user;

      ve = &vertex->pipe[i];
      vb = &nv30->vtxbuf[ve->vertex_buffer_index];
      user = (nv30->vbo_user & (1 << ve->vertex_buffer_index));

      res = nv04_resource(vb->buffer);

      if (nv30->vbo_fifo || unlikely(vb->stride == 0)) {
         if (!nv30->vbo_fifo)
            nv30_emit_vtxattr(nv30, vb, ve, i);
         continue;
      }

      offset = ve->src_offset + vb->buffer_offset;

      BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), user ? BUFCTX_VTXTMP : BUFCTX_VTXBUF,
                       res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
                       0, NV30_3D_VTXBUF_DMA1);
   }

   nv30->state.num_vtxelts = vertex->num_elements;
}
示例#17
0
static int
nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
                                 struct pipe_resource *res,
                                 int ref)
{
   struct nvc0_context *nvc0 = nvc0_context(&ctx->pipe);
   unsigned bind = res->bind ? res->bind : PIPE_BIND_VERTEX_BUFFER;
   unsigned s, i;

   if (bind & PIPE_BIND_RENDER_TARGET) {
      for (i = 0; i < nvc0->framebuffer.nr_cbufs; ++i) {
         if (nvc0->framebuffer.cbufs[i] &&
             nvc0->framebuffer.cbufs[i]->texture == res) {
            nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
            if (!--ref)
               return ref;
         }
      }
   }
   if (bind & PIPE_BIND_DEPTH_STENCIL) {
      if (nvc0->framebuffer.zsbuf &&
          nvc0->framebuffer.zsbuf->texture == res) {
         nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
         nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
         if (!--ref)
            return ref;
      }
   }

   if (bind & (PIPE_BIND_VERTEX_BUFFER |
               PIPE_BIND_INDEX_BUFFER |
               PIPE_BIND_CONSTANT_BUFFER |
               PIPE_BIND_STREAM_OUTPUT |
               PIPE_BIND_COMMAND_ARGS_BUFFER |
               PIPE_BIND_SAMPLER_VIEW)) {
      for (i = 0; i < nvc0->num_vtxbufs; ++i) {
         if (nvc0->vtxbuf[i].buffer == res) {
            nvc0->dirty |= NVC0_NEW_ARRAYS;
            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX);
            if (!--ref)
               return ref;
         }
      }

      if (nvc0->idxbuf.buffer == res) {
         nvc0->dirty |= NVC0_NEW_IDXBUF;
         nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_IDX);
         if (!--ref)
            return ref;
      }

      for (s = 0; s < 5; ++s) {
      for (i = 0; i < nvc0->num_textures[s]; ++i) {
         if (nvc0->textures[s][i] &&
             nvc0->textures[s][i]->texture == res) {
            nvc0->textures_dirty[s] |= 1 << i;
            nvc0->dirty |= NVC0_NEW_TEXTURES;
            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i));
            if (!--ref)
               return ref;
         }
      }
      }

      for (s = 0; s < 5; ++s) {
      for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i) {
         if (!(nvc0->constbuf_valid[s] & (1 << i)))
            continue;
         if (!nvc0->constbuf[s][i].user &&
             nvc0->constbuf[s][i].u.buf == res) {
            nvc0->dirty |= NVC0_NEW_CONSTBUF;
            nvc0->constbuf_dirty[s] |= 1 << i;
            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i));
            if (!--ref)
               return ref;
         }
      }
      }
   }

   return ref;
}
示例#18
0
static void
nvc0_m2mf_transfer_rect(struct nvc0_context *nvc0,
                        const struct nv50_m2mf_rect *dst,
                        const struct nv50_m2mf_rect *src,
                        uint32_t nblocksx, uint32_t nblocksy)
{
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nouveau_bufctx *bctx = nvc0->bufctx;
   const int cpp = dst->cpp;
   uint32_t src_ofst = src->base;
   uint32_t dst_ofst = dst->base;
   uint32_t height = nblocksy;
   uint32_t sy = src->y;
   uint32_t dy = dst->y;
   uint32_t exec = (1 << 20);

   assert(dst->cpp == src->cpp);

   nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD);
   nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR);
   nouveau_pushbuf_bufctx(push, bctx);
   nouveau_pushbuf_validate(push);

   if (nouveau_bo_memtype(src->bo)) {
      BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_IN), 5);
      PUSH_DATA (push, src->tile_mode);
      PUSH_DATA (push, src->width * cpp);
      PUSH_DATA (push, src->height);
      PUSH_DATA (push, src->depth);
      PUSH_DATA (push, src->z);
   } else {
      src_ofst += src->y * src->pitch + src->x * cpp;

      BEGIN_NVC0(push, NVC0_M2MF(PITCH_IN), 1);
      PUSH_DATA (push, src->width * cpp);

      exec |= NVC0_M2MF_EXEC_LINEAR_IN;
   }

   if (nouveau_bo_memtype(dst->bo)) {
      BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_OUT), 5);
      PUSH_DATA (push, dst->tile_mode);
      PUSH_DATA (push, dst->width * cpp);
      PUSH_DATA (push, dst->height);
      PUSH_DATA (push, dst->depth);
      PUSH_DATA (push, dst->z);
   } else {
      dst_ofst += dst->y * dst->pitch + dst->x * cpp;

      BEGIN_NVC0(push, NVC0_M2MF(PITCH_OUT), 1);
      PUSH_DATA (push, dst->width * cpp);

      exec |= NVC0_M2MF_EXEC_LINEAR_OUT;
   }

   while (height) {
      int line_count = height > 2047 ? 2047 : height;

      BEGIN_NVC0(push, NVC0_M2MF(OFFSET_IN_HIGH), 2);
      PUSH_DATAh(push, src->bo->offset + src_ofst);
      PUSH_DATA (push, src->bo->offset + src_ofst);

      BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2);
      PUSH_DATAh(push, dst->bo->offset + dst_ofst);
      PUSH_DATA (push, dst->bo->offset + dst_ofst);

      if (!(exec & NVC0_M2MF_EXEC_LINEAR_IN)) {
         BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_IN_X), 2);
         PUSH_DATA (push, src->x * cpp);
         PUSH_DATA (push, sy);
      } else {
         src_ofst += line_count * src->pitch;
      }
      if (!(exec & NVC0_M2MF_EXEC_LINEAR_OUT)) {
         BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_OUT_X), 2);
         PUSH_DATA (push, dst->x * cpp);
         PUSH_DATA (push, dy);
      } else {
         dst_ofst += line_count * dst->pitch;
      }

      BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2);
      PUSH_DATA (push, nblocksx * cpp);
      PUSH_DATA (push, line_count);
      BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1);
      PUSH_DATA (push, exec);

      height -= line_count;
      sy += line_count;
      dy += line_count;
   }

   nouveau_bufctx_reset(bctx, 0);
}
示例#19
0
static void
nve4_m2mf_transfer_rect(struct nvc0_context *nvc0,
                        const struct nv50_m2mf_rect *dst,
                        const struct nv50_m2mf_rect *src,
                        uint32_t nblocksx, uint32_t nblocksy)
{
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nouveau_bufctx *bctx = nvc0->bufctx;
   uint32_t exec;
   uint32_t src_base = src->base;
   uint32_t dst_base = dst->base;
   const int cpp = dst->cpp;

   assert(dst->cpp == src->cpp);

   nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR);
   nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD);
   nouveau_pushbuf_bufctx(push, bctx);
   nouveau_pushbuf_validate(push);

   exec = 0x200 /* 2D_ENABLE */ | 0x6 /* UNK */;

   if (!nouveau_bo_memtype(dst->bo)) {
      assert(!dst->z);
      dst_base += dst->y * dst->pitch + dst->x * cpp;
      exec |= 0x100; /* DST_MODE_2D_LINEAR */
   }
   if (!nouveau_bo_memtype(src->bo)) {
      assert(!src->z);
      src_base += src->y * src->pitch + src->x * cpp;
      exec |= 0x080; /* SRC_MODE_2D_LINEAR */
   }

   BEGIN_NVC0(push, SUBC_COPY(0x070c), 6);
   PUSH_DATA (push, 0x1000 | dst->tile_mode);
   PUSH_DATA (push, dst->pitch);
   PUSH_DATA (push, dst->height);
   PUSH_DATA (push, dst->depth);
   PUSH_DATA (push, dst->z);
   PUSH_DATA (push, (dst->y << 16) | (dst->x * cpp));

   BEGIN_NVC0(push, SUBC_COPY(0x0728), 6);
   PUSH_DATA (push, 0x1000 | src->tile_mode);
   PUSH_DATA (push, src->pitch);
   PUSH_DATA (push, src->height);
   PUSH_DATA (push, src->depth);
   PUSH_DATA (push, src->z);
   PUSH_DATA (push, (src->y << 16) | (src->x * cpp));

   BEGIN_NVC0(push, SUBC_COPY(0x0400), 8);
   PUSH_DATAh(push, src->bo->offset + src_base);
   PUSH_DATA (push, src->bo->offset + src_base);
   PUSH_DATAh(push, dst->bo->offset + dst_base);
   PUSH_DATA (push, dst->bo->offset + dst_base);
   PUSH_DATA (push, src->pitch);
   PUSH_DATA (push, dst->pitch);
   PUSH_DATA (push, nblocksx * cpp);
   PUSH_DATA (push, nblocksy);

   BEGIN_NVC0(push, SUBC_COPY(0x0300), 1);
   PUSH_DATA (push, exec);

   nouveau_bufctx_reset(bctx, 0);
}
示例#20
0
void
nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
{
   struct push_context ctx;
   unsigned i, index_size;
   unsigned inst_count = info->instance_count;
   unsigned vert_count = info->count;
   unsigned prim;

   nvc0_push_context_init(nvc0, &ctx);

   nvc0_vertex_configure_translate(nvc0, info->index_bias);

   if (unlikely(ctx.edgeflag.enabled))
      nvc0_push_map_edgeflag(&ctx, nvc0, info->index_bias);

   ctx.prim_restart = info->primitive_restart;
   ctx.restart_index = info->restart_index;

   if (info->indexed) {
      nvc0_push_map_idxbuf(&ctx, nvc0);
      index_size = nvc0->idxbuf.index_size;

      if (info->primitive_restart) {
         BEGIN_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 2);
         PUSH_DATA (ctx.push, 1);
         PUSH_DATA (ctx.push, info->restart_index);
      } else
      if (nvc0->state.prim_restart) {
         IMMED_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 0);
      }
      nvc0->state.prim_restart = info->primitive_restart;
   } else {
      if (unlikely(info->count_from_stream_output)) {
         struct pipe_context *pipe = &nvc0->base.pipe;
         struct nvc0_so_target *targ;
         targ = nvc0_so_target(info->count_from_stream_output);
         pipe->get_query_result(pipe, targ->pq, TRUE, (void *)&vert_count);
         vert_count /= targ->stride;
      }
      ctx.idxbuf = NULL; /* shut up warnings */
      index_size = 0;
   }

   ctx.instance_id = info->start_instance;

   prim = nvc0_prim_gl(info->mode);
   do {
      PUSH_SPACE(ctx.push, 9);

      ctx.dest = nvc0_push_setup_vertex_array(nvc0, vert_count);
      if (unlikely(!ctx.dest))
         break;

      if (unlikely(ctx.need_vertex_id))
         nvc0_push_upload_vertex_ids(&ctx, nvc0, info);

      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0);
      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1);
      PUSH_DATA (ctx.push, prim);
      switch (index_size) {
      case 1:
         disp_vertices_i08(&ctx, info->start, vert_count);
         break;
      case 2:
         disp_vertices_i16(&ctx, info->start, vert_count);
         break;
      case 4:
         disp_vertices_i32(&ctx, info->start, vert_count);
         break;
      default:
         assert(index_size == 0);
         disp_vertices_seq(&ctx, info->start, vert_count);
         break;
      }
      PUSH_SPACE(ctx.push, 1);
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0);

      if (--inst_count) {
         prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
         ++ctx.instance_id;
      }
      nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX_TMP);
      nouveau_scratch_done(&nvc0->base);
   } while (inst_count);


   /* reset state and unmap buffers (no-op) */

   if (unlikely(!ctx.edgeflag.value)) {
      PUSH_SPACE(ctx.push, 1);
      IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1);
   }

   if (unlikely(ctx.need_vertex_id)) {
      PUSH_SPACE(ctx.push, 4);
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0);
      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(1)), 1);
      PUSH_DATA (ctx.push,
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST |
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 0);
   }

   if (info->indexed)
      nouveau_resource_unmap(nv04_resource(nvc0->idxbuf.buffer));
   for (i = 0; i < nvc0->num_vtxbufs; ++i)
      nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer));

   NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_fallback_count, 1);
}
示例#21
0
void
nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
{
   struct nvc0_context *nvc0 = nvc0_context(pipe);
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nvc0_program *cp = nvc0->compprog;
   int ret;

   ret = !nvc0_state_validate_cp(nvc0, ~0);
   if (ret) {
      NOUVEAU_ERR("Failed to launch grid !\n");
      return;
   }

   nvc0_compute_upload_input(nvc0, info);

   BEGIN_NVC0(push, NVC0_CP(CP_START_ID), 1);
   PUSH_DATA (push, nvc0_program_symbol_offset(cp, info->pc));

   BEGIN_NVC0(push, NVC0_CP(LOCAL_POS_ALLOC), 3);
   PUSH_DATA (push, (cp->hdr[1] & 0xfffff0) + align(cp->cp.lmem_size, 0x10));
   PUSH_DATA (push, 0);
   PUSH_DATA (push, 0x800); /* WARP_CSTACK_SIZE */

   BEGIN_NVC0(push, NVC0_CP(SHARED_SIZE), 3);
   PUSH_DATA (push, align(cp->cp.smem_size, 0x100));
   PUSH_DATA (push, info->block[0] * info->block[1] * info->block[2]);
   PUSH_DATA (push, cp->num_barriers);
   BEGIN_NVC0(push, NVC0_CP(CP_GPR_ALLOC), 1);
   PUSH_DATA (push, cp->num_gprs);

   /* launch preliminary setup */
   BEGIN_NVC0(push, NVC0_CP(GRIDID), 1);
   PUSH_DATA (push, 0x1);
   BEGIN_NVC0(push, SUBC_CP(0x036c), 1);
   PUSH_DATA (push, 0);
   BEGIN_NVC0(push, NVC0_CP(FLUSH), 1);
   PUSH_DATA (push, NVC0_COMPUTE_FLUSH_GLOBAL | NVC0_COMPUTE_FLUSH_UNK8);

   /* block setup */
   BEGIN_NVC0(push, NVC0_CP(BLOCKDIM_YX), 2);
   PUSH_DATA (push, (info->block[1] << 16) | info->block[0]);
   PUSH_DATA (push, info->block[2]);

   if (unlikely(info->indirect)) {
      struct nv04_resource *res = nv04_resource(info->indirect);
      uint32_t offset = res->offset + info->indirect_offset;
      unsigned macro = NVC0_CP_MACRO_LAUNCH_GRID_INDIRECT;

      nouveau_pushbuf_space(push, 16, 0, 1);
      PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain);
      PUSH_DATA(push, NVC0_FIFO_PKHDR_1I(1, macro, 3));
      nouveau_pushbuf_data(push, res->bo, offset,
                           NVC0_IB_ENTRY_1_NO_PREFETCH | 3 * 4);
   } else {
      /* grid setup */
      BEGIN_NVC0(push, NVC0_CP(GRIDDIM_YX), 2);
      PUSH_DATA (push, (info->grid[1] << 16) | info->grid[0]);
      PUSH_DATA (push, info->grid[2]);

      /* kernel launching */
      BEGIN_NVC0(push, NVC0_CP(COMPUTE_BEGIN), 1);
      PUSH_DATA (push, 0);
      BEGIN_NVC0(push, SUBC_CP(0x0a08), 1);
      PUSH_DATA (push, 0);
      BEGIN_NVC0(push, NVC0_CP(LAUNCH), 1);
      PUSH_DATA (push, 0x1000);
      BEGIN_NVC0(push, NVC0_CP(COMPUTE_END), 1);
      PUSH_DATA (push, 0);
      BEGIN_NVC0(push, SUBC_CP(0x0360), 1);
      PUSH_DATA (push, 0x1);
   }

   /* TODO: Not sure if this is really necessary. */
   nvc0_compute_invalidate_surfaces(nvc0, 5);
   nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
   nvc0->dirty_cp |= NVC0_NEW_CP_SURFACES;
   nvc0->images_dirty[5] |= nvc0->images_valid[5];
}
示例#22
0
static int
nv50_invalidate_resource_storage(struct nouveau_context *ctx,
                                 struct pipe_resource *res,
                                 int ref)
{
   struct nv50_context *nv50 = nv50_context(&ctx->pipe);
   unsigned bind = res->bind ? res->bind : PIPE_BIND_VERTEX_BUFFER;
   unsigned s, i;

   if (bind & PIPE_BIND_RENDER_TARGET) {
      assert(nv50->framebuffer.nr_cbufs <= PIPE_MAX_COLOR_BUFS);
      for (i = 0; i < nv50->framebuffer.nr_cbufs; ++i) {
         if (nv50->framebuffer.cbufs[i] &&
             nv50->framebuffer.cbufs[i]->texture == res) {
            nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);
            if (!--ref)
               return ref;
         }
      }
   }
   if (bind & PIPE_BIND_DEPTH_STENCIL) {
      if (nv50->framebuffer.zsbuf &&
          nv50->framebuffer.zsbuf->texture == res) {
         nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER;
         nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);
         if (!--ref)
            return ref;
      }
   }

   if (bind & (PIPE_BIND_VERTEX_BUFFER |
               PIPE_BIND_INDEX_BUFFER |
               PIPE_BIND_CONSTANT_BUFFER |
               PIPE_BIND_STREAM_OUTPUT |
               PIPE_BIND_SAMPLER_VIEW)) {

      assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);
      for (i = 0; i < nv50->num_vtxbufs; ++i) {
         if (nv50->vtxbuf[i].buffer == res) {
            nv50->dirty_3d |= NV50_NEW_3D_ARRAYS;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_VERTEX);
            if (!--ref)
               return ref;
         }
      }

      if (nv50->idxbuf.buffer == res) {
         /* Just rebind to the bufctx as there is no separate dirty bit */
         nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_INDEX);
         BCTX_REFN(nv50->bufctx_3d, 3D_INDEX, nv04_resource(res), RD);
         if (!--ref)
            return ref;
      }

      for (s = 0; s < 3; ++s) {
      assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
      for (i = 0; i < nv50->num_textures[s]; ++i) {
         if (nv50->textures[s][i] &&
             nv50->textures[s][i]->texture == res) {
            nv50->dirty_3d |= NV50_NEW_3D_TEXTURES;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES);
            if (!--ref)
               return ref;
         }
      }
      }

      for (s = 0; s < 3; ++s) {
      for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i) {
         if (!(nv50->constbuf_valid[s] & (1 << i)))
            continue;
         if (!nv50->constbuf[s][i].user &&
             nv50->constbuf[s][i].u.buf == res) {
            nv50->dirty_3d |= NV50_NEW_3D_CONSTBUF;
            nv50->constbuf_dirty[s] |= 1 << i;
            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_CB(s, i));
            if (!--ref)
               return ref;
         }
      }
      }
   }

   return ref;
}
示例#23
0
static int
nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
                                 struct pipe_resource *res,
                                 int ref)
{
   struct nvc0_context *nvc0 = nvc0_context(&ctx->pipe);
   unsigned s, i;

   if (res->bind & PIPE_BIND_RENDER_TARGET) {
      for (i = 0; i < nvc0->framebuffer.nr_cbufs; ++i) {
         if (nvc0->framebuffer.cbufs[i] &&
             nvc0->framebuffer.cbufs[i]->texture == res) {
            nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER;
            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB);
            if (!--ref)
               return ref;
         }
      }
   }
   if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
      if (nvc0->framebuffer.zsbuf &&
          nvc0->framebuffer.zsbuf->texture == res) {
         nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER;
         nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB);
         if (!--ref)
            return ref;
      }
   }

   if (res->target == PIPE_BUFFER) {
      for (i = 0; i < nvc0->num_vtxbufs; ++i) {
         if (nvc0->vtxbuf[i].buffer == res) {
            nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS;
            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX);
            if (!--ref)
               return ref;
         }
      }

      if (nvc0->idxbuf.buffer == res) {
         nvc0->dirty_3d |= NVC0_NEW_3D_IDXBUF;
         nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_IDX);
         if (!--ref)
            return ref;
      }

      for (s = 0; s < 6; ++s) {
         for (i = 0; i < nvc0->num_textures[s]; ++i) {
            if (nvc0->textures[s][i] &&
                nvc0->textures[s][i]->texture == res) {
               nvc0->textures_dirty[s] |= 1 << i;
               if (unlikely(s == 5)) {
                  nvc0->dirty_cp |= NVC0_NEW_CP_TEXTURES;
                  nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i));
               } else {
                  nvc0->dirty_3d |= NVC0_NEW_3D_TEXTURES;
                  nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i));
               }
               if (!--ref)
                  return ref;
            }
         }
      }

      for (s = 0; s < 6; ++s) {
         for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i) {
            if (!(nvc0->constbuf_valid[s] & (1 << i)))
               continue;
            if (!nvc0->constbuf[s][i].user &&
                nvc0->constbuf[s][i].u.buf == res) {
               nvc0->constbuf_dirty[s] |= 1 << i;
               if (unlikely(s == 5)) {
                  nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF;
                  nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i));
               } else {
                  nvc0->dirty_3d |= NVC0_NEW_3D_CONSTBUF;
                  nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_CB(s, i));
               }
               if (!--ref)
                  return ref;
            }
         }
      }

      for (s = 0; s < 6; ++s) {
         for (i = 0; i < NVC0_MAX_BUFFERS; ++i) {
            if (nvc0->buffers[s][i].buffer == res) {
               nvc0->buffers_dirty[s] |= 1 << i;
               if (unlikely(s == 5)) {
                  nvc0->dirty_cp |= NVC0_NEW_CP_BUFFERS;
                  nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_BUF);
               } else {
                  nvc0->dirty_3d |= NVC0_NEW_3D_BUFFERS;
                  nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BUF);
               }
               if (!--ref)
                  return ref;
            }
         }
      }

      for (s = 0; s < 6; ++s) {
         for (i = 0; i < NVC0_MAX_IMAGES; ++i) {
            if (nvc0->images[s][i].resource == res) {
               nvc0->images_dirty[s] |= 1 << i;
               if (unlikely(s == 5)) {
                  nvc0->dirty_cp |= NVC0_NEW_CP_SURFACES;
                  nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
               } else {
                  nvc0->dirty_3d |= NVC0_NEW_3D_SURFACES;
                  nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF);
               }
            }
            if (!--ref)
               return ref;
         }
      }
   }

   return ref;
}
示例#24
0
static void
nve4_mp_pm_query_end(struct nvc0_context *nvc0, struct nvc0_query *q)
{
   struct nvc0_screen *screen = nvc0->screen;
   struct pipe_context *pipe = &nvc0->base.pipe;
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   uint32_t mask;
   uint32_t input[3];
   const uint block[3] = { 32, 4, 1 };
   const uint grid[3] = { screen->mp_count, 1, 1 };
   unsigned c;
   const struct nve4_mp_pm_query_cfg *cfg;

   cfg = &nve4_mp_pm_queries[q->type - PIPE_QUERY_DRIVER_SPECIFIC];

   if (unlikely(!screen->pm.prog)) {
      struct nvc0_program *prog = CALLOC_STRUCT(nvc0_program);
      prog->type = PIPE_SHADER_COMPUTE;
      prog->translated = TRUE;
      prog->num_gprs = 14;
      prog->code = (uint32_t *)nve4_read_mp_pm_counters_code;
      prog->code_size = sizeof(nve4_read_mp_pm_counters_code);
      prog->parm_size = 12;
      screen->pm.prog = prog;
   }

   /* disable all counting */
   PUSH_SPACE(push, 8);
   for (c = 0; c < 8; ++c)
      if (screen->pm.mp_counter[c])
         IMMED_NVC0(push, NVE4_COMPUTE(MP_PM_FUNC(c)), 0);
   /* release counters for this query */
   for (c = 0; c < 8; ++c) {
      if (nvc0_query(screen->pm.mp_counter[c]) == q) {
         screen->pm.num_mp_pm_active[c / 4]--;
         screen->pm.mp_counter[c] = NULL;
      }
   }

   BCTX_REFN_bo(nvc0->bufctx_cp, CP_QUERY, NOUVEAU_BO_GART | NOUVEAU_BO_WR,
                q->bo);

   PUSH_SPACE(push, 1);
   IMMED_NVC0(push, SUBC_COMPUTE(NV50_GRAPH_SERIALIZE), 0);

   pipe->bind_compute_state(pipe, screen->pm.prog);
   input[0] = (q->bo->offset + q->base);
   input[1] = (q->bo->offset + q->base) >> 32;
   input[2] = q->sequence;
   pipe->launch_grid(pipe, block, grid, 0, input);

   nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_QUERY);

   /* re-activate other counters */
   PUSH_SPACE(push, 16);
   mask = 0;
   for (c = 0; c < 8; ++c) {
      unsigned i;
      q = nvc0_query(screen->pm.mp_counter[c]);
      if (!q)
         continue;
      cfg = &nve4_mp_pm_queries[q->type - PIPE_QUERY_DRIVER_SPECIFIC];
      for (i = 0; i < cfg->num_counters; ++i) {
         if (mask & (1 << q->ctr[i]))
            break;
         mask |= 1 << q->ctr[i];
         BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_FUNC(q->ctr[i])), 1);
         PUSH_DATA (push, (cfg->ctr[i].func << 4) | cfg->ctr[i].mode);
      }
   }
}