i965: Disable guardband clipping in the smaller-than-viewport case.
authorKenneth Graunke <kenneth@whitecape.org>
Tue, 26 Aug 2014 23:39:55 +0000 (16:39 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 10 Sep 2014 18:40:30 +0000 (11:40 -0700)
Apparently guardband clipping doesn't work like we thought: objects
entirely outside fthe guardband are trivially rejected, regardless of
their relation to the viewport.  Normally, the guardband is larger than
the viewport, so this is not a problem.  However, when the viewport is
larger than the guardband, this means that we would discard primitives
which were wholly outside of the guardband, but still visible.

We always program the guardband to 8K x 8K to enforce the restriction
that the screenspace bounding box of a single triangle must be no more
than 8K x 8K.  So, if the viewport is larger than that, we need to
disable guardband clipping.

Fixes ES3 conformance tests:
- framebuffer_blit_functionality_negative_height_blit
- framebuffer_blit_functionality_negative_width_blit
- framebuffer_blit_functionality_negative_dimensions_blit
- framebuffer_blit_functionality_magnifying_blit
- framebuffer_blit_functionality_multisampled_to_singlesampled_blit

v2: Mention the acronym expansion for TA/TR/MC in the comments.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/mesa/drivers/dri/i965/gen6_clip_state.c

index e8c1b915172cc1d00ce0de721aad2e057dfca308..ab0828135be05ce99c0017e8eb822b2cab4739b0 100644 (file)
@@ -98,6 +98,37 @@ upload_clip_state(struct brw_context *brw)
 
    dw2 |= GEN6_CLIP_GB_TEST;
 
+   /* We need to disable guardband clipping if the guardband (which we always
+    * program to the maximum screen-space bounding box of 8K x 8K) will be
+    * smaller than the viewport.
+    *
+    * Closely examining the clip determination formulas in the documentation
+    * reveals that objects will be discarded entirely if they're outside the
+    * (small) guardband, even if they're within the (large) viewport:
+    *
+    *     TR = TR_GB || TR_VPXY || TR_VPZ || TR_UC || TR_NEGW
+    *     TA   = !TR && TA_GB && TA_VPZ && TA_NEGW
+    *     MC = !(TA || TR)
+    *
+    * (TA is "Trivial Accept", TR is "Trivial Reject", MC is "Must Clip".)
+    *
+    * Disabling guardband clipping removes the TR_GB condition, which means
+    * they'll be considered MC ("Must Clip") unless they're rejected for
+    * some other reason.
+    *
+    * Note that there is no TA_VPXY condition.  If there were, objects entirely
+    * inside a 16384x16384 viewport would be trivially accepted, breaking the
+    * "objects must have a screenspace bounding box not exceeding 8K in the X
+    * or Y direction" restriction.  Instead, they're clipped.
+    */
+   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
+      if (ctx->ViewportArray[i].Width > 8192 ||
+          ctx->ViewportArray[i].Height > 8192) {
+         dw2 &= ~GEN6_CLIP_GB_TEST;
+         break;
+      }
+   }
+
    /* If the viewport dimensions are smaller than the drawable dimensions,
     * we have to disable guardband clipping prior to Gen8.  We always program
     * the guardband to a fixed size, which is almost always larger than the