i965: Disable dual source blending when shader doesn't support it on gen8+
authorDanylo Piliaiev <danylo.piliaiev@gmail.com>
Mon, 2 Jul 2018 14:04:23 +0000 (17:04 +0300)
committerKenneth Graunke <kenneth@whitecape.org>
Tue, 30 Oct 2018 19:59:53 +0000 (12:59 -0700)
Dual source blending behaviour is undefined when shader doesn't
have second color output, dismissing fragment in such situation
leads to a hang on gen8+ if depth test in enabled.

Since blending cannot be gracefully fixed in such case and the result
is undefined - blending is simply disabled.

v2 (Kenneth Graunke):
 - Listen to BRW_NEW_FS_PROG_DATA in 3DSTATE_PS_BLEND
 - Also whack BLEND_STATE[] to keep the two in sync, since we're not
   sure exactly which copy of the redundant info the hardware will use.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107088
Signed-off-by: Danylo Piliaiev <danylo.piliaiev@globallogic.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/genX_state_upload.c

index 740cb0c4d2edc41842aa37866795ff7f78ddab7c..9cd017a5cfff87bcfb1bb39d2ed01581a839c85c 100644 (file)
@@ -3051,7 +3051,26 @@ set_blend_entry_bits(struct brw_context *brw, BLEND_ENTRY_GENXML *entry, int i,
          dstA = fix_dual_blend_alpha_to_one(dstA);
       }
 
-      entry->ColorBufferBlendEnable = true;
+      /* BRW_NEW_FS_PROG_DATA */
+      const struct brw_wm_prog_data *wm_prog_data =
+         brw_wm_prog_data(brw->wm.base.prog_data);
+
+      /* The Dual Source Blending documentation says:
+       *
+       * "If SRC1 is included in a src/dst blend factor and
+       * a DualSource RT Write message is not used, results
+       * are UNDEFINED. (This reflects the same restriction in DX APIs,
+       * where undefined results are produced if “o1” is not written
+       * by a PS – there are no default values defined).
+       * If SRC1 is not included in a src/dst blend factor,
+       * dual source blending must be disabled."
+       *
+       * There is no way to gracefully fix this undefined situation
+       * so we just disable the blending to prevent possible issues.
+       */
+      entry->ColorBufferBlendEnable =
+         !ctx->Color.Blend[0]._UsesDualSrc || wm_prog_data->dual_src_blend;
+
       entry->DestinationBlendFactor = blend_factor(dstRGB);
       entry->SourceBlendFactor = blend_factor(srcRGB);
       entry->DestinationAlphaBlendFactor = blend_factor(dstA);
@@ -3197,6 +3216,7 @@ static const struct brw_tracked_state genX(blend_state) = {
               _NEW_MULTISAMPLE,
       .brw = BRW_NEW_BATCH |
              BRW_NEW_BLORP |
+             BRW_NEW_FS_PROG_DATA |
              BRW_NEW_STATE_BASE_ADDRESS,
    },
    .emit = genX(upload_blend_state),
@@ -4829,7 +4849,25 @@ genX(upload_ps_blend)(struct brw_context *brw)
             dstA = fix_dual_blend_alpha_to_one(dstA);
          }
 
-         pb.ColorBufferBlendEnable = true;
+         /* BRW_NEW_FS_PROG_DATA */
+         const struct brw_wm_prog_data *wm_prog_data =
+            brw_wm_prog_data(brw->wm.base.prog_data);
+
+         /* The Dual Source Blending documentation says:
+          *
+          * "If SRC1 is included in a src/dst blend factor and
+          * a DualSource RT Write message is not used, results
+          * are UNDEFINED. (This reflects the same restriction in DX APIs,
+          * where undefined results are produced if “o1” is not written
+          * by a PS – there are no default values defined).
+          * If SRC1 is not included in a src/dst blend factor,
+          * dual source blending must be disabled."
+          *
+          * There is no way to gracefully fix this undefined situation
+          * so we just disable the blending to prevent possible issues.
+          */
+         pb.ColorBufferBlendEnable =
+            !color->Blend[0]._UsesDualSrc || wm_prog_data->dual_src_blend;
          pb.SourceAlphaBlendFactor = brw_translate_blend_factor(srcA);
          pb.DestinationAlphaBlendFactor = brw_translate_blend_factor(dstA);
          pb.SourceBlendFactor = brw_translate_blend_factor(srcRGB);
@@ -4848,7 +4886,8 @@ static const struct brw_tracked_state genX(ps_blend) = {
               _NEW_MULTISAMPLE,
       .brw = BRW_NEW_BLORP |
              BRW_NEW_CONTEXT |
-             BRW_NEW_FRAGMENT_PROGRAM,
+             BRW_NEW_FRAGMENT_PROGRAM |
+             BRW_NEW_FS_PROG_DATA,
    },
    .emit = genX(upload_ps_blend)
 };