mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-23 09:40:29 +01:00
nv50: make edgeflags work
It doesn't seem to be possible to set the egdeflag in the vertex shader, so we need to fallback to pushing vertices through the FIFO and use method 0x15e4 if they are used. This only works if VP does MOV OUT[X] IN[Y] where X is the edgeflag output, and Y is saved so we can tell the correct input later. The VP still writes the useless values to wasted outputs as punishment.
This commit is contained in:
parent
b5a408bae5
commit
d29f55546d
4 changed files with 64 additions and 4 deletions
|
|
@ -159,6 +159,8 @@ struct nv50_pc {
|
|||
unsigned insn_nr;
|
||||
|
||||
boolean allow32;
|
||||
|
||||
uint8_t edgeflag_out;
|
||||
};
|
||||
|
||||
static INLINE struct nv50_reg *
|
||||
|
|
@ -2554,10 +2556,16 @@ prep_inspect_insn(struct nv50_pc *pc, const struct tgsi_full_instruction *insn)
|
|||
mask = dst->WriteMask;
|
||||
|
||||
if (dst->File == TGSI_FILE_TEMPORARY)
|
||||
reg = pc->temp;
|
||||
reg = pc->temp;
|
||||
else
|
||||
if (dst->File == TGSI_FILE_OUTPUT)
|
||||
reg = pc->result;
|
||||
if (dst->File == TGSI_FILE_OUTPUT) {
|
||||
reg = pc->result;
|
||||
|
||||
if (insn->Instruction.Opcode == TGSI_OPCODE_MOV &&
|
||||
dst->Index == pc->edgeflag_out &&
|
||||
insn->Src[0].Register.File == TGSI_FILE_INPUT)
|
||||
pc->p->cfg.edgeflag_in = insn->Src[0].Register.Index;
|
||||
}
|
||||
|
||||
if (reg) {
|
||||
for (c = 0; c < 4; c++) {
|
||||
|
|
@ -2856,6 +2864,9 @@ nv50_program_tx_prep(struct nv50_pc *pc)
|
|||
if (p->cfg.io_nr > first)
|
||||
p->cfg.io_nr = first;
|
||||
break;
|
||||
case TGSI_SEMANTIC_EDGEFLAG:
|
||||
pc->edgeflag_out = first;
|
||||
break;
|
||||
/*
|
||||
case TGSI_SEMANTIC_CLIP_DISTANCE:
|
||||
p->cfg.clpd = MIN2(p->cfg.clpd, first);
|
||||
|
|
@ -3104,6 +3115,8 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
|
|||
p->cfg.two_side[0].hw = 0x40;
|
||||
p->cfg.two_side[1].hw = 0x40;
|
||||
|
||||
p->cfg.edgeflag_in = pc->edgeflag_out = 0xff;
|
||||
|
||||
switch (p->type) {
|
||||
case PIPE_SHADER_VERTEX:
|
||||
p->cfg.psiz = 0x40;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ struct nv50_program {
|
|||
/* VP only */
|
||||
uint8_t clpd, clpd_nr;
|
||||
uint8_t psiz;
|
||||
uint8_t edgeflag_in;
|
||||
} cfg;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -441,6 +441,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
|
|||
so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE, 1);
|
||||
so_data (so, 1);
|
||||
|
||||
so_method(so, screen->tesla, 0x15e4, 1);
|
||||
so_data (so, 1); /* default edgeflag to TRUE */
|
||||
|
||||
so_emit(chan, so);
|
||||
so_ref (so, &screen->static_init);
|
||||
so_ref (NULL, &so);
|
||||
|
|
|
|||
|
|
@ -372,6 +372,10 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib,
|
|||
so_data (so, fui(v[1]));
|
||||
break;
|
||||
case 1:
|
||||
if (attrib == nv50->vertprog->cfg.edgeflag_in) {
|
||||
so_method(so, tesla, 0x15e4, 1);
|
||||
so_data (so, v[0] ? 1 : 0);
|
||||
}
|
||||
so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 1);
|
||||
so_data (so, fui(v[0]));
|
||||
break;
|
||||
|
|
@ -401,6 +405,9 @@ nv50_vbo_validate(struct nv50_context *nv50)
|
|||
!(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX))
|
||||
nv50->vbo_fifo = 0xffff;
|
||||
|
||||
if (nv50->vertprog->cfg.edgeflag_in < 16)
|
||||
nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */
|
||||
|
||||
n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr);
|
||||
|
||||
vtxattr = NULL;
|
||||
|
|
@ -479,6 +486,9 @@ struct nv50_vbo_emitctx
|
|||
unsigned nr_ve;
|
||||
unsigned vtx_dwords;
|
||||
unsigned vtx_max;
|
||||
|
||||
float edgeflag;
|
||||
unsigned ve_edgeflag;
|
||||
};
|
||||
|
||||
static INLINE void
|
||||
|
|
@ -622,6 +632,9 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit,
|
|||
if (nv50_map_vbufs(nv50) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
emit->ve_edgeflag = nv50->vertprog->cfg.edgeflag_in;
|
||||
|
||||
emit->edgeflag = 0.5f;
|
||||
emit->nr_ve = 0;
|
||||
emit->vtx_dwords = 0;
|
||||
|
||||
|
|
@ -644,7 +657,8 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit,
|
|||
desc = util_format_description(ve->src_format);
|
||||
assert(desc);
|
||||
|
||||
size = util_format_get_component_bits(ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||
size = util_format_get_component_bits(
|
||||
ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
|
||||
|
||||
assert(ve->nr_components > 0 && ve->nr_components <= 4);
|
||||
|
||||
|
|
@ -686,10 +700,31 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit,
|
|||
}
|
||||
|
||||
emit->vtx_max = 512 / emit->vtx_dwords;
|
||||
if (emit->ve_edgeflag < 16)
|
||||
emit->vtx_max = 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
set_edgeflag(struct nouveau_channel *chan,
|
||||
struct nouveau_grobj *tesla,
|
||||
struct nv50_vbo_emitctx *emit, uint32_t index)
|
||||
{
|
||||
unsigned i = emit->ve_edgeflag;
|
||||
|
||||
if (i < 16) {
|
||||
float f = *((float *)(emit->map[i] + index * emit->stride[i]));
|
||||
|
||||
if (emit->edgeflag != f) {
|
||||
emit->edgeflag = f;
|
||||
|
||||
BEGIN_RING(chan, tesla, 0x15e4, 1);
|
||||
OUT_RING (chan, f ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count)
|
||||
{
|
||||
|
|
@ -704,6 +739,8 @@ nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count)
|
|||
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
|
||||
dw = nr * emit.vtx_dwords;
|
||||
|
||||
set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
|
||||
for (i = 0; i < nr; ++i)
|
||||
emit_vtx_next(chan, &emit);
|
||||
|
|
@ -729,6 +766,8 @@ nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count)
|
|||
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
|
||||
dw = nr * emit.vtx_dwords;
|
||||
|
||||
set_edgeflag(chan, tesla, &emit, *map);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
|
||||
for (i = 0; i < nr; ++i)
|
||||
emit_vtx(chan, &emit, *map++);
|
||||
|
|
@ -754,6 +793,8 @@ nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count)
|
|||
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
|
||||
dw = nr * emit.vtx_dwords;
|
||||
|
||||
set_edgeflag(chan, tesla, &emit, *map);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
|
||||
for (i = 0; i < nr; ++i)
|
||||
emit_vtx(chan, &emit, *map++);
|
||||
|
|
@ -779,6 +820,8 @@ nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count)
|
|||
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
|
||||
dw = nr * emit.vtx_dwords;
|
||||
|
||||
set_edgeflag(chan, tesla, &emit, *map);
|
||||
|
||||
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
|
||||
for (i = 0; i < nr; ++i)
|
||||
emit_vtx(chan, &emit, *map++);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue