nv50: implement instanced drawing
Too bad we don't have hw array divisors or a method for setting startInstance.
This commit is contained in:
@@ -104,7 +104,9 @@ nv50_create(struct pipe_screen *pscreen, unsigned pctx_id)
|
||||
nv50->pipe.destroy = nv50_destroy;
|
||||
|
||||
nv50->pipe.draw_arrays = nv50_draw_arrays;
|
||||
nv50->pipe.draw_arrays_instanced = nv50_draw_arrays_instanced;
|
||||
nv50->pipe.draw_elements = nv50_draw_elements;
|
||||
nv50->pipe.draw_elements_instanced = nv50_draw_elements_instanced;
|
||||
nv50->pipe.clear = nv50_clear;
|
||||
|
||||
nv50->pipe.flush = nv50_flush;
|
||||
|
||||
@@ -29,9 +29,7 @@
|
||||
#define NV50_CB_PVP 1
|
||||
#define NV50_CB_PFP 2
|
||||
#define NV50_CB_PGP 3
|
||||
#define NV50_CB_TIC 4
|
||||
#define NV50_CB_TSC 5
|
||||
#define NV50_CB_PUPLOAD 6
|
||||
#define NV50_CB_AUX 4
|
||||
|
||||
#define NV50_NEW_BLEND (1 << 0)
|
||||
#define NV50_NEW_ZSA (1 << 1)
|
||||
@@ -137,6 +135,7 @@ struct nv50_state {
|
||||
struct nouveau_stateobj *vtxfmt;
|
||||
struct nouveau_stateobj *vtxbuf;
|
||||
struct nouveau_stateobj *vtxattr;
|
||||
struct nouveau_stateobj *instbuf;
|
||||
unsigned vtxelt_nr;
|
||||
};
|
||||
|
||||
@@ -198,11 +197,22 @@ extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50);
|
||||
/* nv50_vbo.c */
|
||||
extern void nv50_draw_arrays(struct pipe_context *, unsigned mode,
|
||||
unsigned start, unsigned count);
|
||||
extern void nv50_draw_arrays_instanced(struct pipe_context *, unsigned mode,
|
||||
unsigned start, unsigned count,
|
||||
unsigned startInstance,
|
||||
unsigned instanceCount);
|
||||
extern void nv50_draw_elements(struct pipe_context *pipe,
|
||||
struct pipe_buffer *indexBuffer,
|
||||
unsigned indexSize,
|
||||
unsigned mode, unsigned start,
|
||||
unsigned count);
|
||||
extern void nv50_draw_elements_instanced(struct pipe_context *pipe,
|
||||
struct pipe_buffer *indexBuffer,
|
||||
unsigned indexSize,
|
||||
unsigned mode, unsigned start,
|
||||
unsigned count,
|
||||
unsigned startInstance,
|
||||
unsigned instanceCount);
|
||||
extern void nv50_vbo_validate(struct nv50_context *nv50);
|
||||
|
||||
/* nv50_clear.c */
|
||||
|
||||
@@ -95,6 +95,8 @@ struct nv50_reg {
|
||||
|
||||
int vtx; /* vertex index, for GP inputs (TGSI Dimension.Index) */
|
||||
int indirect[2]; /* index into pc->addr, or -1 */
|
||||
|
||||
ubyte buf_index; /* c{0 .. 15}[] or g{0 .. 15}[] */
|
||||
};
|
||||
|
||||
#define NV50_MOD_NEG 1
|
||||
@@ -188,6 +190,7 @@ ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
|
||||
reg->vtx = -1;
|
||||
reg->acc = 0;
|
||||
reg->indirect[0] = reg->indirect[1] = -1;
|
||||
reg->buf_index = (type == P_CONST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static INLINE unsigned
|
||||
@@ -631,7 +634,7 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s,
|
||||
set_addr(e, pc->addr[src->indirect[0]]);
|
||||
}
|
||||
|
||||
e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22);
|
||||
e->inst[1] |= (src->buf_index << 22);
|
||||
}
|
||||
|
||||
/* Never apply nv50_reg::mod in emit_mov, or carefully check the code !!! */
|
||||
@@ -3482,6 +3485,19 @@ load_frontfacing(struct nv50_pc *pc, struct nv50_reg *sv)
|
||||
free_temp(pc, temp);
|
||||
}
|
||||
|
||||
static void
|
||||
load_instance_id(struct nv50_pc *pc, unsigned index)
|
||||
{
|
||||
struct nv50_reg reg, mem;
|
||||
|
||||
ctor_reg(®, P_TEMP, -1, -1);
|
||||
ctor_reg(&mem, P_CONST, -1, 24); /* startInstance */
|
||||
mem.buf_index = 2;
|
||||
|
||||
emit_add_b32(pc, ®, &pc->sysval[index], &mem);
|
||||
pc->sysval[index] = reg;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_semantic_info(struct nv50_program *p)
|
||||
{
|
||||
@@ -3668,8 +3684,10 @@ nv50_program_tx_prep(struct nv50_pc *pc)
|
||||
}
|
||||
if (p->cfg.regs[0] & (1 << 0))
|
||||
pc->sysval[vertex_id].hw = rid++;
|
||||
if (p->cfg.regs[0] & (1 << 4))
|
||||
if (p->cfg.regs[0] & (1 << 4)) {
|
||||
pc->sysval[instance_id].hw = rid++;
|
||||
load_instance_id(pc, instance_id);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, rid = 0; i < pc->result_nr; ++i) {
|
||||
|
||||
@@ -329,7 +329,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
|
||||
so_ref(NULL, &so);
|
||||
|
||||
/* Static tesla init */
|
||||
so = so_new(44, 90, 22);
|
||||
so = so_new(47, 95, 24);
|
||||
|
||||
so_method(so, screen->tesla, NV50TCL_COND_MODE, 1);
|
||||
so_data (so, NV50TCL_COND_MODE_ALWAYS);
|
||||
@@ -372,7 +372,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (128 * 4) * 4,
|
||||
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4,
|
||||
&screen->constbuf_parm[i]);
|
||||
if (ret) {
|
||||
nv50_screen_destroy(pscreen);
|
||||
@@ -411,6 +411,18 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
|
||||
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
|
||||
so_data (so, 0x00000031 | (NV50_CB_PMISC << 12));
|
||||
|
||||
/* bind auxiliary constbuf to immediate data bo */
|
||||
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
|
||||
so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
|
||||
so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
|
||||
so_data (so, (NV50_CB_AUX << 16) | 0x00000200);
|
||||
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
|
||||
so_data (so, 0x00000201 | (NV50_CB_AUX << 12));
|
||||
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
|
||||
so_data (so, 0x00000221 | (NV50_CB_AUX << 12));
|
||||
|
||||
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
|
||||
so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
|
||||
|
||||
@@ -23,6 +23,8 @@ struct nv50_screen {
|
||||
struct nouveau_resource *immd_heap[1];
|
||||
struct nouveau_resource *parm_heap[PIPE_SHADER_TYPES];
|
||||
|
||||
struct pipe_buffer *strm_vbuf[16];
|
||||
|
||||
struct nouveau_bo *tic;
|
||||
struct nouveau_bo *tsc;
|
||||
|
||||
|
||||
@@ -274,6 +274,9 @@ nv50_state_flush_notify(struct nouveau_channel *chan)
|
||||
so_emit_reloc_markers(chan, nv50->state.fragprog);
|
||||
so_emit_reloc_markers(chan, nv50->state.vtxbuf);
|
||||
so_emit_reloc_markers(chan, nv50->screen->static_init);
|
||||
|
||||
if (nv50->state.instbuf)
|
||||
so_emit_reloc_markers(chan, nv50->state.instbuf);
|
||||
}
|
||||
|
||||
boolean
|
||||
|
||||
@@ -160,6 +160,188 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve)
|
||||
return (hw_type | hw_size);
|
||||
}
|
||||
|
||||
/* For instanced drawing from user buffers, hitting the FIFO repeatedly
|
||||
* with the same vertex data is probably worse than uploading all data.
|
||||
*/
|
||||
static boolean
|
||||
nv50_upload_vtxbuf(struct nv50_context *nv50, unsigned i)
|
||||
{
|
||||
struct nv50_screen *nscreen = nv50->screen;
|
||||
struct pipe_screen *pscreen = &nscreen->base.base;
|
||||
struct pipe_buffer *buf = nscreen->strm_vbuf[i];
|
||||
struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i];
|
||||
uint8_t *src;
|
||||
unsigned size = MAX2(vb->buffer->size, 4096);
|
||||
|
||||
if (buf && buf->size < size)
|
||||
pipe_buffer_reference(&nscreen->strm_vbuf[i], NULL);
|
||||
|
||||
if (!nscreen->strm_vbuf[i]) {
|
||||
nscreen->strm_vbuf[i] = pipe_buffer_create(
|
||||
pscreen, 0, PIPE_BUFFER_USAGE_VERTEX, size);
|
||||
buf = nscreen->strm_vbuf[i];
|
||||
}
|
||||
|
||||
src = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
|
||||
if (!src)
|
||||
return FALSE;
|
||||
src += vb->buffer_offset;
|
||||
|
||||
size = (vb->max_index + 1) * vb->stride + 16; /* + 16 is for stride 0 */
|
||||
if (vb->buffer_offset + size > vb->buffer->size)
|
||||
size = vb->buffer->size - vb->buffer_offset;
|
||||
|
||||
pipe_buffer_write(pscreen, buf, vb->buffer_offset, size, src);
|
||||
pipe_buffer_unmap(pscreen, vb->buffer);
|
||||
|
||||
vb->buffer = buf; /* don't pipe_reference, this is a private copy */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_upload_user_vbufs(struct nv50_context *nv50)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (nv50->vbo_fifo)
|
||||
nv50->dirty |= NV50_NEW_ARRAYS;
|
||||
if (!(nv50->dirty & NV50_NEW_ARRAYS))
|
||||
return;
|
||||
|
||||
for (i = 0; i < nv50->vtxbuf_nr; ++i) {
|
||||
if (nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX)
|
||||
continue;
|
||||
nv50_upload_vtxbuf(nv50, i);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned
|
||||
init_per_instance_arrays(struct nv50_context *nv50,
|
||||
unsigned startInstance,
|
||||
unsigned pos[16], unsigned step[16])
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_channel *chan = tesla->channel;
|
||||
struct nouveau_bo *bo;
|
||||
struct nouveau_stateobj *so;
|
||||
unsigned i, b, count = 0;
|
||||
const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
|
||||
|
||||
so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2);
|
||||
|
||||
for (i = 0; i < nv50->vtxelt_nr; ++i) {
|
||||
if (!nv50->vtxelt[i].instance_divisor)
|
||||
continue;
|
||||
++count;
|
||||
b = nv50->vtxelt[i].vertex_buffer_index;
|
||||
|
||||
pos[i] = nv50->vtxelt[i].src_offset +
|
||||
nv50->vtxbuf[b].buffer_offset +
|
||||
startInstance * nv50->vtxbuf[b].stride;
|
||||
|
||||
if (!startInstance) {
|
||||
step[i] = 0;
|
||||
continue;
|
||||
}
|
||||
step[i] = startInstance % nv50->vtxelt[i].instance_divisor;
|
||||
|
||||
bo = nouveau_bo(nv50->vtxbuf[b].buffer);
|
||||
|
||||
so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2);
|
||||
so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0);
|
||||
so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0);
|
||||
}
|
||||
|
||||
if (count) {
|
||||
so_ref (so, &nv50->state.instbuf); /* for flush notify */
|
||||
so_emit(chan, nv50->state.instbuf);
|
||||
}
|
||||
so_ref (NULL, &so);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
step_per_instance_arrays(struct nv50_context *nv50,
|
||||
unsigned pos[16], unsigned step[16])
|
||||
{
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_channel *chan = tesla->channel;
|
||||
struct nouveau_bo *bo;
|
||||
struct nouveau_stateobj *so;
|
||||
unsigned i, b;
|
||||
const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
|
||||
|
||||
so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2);
|
||||
|
||||
for (i = 0; i < nv50->vtxelt_nr; ++i) {
|
||||
if (!nv50->vtxelt[i].instance_divisor)
|
||||
continue;
|
||||
b = nv50->vtxelt[i].vertex_buffer_index;
|
||||
|
||||
if (++step[i] == nv50->vtxelt[i].instance_divisor) {
|
||||
step[i] = 0;
|
||||
pos[i] += nv50->vtxbuf[b].stride;
|
||||
}
|
||||
|
||||
bo = nouveau_bo(nv50->vtxbuf[b].buffer);
|
||||
|
||||
so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2);
|
||||
so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0);
|
||||
so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0);
|
||||
}
|
||||
|
||||
so_ref (so, &nv50->state.instbuf); /* for flush notify */
|
||||
so_ref (NULL, &so);
|
||||
|
||||
so_emit(chan, nv50->state.instbuf);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_draw_arrays_instanced(struct pipe_context *pipe,
|
||||
unsigned mode, unsigned start, unsigned count,
|
||||
unsigned startInstance, unsigned instanceCount)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_channel *chan = nv50->screen->tesla->channel;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
unsigned i, nz_divisors;
|
||||
unsigned step[16], pos[16];
|
||||
|
||||
nv50_upload_user_vbufs(nv50);
|
||||
|
||||
nv50_state_validate(nv50);
|
||||
|
||||
nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2);
|
||||
OUT_RING (chan, NV50_CB_AUX | (24 << 8));
|
||||
OUT_RING (chan, startInstance);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(mode));
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2);
|
||||
OUT_RING (chan, start);
|
||||
OUT_RING (chan, count);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
for (i = 1; i < instanceCount; i++) {
|
||||
if (nz_divisors) /* any non-zero array divisors ? */
|
||||
step_per_instance_arrays(nv50, pos, step);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(mode) | (1 << 28));
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2);
|
||||
OUT_RING (chan, start);
|
||||
OUT_RING (chan, count);
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
so_ref(NULL, &nv50->state.instbuf);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
|
||||
unsigned count)
|
||||
@@ -285,6 +467,75 @@ nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
nv50_draw_elements_inline(struct nv50_context *nv50,
|
||||
void *map, unsigned indexSize,
|
||||
unsigned start, unsigned count)
|
||||
{
|
||||
switch (indexSize) {
|
||||
case 1:
|
||||
nv50_draw_elements_inline_u08(nv50, map, start, count);
|
||||
break;
|
||||
case 2:
|
||||
nv50_draw_elements_inline_u16(nv50, map, start, count);
|
||||
break;
|
||||
case 4:
|
||||
nv50_draw_elements_inline_u32(nv50, map, start, count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv50_draw_elements_instanced(struct pipe_context *pipe,
|
||||
struct pipe_buffer *indexBuffer,
|
||||
unsigned indexSize,
|
||||
unsigned mode, unsigned start, unsigned count,
|
||||
unsigned startInstance, unsigned instanceCount)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_channel *chan = tesla->channel;
|
||||
struct pipe_screen *pscreen = pipe->screen;
|
||||
void *map;
|
||||
unsigned i, nz_divisors;
|
||||
unsigned step[16], pos[16];
|
||||
|
||||
map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ);
|
||||
|
||||
nv50_upload_user_vbufs(nv50);
|
||||
|
||||
nv50_state_validate(nv50);
|
||||
|
||||
nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2);
|
||||
OUT_RING (chan, NV50_CB_AUX | (24 << 8));
|
||||
OUT_RING (chan, startInstance);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(mode) | (1 << 28));
|
||||
|
||||
nv50_draw_elements_inline(nv50, map, indexSize, start, count);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
for (i = 1; i < instanceCount; ++i) {
|
||||
if (nz_divisors) /* any non-zero array divisors ? */
|
||||
step_per_instance_arrays(nv50, pos, step);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(mode) | (1 << 28));
|
||||
|
||||
nv50_draw_elements_inline(nv50, map, indexSize, start, count);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
so_ref(NULL, &nv50->state.instbuf);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_draw_elements(struct pipe_context *pipe,
|
||||
struct pipe_buffer *indexBuffer, unsigned indexSize,
|
||||
@@ -295,7 +546,6 @@ nv50_draw_elements(struct pipe_context *pipe,
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct pipe_screen *pscreen = pipe->screen;
|
||||
void *map;
|
||||
boolean ret;
|
||||
|
||||
map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ);
|
||||
|
||||
@@ -308,29 +558,13 @@ nv50_draw_elements(struct pipe_context *pipe,
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
|
||||
OUT_RING (chan, nv50_prim(mode));
|
||||
switch (indexSize) {
|
||||
case 1:
|
||||
ret = nv50_draw_elements_inline_u08(nv50, map, start, count);
|
||||
break;
|
||||
case 2:
|
||||
ret = nv50_draw_elements_inline_u16(nv50, map, start, count);
|
||||
break;
|
||||
case 4:
|
||||
ret = nv50_draw_elements_inline_u32(nv50, map, start, count);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
nv50_draw_elements_inline(nv50, map, indexSize, start, count);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
pipe_buffer_unmap(pscreen, indexBuffer);
|
||||
|
||||
/* XXX: what to do if ret != TRUE? Flush and retry?
|
||||
*/
|
||||
assert(ret);
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
@@ -343,23 +577,16 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib,
|
||||
struct nouveau_stateobj *so;
|
||||
struct nouveau_grobj *tesla = nv50->screen->tesla;
|
||||
struct nouveau_bo *bo = nouveau_bo(vb->buffer);
|
||||
float *v;
|
||||
float v[4];
|
||||
int ret;
|
||||
enum pipe_format pf = ve->src_format;
|
||||
const struct util_format_description *desc;
|
||||
|
||||
desc = util_format_description(pf);
|
||||
assert(desc);
|
||||
|
||||
if ((desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT) ||
|
||||
util_format_get_component_bits(pf, UTIL_FORMAT_COLORSPACE_RGB, 0) != 32)
|
||||
return FALSE;
|
||||
|
||||
ret = nouveau_bo_map(bo, NOUVEAU_BO_RD);
|
||||
if (ret)
|
||||
return FALSE;
|
||||
v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset));
|
||||
|
||||
util_format_read_4f(ve->src_format, v, 0, (uint8_t *)bo->map +
|
||||
(vb->buffer_offset + ve->src_offset), 0,
|
||||
0, 0, 1, 1);
|
||||
so = *pso;
|
||||
if (!so)
|
||||
*pso = so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 4, 0);
|
||||
@@ -455,7 +682,8 @@ nv50_vbo_validate(struct nv50_context *nv50)
|
||||
}
|
||||
|
||||
so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3);
|
||||
so_data (vtxbuf, 0x20000000 | vb->stride);
|
||||
so_data (vtxbuf, 0x20000000 |
|
||||
(ve->instance_divisor ? 0 : vb->stride));
|
||||
so_reloc (vtxbuf, bo, vb->buffer_offset +
|
||||
ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
|
||||
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
|
||||
|
||||
Reference in New Issue
Block a user