nv50: implement multiple viewports/scissors, enable ARB_viewport_array
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Reviewed-by: Christoph Bumiller <e0425955@student.tuwien.ac.at>
This commit is contained in:
parent
a7012eede8
commit
246ca4b001
|
@ -1031,6 +1031,7 @@ bool Source::scanInstruction(const struct tgsi_full_instruction *inst)
|
|||
if (info->out[dst.getIndex(0)].sn == TGSI_SEMANTIC_PSIZE ||
|
||||
info->out[dst.getIndex(0)].sn == TGSI_SEMANTIC_PRIMID ||
|
||||
info->out[dst.getIndex(0)].sn == TGSI_SEMANTIC_LAYER ||
|
||||
info->out[dst.getIndex(0)].sn == TGSI_SEMANTIC_VIEWPORT_INDEX ||
|
||||
info->out[dst.getIndex(0)].sn == TGSI_SEMANTIC_FOG)
|
||||
info->out[dst.getIndex(0)].mask &= 1;
|
||||
|
||||
|
|
|
@ -163,8 +163,10 @@ struct nv50_context {
|
|||
struct pipe_blend_color blend_colour;
|
||||
struct pipe_stencil_ref stencil_ref;
|
||||
struct pipe_poly_stipple stipple;
|
||||
struct pipe_scissor_state scissor;
|
||||
struct pipe_viewport_state viewport;
|
||||
struct pipe_scissor_state scissors[NV50_MAX_VIEWPORTS];
|
||||
unsigned scissors_dirty;
|
||||
struct pipe_viewport_state viewports[NV50_MAX_VIEWPORTS];
|
||||
unsigned viewports_dirty;
|
||||
struct pipe_clip_state clip;
|
||||
|
||||
unsigned sample_mask;
|
||||
|
|
|
@ -107,6 +107,10 @@ nv50_vertprog_assign_slots(struct nv50_ir_prog_info *info)
|
|||
prog->gp.has_layer = TRUE;
|
||||
prog->gp.layerid = n;
|
||||
break;
|
||||
case TGSI_SEMANTIC_VIEWPORT_INDEX:
|
||||
prog->gp.has_viewport = true;
|
||||
prog->gp.viewportid = n;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -344,6 +348,7 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset)
|
|||
prog->vp.clpd[1] = map_undef;
|
||||
prog->vp.psiz = map_undef;
|
||||
prog->gp.has_layer = 0;
|
||||
prog->gp.has_viewport = 0;
|
||||
|
||||
info->driverPriv = prog;
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ struct nv50_program {
|
|||
uint8_t prim_type; /* point, line strip or tri strip */
|
||||
uint8_t has_layer;
|
||||
ubyte layerid; /* hw value of layer output */
|
||||
uint8_t has_viewport;
|
||||
ubyte viewportid; /* hw value of viewport index output */
|
||||
} gp;
|
||||
|
||||
void *fixups; /* relocation records */
|
||||
|
|
|
@ -197,6 +197,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
|
|||
return PIPE_ENDIAN_LITTLE;
|
||||
case PIPE_CAP_TGSI_VS_LAYER:
|
||||
return 0;
|
||||
case PIPE_CAP_MAX_VIEWPORTS:
|
||||
return NV50_MAX_VIEWPORTS;
|
||||
default:
|
||||
NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
|
||||
return 0;
|
||||
|
@ -528,9 +530,14 @@ nv50_screen_init_hwctx(struct nv50_screen *screen)
|
|||
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1);
|
||||
PUSH_DATA (push, 1);
|
||||
BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
|
||||
PUSH_DATAf(push, 0.0f);
|
||||
PUSH_DATAf(push, 1.0f);
|
||||
for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
|
||||
BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(i)), 2);
|
||||
PUSH_DATAf(push, 0.0f);
|
||||
PUSH_DATAf(push, 1.0f);
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(i)), 2);
|
||||
PUSH_DATA (push, 8192 << 16);
|
||||
PUSH_DATA (push, 8192 << 16);
|
||||
}
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(VIEW_VOLUME_CLIP_CTRL), 1);
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
|
@ -545,10 +552,12 @@ nv50_screen_init_hwctx(struct nv50_screen *screen)
|
|||
/* We use scissors instead of exact view volume clipping,
|
||||
* so they're always enabled.
|
||||
*/
|
||||
BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 3);
|
||||
PUSH_DATA (push, 1);
|
||||
PUSH_DATA (push, 8192 << 16);
|
||||
PUSH_DATA (push, 8192 << 16);
|
||||
for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
|
||||
BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(i)), 3);
|
||||
PUSH_DATA (push, 1);
|
||||
PUSH_DATA (push, 8192 << 16);
|
||||
PUSH_DATA (push, 8192 << 16);
|
||||
}
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(RASTERIZE_ENABLE), 1);
|
||||
PUSH_DATA (push, 1);
|
||||
|
|
|
@ -21,6 +21,8 @@ struct nv50_context;
|
|||
|
||||
#define NV50_SCREEN_RESIDENT_BO_COUNT 5
|
||||
|
||||
#define NV50_MAX_VIEWPORTS 16
|
||||
|
||||
struct nv50_blitter;
|
||||
|
||||
struct nv50_screen {
|
||||
|
|
|
@ -347,6 +347,7 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
|
|||
int i, n, c, m;
|
||||
uint32_t primid = 0;
|
||||
uint32_t layerid = 0;
|
||||
uint32_t viewportid = 0;
|
||||
uint32_t psiz = 0x000;
|
||||
uint32_t interp = fp->fp.interp;
|
||||
uint32_t colors = fp->fp.colors;
|
||||
|
@ -408,6 +409,9 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
|
|||
case TGSI_SEMANTIC_LAYER:
|
||||
layerid = m;
|
||||
break;
|
||||
case TGSI_SEMANTIC_VIEWPORT_INDEX:
|
||||
viewportid = m;
|
||||
break;
|
||||
}
|
||||
m = nv50_vec4_map(map, m, lin,
|
||||
&fp->in[i], (n < vp->out_nr) ? &vp->out[n] : &dummy);
|
||||
|
@ -418,6 +422,11 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
|
|||
map[m++] = vp->gp.layerid;
|
||||
}
|
||||
|
||||
if (vp->gp.has_viewport && !viewportid) {
|
||||
viewportid = m;
|
||||
map[m++] = vp->gp.viewportid;
|
||||
}
|
||||
|
||||
if (nv50->rast->pipe.point_size_per_vertex) {
|
||||
psiz = (m << 4) | 1;
|
||||
map[m++] = vp->vp.psiz;
|
||||
|
@ -472,12 +481,16 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
|
|||
PUSH_DATAp(push, map, n);
|
||||
}
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(SEMANTIC_COLOR), 4);
|
||||
BEGIN_NV04(push, NV50_3D(GP_VIEWPORT_ID_ENABLE), 5);
|
||||
PUSH_DATA (push, vp->gp.has_viewport);
|
||||
PUSH_DATA (push, colors);
|
||||
PUSH_DATA (push, (vp->vp.clpd_nr << 8) | 4);
|
||||
PUSH_DATA (push, layerid);
|
||||
PUSH_DATA (push, psiz);
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(SEMANTIC_VIEWPORT), 1);
|
||||
PUSH_DATA (push, viewportid);
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(LAYER), 1);
|
||||
PUSH_DATA (push, vp->gp.has_layer << 16);
|
||||
|
||||
|
|
|
@ -235,8 +235,10 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
|
|||
so->pipe = *cso;
|
||||
|
||||
#ifndef NV50_SCISSORS_CLIPPING
|
||||
SB_BEGIN_3D(so, SCISSOR_ENABLE(0), 1);
|
||||
SB_DATA (so, cso->scissor);
|
||||
for (int i = 0; i < NV50_MAX_VIEWPORTS; i++) {
|
||||
SB_BEGIN_3D(so, SCISSOR_ENABLE(i), 1);
|
||||
SB_DATA (so, cso->scissor);
|
||||
}
|
||||
#endif
|
||||
|
||||
SB_BEGIN_3D(so, SHADE_MODEL, 1);
|
||||
|
@ -903,9 +905,16 @@ nv50_set_scissor_states(struct pipe_context *pipe,
|
|||
const struct pipe_scissor_state *scissor)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
int i;
|
||||
|
||||
nv50->scissor = *scissor;
|
||||
nv50->dirty |= NV50_NEW_SCISSOR;
|
||||
assert(start_slot + num_scissors <= NV50_MAX_VIEWPORTS);
|
||||
for (i = 0; i < num_scissors; i++) {
|
||||
if (!memcmp(&nv50->scissors[start_slot + i], &scissor[i], sizeof(*scissor)))
|
||||
continue;
|
||||
nv50->scissors[start_slot + i] = scissor[i];
|
||||
nv50->scissors_dirty |= 1 << (start_slot + i);
|
||||
nv50->dirty |= NV50_NEW_SCISSOR;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -915,9 +924,16 @@ nv50_set_viewport_states(struct pipe_context *pipe,
|
|||
const struct pipe_viewport_state *vpt)
|
||||
{
|
||||
struct nv50_context *nv50 = nv50_context(pipe);
|
||||
int i;
|
||||
|
||||
nv50->viewport = *vpt;
|
||||
nv50->dirty |= NV50_NEW_VIEWPORT;
|
||||
assert(start_slot + num_viewports <= NV50_MAX_VIEWPORTS);
|
||||
for (i = 0; i < num_viewports; i++) {
|
||||
if (!memcmp(&nv50->viewports[start_slot + i], &vpt[i], sizeof(*vpt)))
|
||||
continue;
|
||||
nv50->viewports[start_slot + i] = vpt[i];
|
||||
nv50->viewports_dirty |= 1 << (start_slot + i);
|
||||
nv50->dirty |= NV50_NEW_VIEWPORT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -124,6 +124,7 @@ nv50_validate_fb(struct nv50_context *nv50)
|
|||
BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
|
||||
PUSH_DATA (push, ms_mode);
|
||||
|
||||
/* Only need to initialize the first viewport, which is used for clears */
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
|
||||
PUSH_DATA (push, fb->width << 16);
|
||||
PUSH_DATA (push, fb->height << 16);
|
||||
|
@ -167,42 +168,63 @@ static void
|
|||
nv50_validate_scissor(struct nv50_context *nv50)
|
||||
{
|
||||
struct nouveau_pushbuf *push = nv50->base.pushbuf;
|
||||
struct pipe_scissor_state *s = &nv50->scissor;
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
struct pipe_viewport_state *vp = &nv50->viewport;
|
||||
int minx, maxx, miny, maxy;
|
||||
int minx, maxx, miny, maxy, i;
|
||||
|
||||
if (!(nv50->dirty &
|
||||
(NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
|
||||
nv50->state.scissor == nv50->rast->pipe.scissor)
|
||||
return;
|
||||
|
||||
if (nv50->state.scissor != nv50->rast->pipe.scissor)
|
||||
nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
|
||||
|
||||
nv50->state.scissor = nv50->rast->pipe.scissor;
|
||||
|
||||
if (nv50->state.scissor) {
|
||||
minx = s->minx;
|
||||
maxx = s->maxx;
|
||||
miny = s->miny;
|
||||
maxy = s->maxy;
|
||||
} else {
|
||||
minx = 0;
|
||||
maxx = nv50->framebuffer.width;
|
||||
miny = 0;
|
||||
maxy = nv50->framebuffer.height;
|
||||
if ((nv50->dirty & NV50_NEW_FRAMEBUFFER) && !nv50->state.scissor)
|
||||
nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
|
||||
|
||||
for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
|
||||
struct pipe_scissor_state *s = &nv50->scissors[i];
|
||||
struct pipe_viewport_state *vp = &nv50->viewports[i];
|
||||
|
||||
if (!(nv50->scissors_dirty & (1 << i)) &&
|
||||
!(nv50->viewports_dirty & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (nv50->state.scissor) {
|
||||
minx = s->minx;
|
||||
maxx = s->maxx;
|
||||
miny = s->miny;
|
||||
maxy = s->maxy;
|
||||
} else {
|
||||
minx = 0;
|
||||
maxx = nv50->framebuffer.width;
|
||||
miny = 0;
|
||||
maxy = nv50->framebuffer.height;
|
||||
}
|
||||
|
||||
minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
|
||||
maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
|
||||
miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
|
||||
maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
|
||||
|
||||
minx = MIN2(minx, 8192);
|
||||
maxx = MAX2(maxx, 0);
|
||||
miny = MIN2(miny, 8192);
|
||||
maxy = MAX2(maxy, 0);
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
|
||||
PUSH_DATA (push, (maxx << 16) | minx);
|
||||
PUSH_DATA (push, (maxy << 16) | miny);
|
||||
#else
|
||||
BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
|
||||
PUSH_DATA (push, (s->maxx << 16) | s->minx);
|
||||
PUSH_DATA (push, (s->maxy << 16) | s->miny);
|
||||
#endif
|
||||
}
|
||||
|
||||
minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
|
||||
maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
|
||||
miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
|
||||
maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
|
||||
PUSH_DATA (push, (maxx << 16) | minx);
|
||||
PUSH_DATA (push, (maxy << 16) | miny);
|
||||
#else
|
||||
BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
|
||||
PUSH_DATA (push, (s->maxx << 16) | s->minx);
|
||||
PUSH_DATA (push, (s->maxy << 16) | s->miny);
|
||||
#endif
|
||||
nv50->scissors_dirty = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -210,24 +232,34 @@ nv50_validate_viewport(struct nv50_context *nv50)
|
|||
{
|
||||
struct nouveau_pushbuf *push = nv50->base.pushbuf;
|
||||
float zmin, zmax;
|
||||
int i;
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(0)), 3);
|
||||
PUSH_DATAf(push, nv50->viewport.translate[0]);
|
||||
PUSH_DATAf(push, nv50->viewport.translate[1]);
|
||||
PUSH_DATAf(push, nv50->viewport.translate[2]);
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(0)), 3);
|
||||
PUSH_DATAf(push, nv50->viewport.scale[0]);
|
||||
PUSH_DATAf(push, nv50->viewport.scale[1]);
|
||||
PUSH_DATAf(push, nv50->viewport.scale[2]);
|
||||
for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
|
||||
struct pipe_viewport_state *vpt = &nv50->viewports[i];
|
||||
|
||||
zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]);
|
||||
zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]);
|
||||
if (!(nv50->viewports_dirty & (1 << i)))
|
||||
continue;
|
||||
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(i)), 3);
|
||||
PUSH_DATAf(push, vpt->translate[0]);
|
||||
PUSH_DATAf(push, vpt->translate[1]);
|
||||
PUSH_DATAf(push, vpt->translate[2]);
|
||||
BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(i)), 3);
|
||||
PUSH_DATAf(push, vpt->scale[0]);
|
||||
PUSH_DATAf(push, vpt->scale[1]);
|
||||
PUSH_DATAf(push, vpt->scale[2]);
|
||||
|
||||
zmin = vpt->translate[2] - fabsf(vpt->scale[2]);
|
||||
zmax = vpt->translate[2] + fabsf(vpt->scale[2]);
|
||||
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
|
||||
PUSH_DATAf(push, zmin);
|
||||
PUSH_DATAf(push, zmax);
|
||||
BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(i)), 2);
|
||||
PUSH_DATAf(push, zmin);
|
||||
PUSH_DATAf(push, zmax);
|
||||
#endif
|
||||
}
|
||||
|
||||
nv50->viewports_dirty = 0;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
|
|
Loading…
Reference in New Issue