[Mesa-dev] [PATCH] anv: Disable dual source blending when shader doesn't support it on gen8+

Danylo Piliaiev danylo.piliaiev at gmail.com
Fri Jul 20 09:54:42 UTC 2018


Dual source blending behaviour is undefined when shader doesn't
have second color output.

 "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)."

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.

Signed-off-by: Danylo Piliaiev <danylo.piliaiev at globallogic.com>
---

Also there is a similar patch which fixes the same issue
for OpenGL https://patchwork.freedesktop.org/patch/235939

 src/intel/vulkan/genX_pipeline.c | 43 ++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c
index 0821d71c9f..d7c532a22d 100644
--- a/src/intel/vulkan/genX_pipeline.c
+++ b/src/intel/vulkan/genX_pipeline.c
@@ -854,6 +854,15 @@ emit_ds_state(struct anv_pipeline *pipeline,
 #endif
 }
 
+MAYBE_UNUSED static bool
+is_dual_src_blend_factor(VkBlendFactor factor)
+{
+   return factor == VK_BLEND_FACTOR_SRC1_COLOR ||
+          factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR ||
+          factor == VK_BLEND_FACTOR_SRC1_ALPHA ||
+          factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
+}
+
 static void
 emit_cb_state(struct anv_pipeline *pipeline,
               const VkPipelineColorBlendStateCreateInfo *info,
@@ -886,6 +895,7 @@ emit_cb_state(struct anv_pipeline *pipeline,
    state_pos += GENX(BLEND_STATE_length);
 #if GEN_GEN >= 8
    struct GENX(BLEND_STATE_ENTRY) bs0 = { 0 };
+   bool force_disable_color_blend = false;
 #endif
    for (unsigned i = 0; i < surface_count; i++) {
       struct anv_pipeline_binding *binding = &map->surface_to_descriptor[i];
@@ -969,8 +979,27 @@ emit_cb_state(struct anv_pipeline *pipeline,
       GENX(BLEND_STATE_ENTRY_pack)(NULL, state_pos, &entry);
       state_pos += GENX(BLEND_STATE_ENTRY_length);
 #if GEN_GEN >= 8
-      if (i == 0)
+      if (i == 0) {
          bs0 = entry;
+
+         /* 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)."
+          *
+          * There is no way to gracefully fix this undefined situation
+          * so we just disable the blending to prevent possible issues.
+          */
+         const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
+         force_disable_color_blend = !wm_prog_data->dual_src_blend &&
+            (is_dual_src_blend_factor(a->srcColorBlendFactor) ||
+            is_dual_src_blend_factor(a->dstColorBlendFactor) ||
+            is_dual_src_blend_factor(a->srcAlphaBlendFactor) ||
+            is_dual_src_blend_factor(a->dstAlphaBlendFactor));
+      }
 #endif
    }
 
@@ -978,7 +1007,8 @@ emit_cb_state(struct anv_pipeline *pipeline,
    anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS_BLEND), blend) {
       blend.AlphaToCoverageEnable         = blend_state.AlphaToCoverageEnable;
       blend.HasWriteableRT                = has_writeable_rt;
-      blend.ColorBufferBlendEnable        = bs0.ColorBufferBlendEnable;
+      blend.ColorBufferBlendEnable        =
+         bs0.ColorBufferBlendEnable && !force_disable_color_blend;
       blend.SourceAlphaBlendFactor        = bs0.SourceAlphaBlendFactor;
       blend.DestinationAlphaBlendFactor   = bs0.DestinationAlphaBlendFactor;
       blend.SourceBlendFactor             = bs0.SourceBlendFactor;
@@ -1430,15 +1460,6 @@ emit_3dstate_wm(struct anv_pipeline *pipeline, struct anv_subpass *subpass,
    }
 }
 
-UNUSED static bool
-is_dual_src_blend_factor(VkBlendFactor factor)
-{
-   return factor == VK_BLEND_FACTOR_SRC1_COLOR ||
-          factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR ||
-          factor == VK_BLEND_FACTOR_SRC1_ALPHA ||
-          factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
-}
-
 static void
 emit_3dstate_ps(struct anv_pipeline *pipeline,
                 const VkPipelineColorBlendStateCreateInfo *blend,
-- 
2.17.1



More information about the mesa-dev mailing list