freedreno: support multiple viewports

Core plumbing to have multiple viewport support.  Each viewport has it's
own scissor state.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19236>
This commit is contained in:
Rob Clark 2022-10-16 12:20:01 -07:00 committed by Marge Bot
parent 138b513fb7
commit e752a26ca4
9 changed files with 114 additions and 89 deletions

View file

@ -203,15 +203,17 @@ fd2_emit_state_binning(struct fd_context *ctx,
}
if (dirty & FD_DIRTY_VIEWPORT) {
struct pipe_viewport_state *vp = & ctx->viewport[0];
OUT_PKT3(ring, CP_SET_CONSTANT, 9);
OUT_RING(ring, 0x00000184);
OUT_RING(ring, fui(ctx->viewport.translate[0]));
OUT_RING(ring, fui(ctx->viewport.translate[1]));
OUT_RING(ring, fui(ctx->viewport.translate[2]));
OUT_RING(ring, fui(vp->translate[0]));
OUT_RING(ring, fui(vp->translate[1]));
OUT_RING(ring, fui(vp->translate[2]));
OUT_RING(ring, fui(0.0f));
OUT_RING(ring, fui(ctx->viewport.scale[0]));
OUT_RING(ring, fui(ctx->viewport.scale[1]));
OUT_RING(ring, fui(ctx->viewport.scale[2]));
OUT_RING(ring, fui(vp->scale[0]));
OUT_RING(ring, fui(vp->scale[1]));
OUT_RING(ring, fui(vp->scale[2]));
OUT_RING(ring, fui(0.0f));
}
@ -333,27 +335,29 @@ fd2_emit_state(struct fd_context *ctx, const enum fd_dirty_3d_state dirty)
}
if (dirty & FD_DIRTY_VIEWPORT) {
struct pipe_viewport_state *vp = & ctx->viewport[0];
OUT_PKT3(ring, CP_SET_CONSTANT, 7);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
OUT_RING(ring, fui(ctx->viewport.scale[0])); /* PA_CL_VPORT_XSCALE */
OUT_RING(ring, fui(ctx->viewport.translate[0])); /* PA_CL_VPORT_XOFFSET */
OUT_RING(ring, fui(ctx->viewport.scale[1])); /* PA_CL_VPORT_YSCALE */
OUT_RING(ring, fui(ctx->viewport.translate[1])); /* PA_CL_VPORT_YOFFSET */
OUT_RING(ring, fui(ctx->viewport.scale[2])); /* PA_CL_VPORT_ZSCALE */
OUT_RING(ring, fui(ctx->viewport.translate[2])); /* PA_CL_VPORT_ZOFFSET */
OUT_RING(ring, fui(vp->scale[0])); /* PA_CL_VPORT_XSCALE */
OUT_RING(ring, fui(vp->translate[0])); /* PA_CL_VPORT_XOFFSET */
OUT_RING(ring, fui(vp->scale[1])); /* PA_CL_VPORT_YSCALE */
OUT_RING(ring, fui(vp->translate[1])); /* PA_CL_VPORT_YOFFSET */
OUT_RING(ring, fui(vp->scale[2])); /* PA_CL_VPORT_ZSCALE */
OUT_RING(ring, fui(vp->translate[2])); /* PA_CL_VPORT_ZOFFSET */
/* set viewport in C65/C66, for a20x hw binning and fragcoord.z */
OUT_PKT3(ring, CP_SET_CONSTANT, 9);
OUT_RING(ring, 0x00000184);
OUT_RING(ring, fui(ctx->viewport.translate[0]));
OUT_RING(ring, fui(ctx->viewport.translate[1]));
OUT_RING(ring, fui(ctx->viewport.translate[2]));
OUT_RING(ring, fui(vp->translate[0]));
OUT_RING(ring, fui(vp->translate[1]));
OUT_RING(ring, fui(vp->translate[2]));
OUT_RING(ring, fui(0.0f));
OUT_RING(ring, fui(ctx->viewport.scale[0]));
OUT_RING(ring, fui(ctx->viewport.scale[1]));
OUT_RING(ring, fui(ctx->viewport.scale[2]));
OUT_RING(ring, fui(vp->scale[0]));
OUT_RING(ring, fui(vp->scale[1]));
OUT_RING(ring, fui(vp->scale[2]));
OUT_RING(ring, fui(0.0f));
}

View file

@ -678,7 +678,8 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
* viewport clip via scissors.
*/
if (!ctx->rasterizer->depth_clip_near) {
struct pipe_viewport_state *vp = &ctx->viewport;
struct pipe_viewport_state *vp = &ctx->viewport[0];
minx = MAX2(minx, (int)floorf(vp->translate[0] - fabsf(vp->scale[0])));
miny = MAX2(miny, (int)floorf(vp->translate[1] - fabsf(vp->scale[1])));
maxx = MIN2(maxx, (int)ceilf(vp->translate[0] + fabsf(vp->scale[0])));
@ -698,16 +699,19 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
}
if (dirty & FD_DIRTY_VIEWPORT) {
struct pipe_viewport_state *vp = &ctx->viewport[0];
fd_wfi(ctx->batch, ring);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 6);
OUT_RING(ring,
A3XX_GRAS_CL_VPORT_XOFFSET(ctx->viewport.translate[0] - 0.5f));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE(ctx->viewport.scale[0]));
A3XX_GRAS_CL_VPORT_XOFFSET(vp->translate[0] - 0.5f));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE(vp->scale[0]));
OUT_RING(ring,
A3XX_GRAS_CL_VPORT_YOFFSET(ctx->viewport.translate[1] - 0.5f));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(ctx->viewport.scale[1]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(ctx->viewport.translate[2]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(ctx->viewport.scale[2]));
A3XX_GRAS_CL_VPORT_YOFFSET(vp->translate[1] - 0.5f));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(vp->scale[1]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(vp->translate[2]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(vp->scale[2]));
}
if (dirty &
@ -719,7 +723,7 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
pipe_surface_format(ctx->batch->framebuffer.zsbuf),
UTIL_FORMAT_COLORSPACE_ZS, 0);
}
util_viewport_zmin_zmax(&ctx->viewport, ctx->rasterizer->clip_halfz,
util_viewport_zmin_zmax(&ctx->viewport[0], ctx->rasterizer->clip_halfz,
&zmin, &zmax);
OUT_PKT0(ring, REG_A3XX_RB_Z_CLAMP_MIN, 2);

View file

@ -800,14 +800,17 @@ fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
}
if (dirty & FD_DIRTY_VIEWPORT) {
struct pipe_viewport_state *vp = & ctx->viewport[0];
fd_wfi(ctx->batch, ring);
OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 6);
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0(ctx->viewport.translate[0]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0(ctx->viewport.scale[0]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0(ctx->viewport.translate[1]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(ctx->viewport.scale[1]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(ctx->viewport.translate[2]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(ctx->viewport.scale[2]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0(vp->translate[0]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0(vp->scale[0]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0(vp->translate[1]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(vp->scale[1]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(vp->translate[2]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(vp->scale[2]));
}
if (dirty &
@ -819,7 +822,7 @@ fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
pipe_surface_format(ctx->batch->framebuffer.zsbuf),
UTIL_FORMAT_COLORSPACE_ZS, 0);
}
util_viewport_zmin_zmax(&ctx->viewport, ctx->rasterizer->clip_halfz,
util_viewport_zmin_zmax(&ctx->viewport[0], ctx->rasterizer->clip_halfz,
&zmin, &zmax);
OUT_PKT0(ring, REG_A4XX_RB_VPORT_Z_CLAMP(0), 2);

View file

@ -640,14 +640,17 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
}
if (dirty & FD_DIRTY_VIEWPORT) {
struct pipe_viewport_state *vp = & ctx->viewport[0];
fd_wfi(ctx->batch, ring);
OUT_PKT4(ring, REG_A5XX_GRAS_CL_VPORT_XOFFSET_0, 6);
OUT_RING(ring, A5XX_GRAS_CL_VPORT_XOFFSET_0(ctx->viewport.translate[0]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_XSCALE_0(ctx->viewport.scale[0]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_YOFFSET_0(ctx->viewport.translate[1]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_YSCALE_0(ctx->viewport.scale[1]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_ZOFFSET_0(ctx->viewport.translate[2]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_ZSCALE_0(ctx->viewport.scale[2]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_XOFFSET_0(vp->translate[0]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_XSCALE_0(vp->scale[0]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_YOFFSET_0(vp->translate[1]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_YSCALE_0(vp->scale[1]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_ZOFFSET_0(vp->translate[2]));
OUT_RING(ring, A5XX_GRAS_CL_VPORT_ZSCALE_0(vp->scale[2]));
}
if (dirty & (FD_DIRTY_PROG | FD_DIRTY_RASTERIZER_CLIP_PLANE_ENABLE))

View file

@ -966,14 +966,15 @@ fd6_emit_non_ring(struct fd_ringbuffer *ring, struct fd6_emit *emit) assert_dt
}
if (dirty & FD_DIRTY_VIEWPORT) {
struct pipe_scissor_state *scissor = &ctx->viewport_scissor;
struct pipe_scissor_state *scissor = &ctx->viewport_scissor[0];
struct pipe_viewport_state *vp = & ctx->viewport[0];
OUT_REG(ring, A6XX_GRAS_CL_VPORT_XOFFSET(0, ctx->viewport.translate[0]),
A6XX_GRAS_CL_VPORT_XSCALE(0, ctx->viewport.scale[0]),
A6XX_GRAS_CL_VPORT_YOFFSET(0, ctx->viewport.translate[1]),
A6XX_GRAS_CL_VPORT_YSCALE(0, ctx->viewport.scale[1]),
A6XX_GRAS_CL_VPORT_ZOFFSET(0, ctx->viewport.translate[2]),
A6XX_GRAS_CL_VPORT_ZSCALE(0, ctx->viewport.scale[2]));
OUT_REG(ring, A6XX_GRAS_CL_VPORT_XOFFSET(0, vp->translate[0]),
A6XX_GRAS_CL_VPORT_XSCALE(0, vp->scale[0]),
A6XX_GRAS_CL_VPORT_YOFFSET(0, vp->translate[1]),
A6XX_GRAS_CL_VPORT_YSCALE(0, vp->scale[1]),
A6XX_GRAS_CL_VPORT_ZOFFSET(0, vp->translate[2]),
A6XX_GRAS_CL_VPORT_ZSCALE(0, vp->scale[2]));
OUT_REG(
ring,
@ -982,10 +983,10 @@ fd6_emit_non_ring(struct fd_ringbuffer *ring, struct fd6_emit *emit) assert_dt
A6XX_GRAS_SC_VIEWPORT_SCISSOR_BR(0, .x = MAX2(scissor->maxx, 1) - 1,
.y = MAX2(scissor->maxy, 1) - 1));
unsigned guardband_x = fd_calc_guardband(ctx->viewport.translate[0],
ctx->viewport.scale[0], false);
unsigned guardband_y = fd_calc_guardband(ctx->viewport.translate[1],
ctx->viewport.scale[1], false);
unsigned guardband_x = fd_calc_guardband(vp->translate[0],
vp->scale[0], false);
unsigned guardband_y = fd_calc_guardband(vp->translate[1],
vp->scale[1], false);
OUT_REG(ring, A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ(.horz = guardband_x,
.vert = guardband_y));
@ -996,8 +997,10 @@ fd6_emit_non_ring(struct fd_ringbuffer *ring, struct fd6_emit *emit) assert_dt
*/
if ((dirty & (FD_DIRTY_VIEWPORT | FD_DIRTY_RASTERIZER)) &&
fd_depth_clamp_enabled(ctx)) {
struct pipe_viewport_state *vp = & ctx->viewport[0];
float zmin, zmax;
util_viewport_zmin_zmax(&ctx->viewport, ctx->rasterizer->clip_halfz,
util_viewport_zmin_zmax(vp, ctx->rasterizer->clip_halfz,
&zmin, &zmax);
OUT_REG(ring, A6XX_GRAS_CL_Z_CLAMP_MIN(0, zmin),

View file

@ -88,8 +88,8 @@ fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) assert_dt
util_blitter_save_so_targets(ctx->blitter, ctx->streamout.num_targets,
ctx->streamout.targets);
util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
util_blitter_save_viewport(ctx->blitter, &ctx->viewport[0]);
util_blitter_save_scissor(ctx->blitter, &ctx->scissor[0]);
util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fs);
util_blitter_save_blend(ctx->blitter, ctx->blend);
util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);

View file

@ -665,7 +665,7 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
list_add(&ctx->node, &ctx->screen->context_list);
fd_screen_unlock(ctx->screen);
ctx->current_scissor = &ctx->disabled_scissor;
ctx->current_scissor = ctx->disabled_scissor;
fd_gpu_tracepoint_config_variable();
u_trace_pipe_context_init(&ctx->trace_context, pctx,

View file

@ -351,13 +351,13 @@ struct fd_context {
/* points to either scissor or disabled_scissor depending on rast state: */
struct pipe_scissor_state *current_scissor dt;
struct pipe_scissor_state scissor dt;
struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS] dt;
/* we don't have a disable/enable bit for scissor, so instead we keep
* a disabled-scissor state which matches the entire bound framebuffer
* and use that when scissor is not enabled.
*/
struct pipe_scissor_state disabled_scissor dt;
struct pipe_scissor_state disabled_scissor[PIPE_MAX_VIEWPORTS] dt;
/* Per vsc pipe bo's (a2xx-a5xx): */
struct fd_bo *vsc_pipe_bo[32] dt;
@ -399,8 +399,8 @@ struct fd_context {
/* local context fb state, for when ctx->batch is null: */
struct pipe_framebuffer_state framebuffer dt;
struct pipe_poly_stipple stipple dt;
struct pipe_viewport_state viewport dt;
struct pipe_scissor_state viewport_scissor dt;
struct pipe_viewport_state viewport[PIPE_MAX_VIEWPORTS] dt;
struct pipe_scissor_state viewport_scissor[PIPE_MAX_VIEWPORTS] dt;
struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES] dt;
struct fd_shaderbuf_stateobj shaderbuf[PIPE_SHADER_TYPES] dt;
struct fd_shaderimg_stateobj shaderimg[PIPE_SHADER_TYPES] dt;

View file

@ -310,10 +310,12 @@ fd_set_framebuffer_state(struct pipe_context *pctx,
fd_context_dirty(ctx, FD_DIRTY_FRAMEBUFFER);
ctx->disabled_scissor.minx = 0;
ctx->disabled_scissor.miny = 0;
ctx->disabled_scissor.maxx = cso->width;
ctx->disabled_scissor.maxy = cso->height;
for (unsigned i = 0; i < PIPE_MAX_VIEWPORTS; i++) {
ctx->disabled_scissor[i].minx = 0;
ctx->disabled_scissor[i].miny = 0;
ctx->disabled_scissor[i].maxx = cso->width;
ctx->disabled_scissor[i].maxy = cso->height;
}
fd_context_dirty(ctx, FD_DIRTY_SCISSOR);
update_draw_cost(ctx);
@ -335,44 +337,50 @@ fd_set_scissor_states(struct pipe_context *pctx, unsigned start_slot,
{
struct fd_context *ctx = fd_context(pctx);
ctx->scissor = *scissor;
for (unsigned i = 0; i < num_scissors; i++)
ctx->scissor[start_slot + i] = scissor[i];
fd_context_dirty(ctx, FD_DIRTY_SCISSOR);
}
static void
fd_set_viewport_states(struct pipe_context *pctx, unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *viewport) in_dt
const struct pipe_viewport_state *viewports) in_dt
{
struct fd_context *ctx = fd_context(pctx);
struct pipe_scissor_state *scissor = &ctx->viewport_scissor;
float minx, miny, maxx, maxy;
ctx->viewport = *viewport;
for (unsigned i = 0; i < num_viewports; i++) {
unsigned idx = start_slot + i;
struct pipe_scissor_state *scissor = &ctx->viewport_scissor[idx];
const struct pipe_viewport_state *viewport = &viewports[i];
/* see si_get_scissor_from_viewport(): */
ctx->viewport[idx] = *viewport;
/* Convert (-1, -1) and (1, 1) from clip space into window space. */
minx = -viewport->scale[0] + viewport->translate[0];
miny = -viewport->scale[1] + viewport->translate[1];
maxx = viewport->scale[0] + viewport->translate[0];
maxy = viewport->scale[1] + viewport->translate[1];
/* see si_get_scissor_from_viewport(): */
/* Handle inverted viewports. */
if (minx > maxx) {
swap(minx, maxx);
/* Convert (-1, -1) and (1, 1) from clip space into window space. */
float minx = -viewport->scale[0] + viewport->translate[0];
float miny = -viewport->scale[1] + viewport->translate[1];
float maxx = viewport->scale[0] + viewport->translate[0];
float maxy = viewport->scale[1] + viewport->translate[1];
/* Handle inverted viewports. */
if (minx > maxx) {
swap(minx, maxx);
}
if (miny > maxy) {
swap(miny, maxy);
}
const float max_dims = ctx->screen->gen >= 4 ? 16384.f : 4096.f;
/* Clamp, convert to integer and round up the max bounds. */
scissor->minx = CLAMP(minx, 0.f, max_dims);
scissor->miny = CLAMP(miny, 0.f, max_dims);
scissor->maxx = CLAMP(ceilf(maxx), 0.f, max_dims);
scissor->maxy = CLAMP(ceilf(maxy), 0.f, max_dims);
}
if (miny > maxy) {
swap(miny, maxy);
}
const float max_dims = ctx->screen->gen >= 4 ? 16384.f : 4096.f;
/* Clamp, convert to integer and round up the max bounds. */
scissor->minx = CLAMP(minx, 0.f, max_dims);
scissor->miny = CLAMP(miny, 0.f, max_dims);
scissor->maxx = CLAMP(ceilf(maxx), 0.f, max_dims);
scissor->maxy = CLAMP(ceilf(maxy), 0.f, max_dims);
fd_context_dirty(ctx, FD_DIRTY_VIEWPORT);
}
@ -463,9 +471,9 @@ fd_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
fd_context_dirty(ctx, FD_DIRTY_RASTERIZER);
if (ctx->rasterizer && ctx->rasterizer->scissor) {
ctx->current_scissor = &ctx->scissor;
ctx->current_scissor = ctx->scissor;
} else {
ctx->current_scissor = &ctx->disabled_scissor;
ctx->current_scissor = ctx->disabled_scissor;
}
/* if scissor enable bit changed we need to mark scissor