static void
nv30_prevalidate_vbufs(struct nv30_context *nv30)
{
   struct pipe_vertex_buffer *vb;
   struct nv04_resource *buf;
   int i;
   uint32_t base, size;

   nv30->vbo_fifo = nv30->vbo_user = 0;

   for (i = 0; i < nv30->num_vtxbufs; i++) {
      vb = &nv30->vtxbuf[i];
      if (!vb->stride || !vb->buffer) /* NOTE: user_buffer not implemented */
         continue;
      buf = nv04_resource(vb->buffer);

      /* NOTE: user buffers with temporary storage count as mapped by GPU */
      if (!nouveau_resource_mapped_by_gpu(vb->buffer)) {
         if (nv30->vbo_push_hint) {
            nv30->vbo_fifo = ~0;
            continue;
         } else {
            if (buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY) {
               nv30->vbo_user |= 1 << i;
               assert(vb->stride > vb->buffer_offset);
               nv30_vbuf_range(nv30, i, &base, &size);
               nouveau_user_buffer_upload(&nv30->base, buf, base, size);
            } else {
               nouveau_buffer_migrate(&nv30->base, buf, NOUVEAU_BO_GART);
            }
            nv30->base.vbo_dirty = TRUE;
         }
      }
   }
}
예제 #2
0
static inline struct nv04_resource *
nv30_transfer_rect_fragprog(struct nv30_context *nv30)
{
   struct nv04_resource *fp = nv04_resource(nv30->blit_fp);
   struct pipe_context *pipe = &nv30->base.pipe;

   if (!fp) {
      nv30->blit_fp = pipe_buffer_create(pipe->screen, 0, 0, 12 * 4);
      if (nv30->blit_fp) {
         struct pipe_transfer *transfer;
         u32 *map = pipe_buffer_map(pipe, nv30->blit_fp,
                                    PIPE_TRANSFER_WRITE, &transfer);
         if (map) {
            map[0] = 0x17009e00; /* texr r0, i[tex0], texture[0]; end; */
            map[1] = 0x1c9dc801;
            map[2] = 0x0001c800;
            map[3] = 0x3fe1c800;
            map[4] = 0x01401e81; /* end; */
            map[5] = 0x1c9dc800;
            map[6] = 0x0001c800;
            map[7] = 0x0001c800;
            pipe_buffer_unmap(pipe, transfer);
         }

         fp = nv04_resource(nv30->blit_fp);
         nouveau_buffer_migrate(&nv30->base, fp, NOUVEAU_BO_VRAM);
      }
   }

   return fp;
}
예제 #3
0
static void
nv30_fragprog_upload(struct nv30_context *nv30)
{
   struct nouveau_context *nv = &nv30->base;
   struct nv30_fragprog *fp = nv30->fragprog.program;
   struct pipe_context *pipe = &nv30->base.pipe;

   if (unlikely(!fp->buffer))
      fp->buffer = pipe_buffer_create(pipe->screen, 0, 0, fp->insn_len * 4);

#ifndef PIPE_ARCH_BIG_ENDIAN
   pipe_buffer_write(pipe, fp->buffer, 0, fp->insn_len * 4, fp->insn);
#else
   {
      struct pipe_transfer *transfer;
      uint32_t *map;
      int i;

      map = pipe_buffer_map(pipe, fp->buffer,
                            PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
                            &transfer);
      for (i = 0; i < fp->insn_len; i++)
         *map++ = (fp->insn[i] >> 16) | (fp->insn[i] << 16);
      pipe_buffer_unmap(pipe, transfer);
   }
#endif

   if (nv04_resource(fp->buffer)->domain != NOUVEAU_BO_VRAM)
      nouveau_buffer_migrate(nv, nv04_resource(fp->buffer), NOUVEAU_BO_VRAM);
}
예제 #4
0
void
nv50_constbufs_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   unsigned s;

   for (s = 0; s < 3; ++s) {
      struct nv04_resource *res;
      int i;
      unsigned p, b;

      if (s == PIPE_SHADER_FRAGMENT)
         p = NV50_3D_SET_PROGRAM_CB_PROGRAM_FRAGMENT;
      else
      if (s == PIPE_SHADER_GEOMETRY)
         p = NV50_3D_SET_PROGRAM_CB_PROGRAM_GEOMETRY;
      else
         p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX;

      while (nv50->constbuf_dirty[s]) {
         struct nouveau_bo *bo;
         unsigned start = 0;
         unsigned words = 0;

         i = ffs(nv50->constbuf_dirty[s]) - 1;
         nv50->constbuf_dirty[s] &= ~(1 << i);

         res = nv04_resource(nv50->constbuf[s][i]);
         if (!res) {
            if (i != 0) {
               BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1);
               OUT_RING  (chan, (i << 8) | p | 0);
            }
            continue;
         }

         if (i == 0) {
            b = NV50_CB_PVP + s;

            /* always upload GL uniforms through CB DATA */
            bo = nv50->screen->uniforms;
            words = res->base.width0 / 4;
         } else {
            b = s * 16 + i;

            assert(0);

            if (!nouveau_resource_mapped_by_gpu(&res->base)) {
               nouveau_buffer_migrate(&nv50->base, res, NOUVEAU_BO_VRAM);

               BEGIN_RING(chan, RING_3D(CODE_CB_FLUSH), 1);
               OUT_RING  (chan, 0);
            }
            MARK_RING (chan, 6, 2);
            BEGIN_RING(chan, RING_3D(CB_DEF_ADDRESS_HIGH), 3);
            OUT_RESRCh(chan, res, 0, NOUVEAU_BO_RD);
            OUT_RESRCl(chan, res, 0, NOUVEAU_BO_RD);
            OUT_RING  (chan, (b << 16) | (res->base.width0 & 0xffff));
            BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1);
            OUT_RING  (chan, (b << 12) | (i << 8) | p | 1);

            bo = res->bo;

            nv50_bufctx_add_resident(nv50, NV50_BUFCTX_CONSTANT, res,
                                     res->domain | NOUVEAU_BO_RD);
         }

         if (words) {
            MARK_RING(chan, 8, 1);

            nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR);
         }

         while (words) {
            unsigned nr = AVAIL_RING(chan);

            if (nr < 16) {
               FIRE_RING(chan);
               nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR);
               continue;
            }
            nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);

            BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
            OUT_RING  (chan, (start << 8) | b);
            BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nr);
            OUT_RINGp (chan, &res->data[start * 4], nr);

            start += nr;
            words -= nr;
         }
      }
   }
}