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; } } } }
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; }
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); }
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; } } } }