Before, we were trusting in the hardware to take the intersection of the viewport clip with the drawing rectangle. Unfortunately, 3DSTATE_DRAWING_RECTANGLE is fairly expensive because it implicitly does a full pipeline stall. If we're a bit more careful with our viewport clipping, we can just re-emit it once at context creation time. --- src/mesa/drivers/dri/i965/genX_state_upload.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c index b7a6cd7..9fe90a2 100644 --- a/src/mesa/drivers/dri/i965/genX_state_upload.c +++ b/src/mesa/drivers/dri/i965/genX_state_upload.c @@ -2451,24 +2451,28 @@ genX(upload_sf_clip_viewport)(struct brw_context *brw) #elif GEN_GEN >= 8 /* _NEW_VIEWPORT | _NEW_BUFFERS: Screen Space Viewport * The hardware will take the intersection of the drawing rectangle, - * scissor rectangle, and the viewport extents. We don't need to be - * smart, and can therefore just program the viewport extents. + * scissor rectangle, and the viewport extents. However, emitting + * 3DSTATE_DRAWING_RECTANGLE is expensive since it requires a full + * pipeline stall so we're better off just being a little more clever + * with our viewport so we can emit it once at context creation time. */ + const float viewport_Xmin = MAX2(ctx->ViewportArray[i].X, 0); + const float viewport_Ymin = MAX2(ctx->ViewportArray[i].Y, 0); const float viewport_Xmax = - ctx->ViewportArray[i].X + ctx->ViewportArray[i].Width; + MIN2(ctx->ViewportArray[i].X + ctx->ViewportArray[i].Width, fb_width); const float viewport_Ymax = - ctx->ViewportArray[i].Y + ctx->ViewportArray[i].Height; + MIN2(ctx->ViewportArray[i].Y + ctx->ViewportArray[i].Height, fb_height); if (render_to_fbo) { - sfv.XMinViewPort = ctx->ViewportArray[i].X; + sfv.XMinViewPort = viewport_Xmin; sfv.XMaxViewPort = viewport_Xmax - 1; - sfv.YMinViewPort = ctx->ViewportArray[i].Y; + sfv.YMinViewPort = viewport_Ymin; sfv.YMaxViewPort = viewport_Ymax - 1; } else { - sfv.XMinViewPort = ctx->ViewportArray[i].X; + sfv.XMinViewPort = viewport_Xmin; sfv.XMaxViewPort = viewport_Xmax - 1; sfv.YMinViewPort = fb_height - viewport_Ymax; - sfv.YMaxViewPort = fb_height - ctx->ViewportArray[i].Y - 1; + sfv.YMaxViewPort = fb_height - viewport_Ymin - 1; } #endif -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev