Module: Mesa
Branch: main
Commit: daa2aeaa0c74f2d7cc6a7b7a9a707afc0ca766bb
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=daa2aeaa0c74f2d7cc6a7b7a9a707afc0ca766bb

Author: Samuel Pitoiset <[email protected]>
Date:   Fri Jan  6 15:29:44 2023 +0100

radv: add support for dynamic blend equation

Signed-off-by: Samuel Pitoiset <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20281>

---

 src/amd/vulkan/radv_cmd_buffer.c | 210 +++++++++++++++++++++++++++++++++------
 src/amd/vulkan/radv_pipeline.c   | 112 +++------------------
 src/amd/vulkan/radv_private.h    |  24 ++---
 src/amd/vulkan/radv_shader.h     |   2 -
 4 files changed, 205 insertions(+), 143 deletions(-)

diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c
index a2cc6dab4c3..4ac63915b33 100644
--- a/src/amd/vulkan/radv_cmd_buffer.c
+++ b/src/amd/vulkan/radv_cmd_buffer.c
@@ -245,6 +245,25 @@ radv_bind_dynamic_state(struct radv_cmd_buffer 
*cmd_buffer, const struct radv_dy
       }
    }
 
+   if (copy_mask & RADV_DYNAMIC_COLOR_BLEND_EQUATION) {
+      for (uint32_t i = 0; i < MAX_RTS; i++) {
+         if (dest->vk.cb.attachments[i].src_color_blend_factor != 
src->vk.cb.attachments[i].src_color_blend_factor ||
+             dest->vk.cb.attachments[i].dst_color_blend_factor != 
src->vk.cb.attachments[i].dst_color_blend_factor ||
+             dest->vk.cb.attachments[i].color_blend_op != 
src->vk.cb.attachments[i].color_blend_op ||
+             dest->vk.cb.attachments[i].src_alpha_blend_factor != 
src->vk.cb.attachments[i].src_alpha_blend_factor ||
+             dest->vk.cb.attachments[i].dst_alpha_blend_factor != 
src->vk.cb.attachments[i].dst_alpha_blend_factor ||
+             dest->vk.cb.attachments[i].alpha_blend_op != 
src->vk.cb.attachments[i].alpha_blend_op) {
+            dest->vk.cb.attachments[i].src_color_blend_factor = 
src->vk.cb.attachments[i].src_color_blend_factor;
+            dest->vk.cb.attachments[i].dst_color_blend_factor = 
src->vk.cb.attachments[i].dst_color_blend_factor;
+            dest->vk.cb.attachments[i].color_blend_op = 
src->vk.cb.attachments[i].color_blend_op;
+            dest->vk.cb.attachments[i].src_alpha_blend_factor = 
src->vk.cb.attachments[i].src_alpha_blend_factor;
+            dest->vk.cb.attachments[i].dst_alpha_blend_factor = 
src->vk.cb.attachments[i].dst_alpha_blend_factor;
+            dest->vk.cb.attachments[i].alpha_blend_op = 
src->vk.cb.attachments[i].alpha_blend_op;
+            dest_mask |= RADV_DYNAMIC_COLOR_BLEND_EQUATION;
+         }
+      }
+   }
+
 #define RADV_CMP_COPY(field, flag)                                \
    if (copy_mask & flag) {                                        \
       if (dest->field != src->field) {                            \
@@ -1939,17 +1958,10 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer 
*cmd_buffer)
       if 
(radv_rast_prim_is_points_or_lines(cmd_buffer->state.emitted_graphics_pipeline->rast_prim)
 != radv_rast_prim_is_points_or_lines(pipeline->rast_prim))
          cmd_buffer->state.dirty |= RADV_CMD_DIRTY_GUARDBAND;
 
-      if (cmd_buffer->state.emitted_graphics_pipeline->mrt0_is_dual_src != 
pipeline->mrt0_is_dual_src ||
-          cmd_buffer->state.emitted_graphics_pipeline->custom_blend_mode != 
pipeline->custom_blend_mode)
+      if (cmd_buffer->state.emitted_graphics_pipeline->custom_blend_mode != 
pipeline->custom_blend_mode)
          cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP |
                                     RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP_ENABLE;
 
-      if (memcmp(cmd_buffer->state.emitted_graphics_pipeline->cb_blend_control,
-                 pipeline->cb_blend_control, 
sizeof(pipeline->cb_blend_control)) ||
-          memcmp(cmd_buffer->state.emitted_graphics_pipeline->sx_mrt_blend_opt,
-                 pipeline->sx_mrt_blend_opt, 
sizeof(pipeline->sx_mrt_blend_opt)))
-         cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_ENABLE;
-
       if 
(cmd_buffer->state.emitted_graphics_pipeline->ms.sample_shading_enable != 
pipeline->ms.sample_shading_enable ||
           cmd_buffer->state.emitted_graphics_pipeline->ms.min_sample_shading 
!= pipeline->ms.min_sample_shading ||
           cmd_buffer->state.emitted_graphics_pipeline->pa_sc_mode_cntl_1 != 
pipeline->pa_sc_mode_cntl_1 ||
@@ -2401,6 +2413,26 @@ radv_emit_clipping(struct radv_cmd_buffer *cmd_buffer)
                              S_028810_DX_LINEAR_ATTR_CLIP_ENA(1));
 }
 
+static bool
+radv_is_mrt0_dual_src(struct radv_cmd_buffer *cmd_buffer)
+{
+   const struct radv_dynamic_state *d = &cmd_buffer->state.dynamic;
+
+   if (!d->vk.cb.attachments[0].write_mask || 
!d->vk.cb.attachments[0].blend_enable)
+      return false;
+
+   const struct vk_color_blend_attachment_state att = {
+      .color_blend_op = d->vk.cb.attachments[0].color_blend_op,
+      .src_color_blend_factor = d->vk.cb.attachments[0].src_color_blend_factor,
+      .dst_color_blend_factor = d->vk.cb.attachments[0].dst_color_blend_factor,
+      .alpha_blend_op = d->vk.cb.attachments[0].alpha_blend_op,
+      .src_alpha_blend_factor = d->vk.cb.attachments[0].src_alpha_blend_factor,
+      .dst_alpha_blend_factor = d->vk.cb.attachments[0].dst_alpha_blend_factor,
+   };
+
+   return radv_can_enable_dual_src(&att);
+}
+
 static void
 radv_emit_logic_op(struct radv_cmd_buffer *cmd_buffer)
 {
@@ -2416,8 +2448,10 @@ radv_emit_logic_op(struct radv_cmd_buffer *cmd_buffer)
 
    if (cmd_buffer->device->physical_device->rad_info.has_rbplus) {
       /* RB+ doesn't work with dual source blending, logic op and CB_RESOLVE. 
*/
+      bool mrt0_is_dual_src = radv_is_mrt0_dual_src(cmd_buffer);
+
       cb_color_control |=
-         S_028808_DISABLE_DUAL_QUAD(pipeline->mrt0_is_dual_src || 
d->vk.cb.logic_op_enable ||
+         S_028808_DISABLE_DUAL_QUAD(mrt0_is_dual_src || 
d->vk.cb.logic_op_enable ||
                                     pipeline->custom_blend_mode == 
V_028808_CB_RESOLVE);
    }
 
@@ -4056,29 +4090,98 @@ radv_emit_sample_mask(struct radv_cmd_buffer 
*cmd_buffer)
 }
 
 static void
-radv_emit_color_blend_enable(struct radv_cmd_buffer *cmd_buffer)
+radv_emit_color_blend(struct radv_cmd_buffer *cmd_buffer)
 {
    const struct radv_physical_device *pdevice = 
cmd_buffer->device->physical_device;
-   const struct radv_graphics_pipeline *pipeline = 
cmd_buffer->state.graphics_pipeline;
+   const enum amd_gfx_level gfx_level = pdevice->rad_info.gfx_level;
    const struct radv_dynamic_state *d = &cmd_buffer->state.dynamic;
    unsigned cb_blend_control[MAX_RTS], sx_mrt_blend_opt[MAX_RTS];
+   bool mrt0_is_dual_src = radv_is_mrt0_dual_src(cmd_buffer);
 
    for (unsigned i = 0; i < MAX_RTS; i++) {
-      bool blend_enable = d->vk.cb.attachments[i].blend_enable;
-
-      cb_blend_control[i] = pipeline->cb_blend_control[i];
-      sx_mrt_blend_opt[i] = pipeline->sx_mrt_blend_opt[i];
-
-      if (blend_enable) {
-         cb_blend_control[i] |= S_028780_ENABLE(1);
-      } else if (pdevice->rad_info.has_rbplus) {
-         /* Make sure to keep RB+ blend optimizations disabled for dual source 
blending. */
-         if (G_028760_COLOR_COMB_FCN(sx_mrt_blend_opt[i]) != 
V_028760_OPT_COMB_NONE &&
-             G_028760_ALPHA_COMB_FCN(sx_mrt_blend_opt[i]) != 
V_028760_OPT_COMB_NONE) {
-            sx_mrt_blend_opt[i] &= C_028760_COLOR_COMB_FCN;
-            sx_mrt_blend_opt[i] &= C_028760_ALPHA_COMB_FCN;
-            sx_mrt_blend_opt[i] |= 
S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED) |
-                                   
S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED);
+      VkBlendOp eqRGB = d->vk.cb.attachments[i].color_blend_op;
+      VkBlendFactor srcRGB = d->vk.cb.attachments[i].src_color_blend_factor;
+      VkBlendFactor dstRGB = d->vk.cb.attachments[i].dst_color_blend_factor;
+      VkBlendOp eqA = d->vk.cb.attachments[i].alpha_blend_op;
+      VkBlendFactor srcA = d->vk.cb.attachments[i].src_alpha_blend_factor;
+      VkBlendFactor dstA = d->vk.cb.attachments[i].dst_alpha_blend_factor;
+      unsigned srcRGB_opt, dstRGB_opt, srcA_opt, dstA_opt;
+      unsigned blend_cntl = 0;
+
+      cb_blend_control[i] = sx_mrt_blend_opt[i] = 0;
+
+      /* Ignore other blend targets if dual-source blending is enabled to 
prevent wrong behaviour.
+       */
+      if (i > 0 && mrt0_is_dual_src)
+         continue;
+
+      if (!d->vk.cb.attachments[i].blend_enable) {
+         sx_mrt_blend_opt[i] |= 
S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED) |
+                                
S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED);
+         continue;
+      }
+
+      radv_normalize_blend_factor(eqRGB, &srcRGB, &dstRGB);
+      radv_normalize_blend_factor(eqA, &srcA, &dstA);
+
+      /* Blending optimizations for RB+.
+       * These transformations don't change the behavior.
+       *
+       * First, get rid of DST in the blend factors:
+       *    func(src * DST, dst * 0) ---> func(src * 0, dst * SRC)
+       */
+      si_blend_remove_dst(&eqRGB, &srcRGB, &dstRGB, VK_BLEND_FACTOR_DST_COLOR,
+                          VK_BLEND_FACTOR_SRC_COLOR);
+
+      si_blend_remove_dst(&eqA, &srcA, &dstA, VK_BLEND_FACTOR_DST_COLOR,
+                          VK_BLEND_FACTOR_SRC_COLOR);
+
+      si_blend_remove_dst(&eqA, &srcA, &dstA, VK_BLEND_FACTOR_DST_ALPHA,
+                          VK_BLEND_FACTOR_SRC_ALPHA);
+
+      /* Look up the ideal settings from tables. */
+      srcRGB_opt = si_translate_blend_opt_factor(srcRGB, false);
+      dstRGB_opt = si_translate_blend_opt_factor(dstRGB, false);
+      srcA_opt = si_translate_blend_opt_factor(srcA, true);
+      dstA_opt = si_translate_blend_opt_factor(dstA, true);
+
+      /* Handle interdependencies. */
+      if (si_blend_factor_uses_dst(srcRGB))
+         dstRGB_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
+      if (si_blend_factor_uses_dst(srcA))
+         dstA_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
+
+      if (srcRGB == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE &&
+          (dstRGB == VK_BLEND_FACTOR_ZERO || dstRGB == 
VK_BLEND_FACTOR_SRC_ALPHA ||
+           dstRGB == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE))
+         dstRGB_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_A0;
+
+      /* Set the final value. */
+      sx_mrt_blend_opt[i] =
+         S_028760_COLOR_SRC_OPT(srcRGB_opt) | 
S_028760_COLOR_DST_OPT(dstRGB_opt) |
+         S_028760_COLOR_COMB_FCN(si_translate_blend_opt_function(eqRGB)) |
+         S_028760_ALPHA_SRC_OPT(srcA_opt) | S_028760_ALPHA_DST_OPT(dstA_opt) |
+         S_028760_ALPHA_COMB_FCN(si_translate_blend_opt_function(eqA));
+
+      blend_cntl |= S_028780_ENABLE(1);
+      blend_cntl |= 
S_028780_COLOR_COMB_FCN(si_translate_blend_function(eqRGB));
+      blend_cntl |= 
S_028780_COLOR_SRCBLEND(si_translate_blend_factor(gfx_level, srcRGB));
+      blend_cntl |= 
S_028780_COLOR_DESTBLEND(si_translate_blend_factor(gfx_level, dstRGB));
+      if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
+         blend_cntl |= S_028780_SEPARATE_ALPHA_BLEND(1);
+         blend_cntl |= 
S_028780_ALPHA_COMB_FCN(si_translate_blend_function(eqA));
+         blend_cntl |= 
S_028780_ALPHA_SRCBLEND(si_translate_blend_factor(gfx_level, srcA));
+         blend_cntl |= 
S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(gfx_level, dstA));
+      }
+      cb_blend_control[i] = blend_cntl;
+   }
+
+   if (pdevice->rad_info.has_rbplus) {
+      /* Disable RB+ blend optimizations for dual source blending. */
+      if (mrt0_is_dual_src) {
+         for (unsigned i = 0; i < MAX_RTS; i++) {
+            sx_mrt_blend_opt[i] = 
S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_NONE) |
+                                  
S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_NONE);
          }
       }
    }
@@ -4123,13 +4226,25 @@ lookup_ps_epilog(struct radv_cmd_buffer *cmd_buffer)
    }
 
    for (unsigned i = 0; i < MAX_RTS; i++) {
+      VkBlendOp eqRGB = d->vk.cb.attachments[i].color_blend_op;
+      VkBlendFactor srcRGB = d->vk.cb.attachments[i].src_color_blend_factor;
+      VkBlendFactor dstRGB = d->vk.cb.attachments[i].dst_color_blend_factor;
+
       state.color_write_mask |= d->vk.cb.attachments[i].write_mask << (4 * i);
       state.color_blend_enable |= d->vk.cb.attachments[i].blend_enable << (4 * 
i);
+
+      radv_normalize_blend_factor(eqRGB, &srcRGB, &dstRGB);
+
+      if (srcRGB == VK_BLEND_FACTOR_SRC_ALPHA || dstRGB == 
VK_BLEND_FACTOR_SRC_ALPHA ||
+          srcRGB == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE ||
+          dstRGB == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE ||
+          srcRGB == VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ||
+          dstRGB == VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
+         state.need_src_alpha |= 1 << i;
    }
 
-   state.mrt0_is_dual_src = pipeline->mrt0_is_dual_src;
+   state.mrt0_is_dual_src = radv_is_mrt0_dual_src(cmd_buffer);
 
-   state.need_src_alpha = pipeline->need_src_alpha;
    if (d->vk.ms.alpha_to_coverage_enable) {
       /* Select a color export format with alpha when alpha to coverage is 
enabled. */
       state.need_src_alpha |= 0x1;
@@ -4316,7 +4431,9 @@ radv_cmd_buffer_flush_dynamic_state(struct 
radv_cmd_buffer *cmd_buffer, bool pip
       radv_emit_clipping(cmd_buffer);
 
    if (states & (RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP | 
RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP_ENABLE |
-                 RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_MASK))
+                 RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_MASK |
+                 RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_ENABLE |
+                 RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_EQUATION))
       radv_emit_logic_op(cmd_buffer);
 
    if (states & (RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_ENABLE |
@@ -4342,8 +4459,10 @@ radv_cmd_buffer_flush_dynamic_state(struct 
radv_cmd_buffer *cmd_buffer, bool pip
                  RADV_CMD_DIRTY_DYNAMIC_DEPTH_CLIP_ENABLE))
       radv_emit_depth_clamp_enable(cmd_buffer);
 
-   if (states & RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_ENABLE)
-      radv_emit_color_blend_enable(cmd_buffer);
+   if (states & (RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_ENABLE |
+                 RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_MASK |
+                 RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_EQUATION))
+      radv_emit_color_blend(cmd_buffer);
 
    if (states & (RADV_CMD_DIRTY_DYNAMIC_RASTERIZATION_SAMPLES |
                  RADV_CMD_DIRTY_DYNAMIC_LINE_RASTERIZATION_MODE))
@@ -6985,6 +7104,35 @@ radv_CmdSetLineRasterizationModeEXT(VkCommandBuffer 
commandBuffer,
    state->dirty |= RADV_CMD_DIRTY_DYNAMIC_LINE_RASTERIZATION_MODE;
 }
 
+VKAPI_ATTR void VKAPI_CALL
+radv_CmdSetColorBlendEquationEXT(VkCommandBuffer commandBuffer, uint32_t 
firstAttachment,
+                                 uint32_t attachmentCount,
+                                 const VkColorBlendEquationEXT 
*pColorBlendEquations)
+{
+   RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
+   struct radv_cmd_state *state = &cmd_buffer->state;
+
+   assert(firstAttachment + attachmentCount <= MAX_RTS);
+   for (uint32_t i = 0; i < attachmentCount; i++) {
+      unsigned idx = firstAttachment + i;
+
+      state->dynamic.vk.cb.attachments[idx].src_color_blend_factor =
+         pColorBlendEquations[i].srcColorBlendFactor;
+      state->dynamic.vk.cb.attachments[idx].dst_color_blend_factor =
+         pColorBlendEquations[i].dstColorBlendFactor;
+      state->dynamic.vk.cb.attachments[idx].color_blend_op =
+         pColorBlendEquations[i].colorBlendOp;
+      state->dynamic.vk.cb.attachments[idx].src_alpha_blend_factor =
+         pColorBlendEquations[i].srcAlphaBlendFactor;
+      state->dynamic.vk.cb.attachments[idx].dst_alpha_blend_factor =
+         pColorBlendEquations[i].dstAlphaBlendFactor;
+      state->dynamic.vk.cb.attachments[idx].alpha_blend_op =
+         pColorBlendEquations[i].alphaBlendOp;
+   }
+
+   state->dirty |= RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_EQUATION;
+}
+
 VKAPI_ATTR void VKAPI_CALL
 radv_CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t 
commandBufferCount,
                         const VkCommandBuffer *pCmdBuffers)
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 2f6fc7c6831..72f9daa4a5c 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -454,100 +454,7 @@ radv_pipeline_init_blend_state(struct 
radv_graphics_pipeline *pipeline,
                                const struct vk_graphics_pipeline_state *state,
                                const struct radv_pipeline_key *key)
 {
-   const struct radv_device *device = pipeline->base.device;
    struct radv_blend_state blend = {0};
-   const enum amd_gfx_level gfx_level = 
device->physical_device->rad_info.gfx_level;
-   int i;
-
-   if (state->cb) {
-      for (i = 0; i < state->cb->attachment_count; i++) {
-         unsigned blend_cntl = 0;
-         unsigned srcRGB_opt, dstRGB_opt, srcA_opt, dstA_opt;
-         VkBlendOp eqRGB = state->cb->attachments[i].color_blend_op;
-         VkBlendFactor srcRGB = 
state->cb->attachments[i].src_color_blend_factor;
-         VkBlendFactor dstRGB = 
state->cb->attachments[i].dst_color_blend_factor;
-         VkBlendOp eqA = state->cb->attachments[i].alpha_blend_op;
-         VkBlendFactor srcA = state->cb->attachments[i].src_alpha_blend_factor;
-         VkBlendFactor dstA = state->cb->attachments[i].dst_alpha_blend_factor;
-
-         if (!state->cb->attachments[i].write_mask)
-            continue;
-
-         /* Ignore other blend targets if dual-source blending
-          * is enabled to prevent wrong behaviour.
-          */
-         if (i > 0 && key->ps.epilog.mrt0_is_dual_src)
-            continue;
-
-         if (!state->cb->attachments[i].blend_enable) {
-            pipeline->cb_blend_control[i] = blend_cntl;
-            continue;
-         }
-
-         radv_normalize_blend_factor(eqRGB, &srcRGB, &dstRGB);
-         radv_normalize_blend_factor(eqA, &srcA, &dstA);
-
-         /* Blending optimizations for RB+.
-          * These transformations don't change the behavior.
-          *
-          * First, get rid of DST in the blend factors:
-          *    func(src * DST, dst * 0) ---> func(src * 0, dst * SRC)
-          */
-         si_blend_remove_dst(&eqRGB, &srcRGB, &dstRGB, 
VK_BLEND_FACTOR_DST_COLOR,
-                             VK_BLEND_FACTOR_SRC_COLOR);
-
-         si_blend_remove_dst(&eqA, &srcA, &dstA, VK_BLEND_FACTOR_DST_COLOR,
-                             VK_BLEND_FACTOR_SRC_COLOR);
-
-         si_blend_remove_dst(&eqA, &srcA, &dstA, VK_BLEND_FACTOR_DST_ALPHA,
-                             VK_BLEND_FACTOR_SRC_ALPHA);
-
-         /* Look up the ideal settings from tables. */
-         srcRGB_opt = si_translate_blend_opt_factor(srcRGB, false);
-         dstRGB_opt = si_translate_blend_opt_factor(dstRGB, false);
-         srcA_opt = si_translate_blend_opt_factor(srcA, true);
-         dstA_opt = si_translate_blend_opt_factor(dstA, true);
-
-         /* Handle interdependencies. */
-         if (si_blend_factor_uses_dst(srcRGB))
-            dstRGB_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
-         if (si_blend_factor_uses_dst(srcA))
-            dstA_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
-
-         if (srcRGB == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE &&
-             (dstRGB == VK_BLEND_FACTOR_ZERO || dstRGB == 
VK_BLEND_FACTOR_SRC_ALPHA ||
-              dstRGB == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE))
-            dstRGB_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_A0;
-
-         /* Set the final value. */
-         pipeline->sx_mrt_blend_opt[i] =
-            S_028760_COLOR_SRC_OPT(srcRGB_opt) | 
S_028760_COLOR_DST_OPT(dstRGB_opt) |
-            S_028760_COLOR_COMB_FCN(si_translate_blend_opt_function(eqRGB)) |
-            S_028760_ALPHA_SRC_OPT(srcA_opt) | 
S_028760_ALPHA_DST_OPT(dstA_opt) |
-            S_028760_ALPHA_COMB_FCN(si_translate_blend_opt_function(eqA));
-
-         blend_cntl |= 
S_028780_COLOR_COMB_FCN(si_translate_blend_function(eqRGB));
-         blend_cntl |= 
S_028780_COLOR_SRCBLEND(si_translate_blend_factor(gfx_level, srcRGB));
-         blend_cntl |= 
S_028780_COLOR_DESTBLEND(si_translate_blend_factor(gfx_level, dstRGB));
-         if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
-            blend_cntl |= S_028780_SEPARATE_ALPHA_BLEND(1);
-            blend_cntl |= 
S_028780_ALPHA_COMB_FCN(si_translate_blend_function(eqA));
-            blend_cntl |= 
S_028780_ALPHA_SRCBLEND(si_translate_blend_factor(gfx_level, srcA));
-            blend_cntl |= 
S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(gfx_level, dstA));
-         }
-         pipeline->cb_blend_control[i] = blend_cntl;
-      }
-   }
-
-   if (device->physical_device->rad_info.has_rbplus) {
-      /* Disable RB+ blend optimizations for dual source blending. */
-      if (key->ps.epilog.mrt0_is_dual_src) {
-         for (i = 0; i < 8; i++) {
-            pipeline->sx_mrt_blend_opt[i] = 
S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_NONE) |
-                                            
S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_NONE);
-         }
-      }
-   }
 
    blend.cb_shader_mask = 
ac_get_cb_shader_mask(key->ps.epilog.spi_shader_col_format);
    blend.spi_shader_col_format = key->ps.epilog.spi_shader_col_format;
@@ -768,6 +675,8 @@ radv_dynamic_state_mask(VkDynamicState state)
       return RADV_DYNAMIC_RASTERIZATION_SAMPLES;
    case VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT:
       return RADV_DYNAMIC_LINE_RASTERIZATION_MODE;
+   case VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT:
+      return RADV_DYNAMIC_COLOR_BLEND_EQUATION;
    default:
       unreachable("Unhandled dynamic state");
    }
@@ -1365,6 +1274,19 @@ radv_pipeline_init_dynamic_state(struct 
radv_graphics_pipeline *pipeline,
       dynamic->vk.rs.line.mode = state->rs->line.mode;
    }
 
+   if (radv_pipeline_has_color_attachments(state->rp) && states & 
RADV_DYNAMIC_COLOR_BLEND_EQUATION) {
+      for (unsigned i = 0; i < state->cb->attachment_count; i++) {
+         const struct vk_color_blend_attachment_state *att = 
&state->cb->attachments[i];
+
+         dynamic->vk.cb.attachments[i].src_color_blend_factor = 
att->src_color_blend_factor;
+         dynamic->vk.cb.attachments[i].dst_color_blend_factor = 
att->dst_color_blend_factor;
+         dynamic->vk.cb.attachments[i].color_blend_op = att->color_blend_op;
+         dynamic->vk.cb.attachments[i].src_alpha_blend_factor = 
att->src_alpha_blend_factor;
+         dynamic->vk.cb.attachments[i].dst_alpha_blend_factor = 
att->dst_alpha_blend_factor;
+         dynamic->vk.cb.attachments[i].alpha_blend_op = att->alpha_blend_op;
+      }
+   }
+
    pipeline->dynamic_state.mask = states;
 }
 
@@ -2258,7 +2180,6 @@ radv_generate_ps_epilog_key(const struct 
radv_graphics_pipeline *pipeline,
    key.color_is_int10 = device->physical_device->rad_info.gfx_level < GFX8 ? 
is_int10 : 0;
    key.enable_mrt_output_nan_fixup = 
device->instance->enable_mrt_output_nan_fixup ? is_float32 : 0;
    key.mrt0_is_dual_src = state->mrt0_is_dual_src;
-   key.need_src_alpha = state->need_src_alpha;
 
    return key;
 }
@@ -5055,9 +4976,6 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline 
*pipeline, struct radv
    /* Copy the non-compacted SPI_SHADER_COL_FORMAT which is used to emit 
RBPLUS state. */
    pipeline->col_format_non_compacted = blend.spi_shader_col_format;
 
-   pipeline->mrt0_is_dual_src = key.ps.epilog.mrt0_is_dual_src;
-   pipeline->need_src_alpha = key.ps.epilog.need_src_alpha;
-
    struct radv_shader *ps = pipeline->base.shaders[MESA_SHADER_FRAGMENT];
    bool enable_mrt_compaction = !key.ps.epilog.mrt0_is_dual_src && 
!ps->info.ps.has_epilog;
    if (enable_mrt_compaction) {
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 55b2c3b54ba..ab835ff870d 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -1185,7 +1185,8 @@ enum radv_dynamic_state_bits {
    RADV_DYNAMIC_COLOR_BLEND_ENABLE = 1ull << 42,
    RADV_DYNAMIC_RASTERIZATION_SAMPLES = 1ull << 43,
    RADV_DYNAMIC_LINE_RASTERIZATION_MODE = 1ull << 44,
-   RADV_DYNAMIC_ALL = (1ull << 45) - 1,
+   RADV_DYNAMIC_COLOR_BLEND_EQUATION = 1ull << 45,
+   RADV_DYNAMIC_ALL = (1ull << 46) - 1,
 };
 
 enum radv_cmd_dirty_bits {
@@ -1236,14 +1237,15 @@ enum radv_cmd_dirty_bits {
    RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_ENABLE = 1ull << 42,
    RADV_CMD_DIRTY_DYNAMIC_RASTERIZATION_SAMPLES = 1ull << 43,
    RADV_CMD_DIRTY_DYNAMIC_LINE_RASTERIZATION_MODE = 1ull << 44,
-   RADV_CMD_DIRTY_DYNAMIC_ALL = (1ull << 45) - 1,
-   RADV_CMD_DIRTY_PIPELINE = 1ull << 45,
-   RADV_CMD_DIRTY_INDEX_BUFFER = 1ull << 46,
-   RADV_CMD_DIRTY_FRAMEBUFFER = 1ull << 47,
-   RADV_CMD_DIRTY_VERTEX_BUFFER = 1ull << 48,
-   RADV_CMD_DIRTY_STREAMOUT_BUFFER = 1ull << 49,
-   RADV_CMD_DIRTY_GUARDBAND = 1ull << 50,
-   RADV_CMD_DIRTY_RBPLUS = 1ull << 51,
+   RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_EQUATION = 1ull << 45,
+   RADV_CMD_DIRTY_DYNAMIC_ALL = (1ull << 46) - 1,
+   RADV_CMD_DIRTY_PIPELINE = 1ull << 46,
+   RADV_CMD_DIRTY_INDEX_BUFFER = 1ull << 47,
+   RADV_CMD_DIRTY_FRAMEBUFFER = 1ull << 48,
+   RADV_CMD_DIRTY_VERTEX_BUFFER = 1ull << 49,
+   RADV_CMD_DIRTY_STREAMOUT_BUFFER = 1ull << 50,
+   RADV_CMD_DIRTY_GUARDBAND = 1ull << 51,
+   RADV_CMD_DIRTY_RBPLUS = 1ull << 52,
 };
 
 enum radv_cmd_flush_bits {
@@ -2064,8 +2066,6 @@ struct radv_graphics_pipeline {
    struct radv_ia_multi_vgt_param_helpers ia_multi_vgt_param;
    uint8_t vtx_emit_num;
    uint64_t needed_dynamic_state;
-   unsigned cb_blend_control[MAX_RTS];
-   unsigned sx_mrt_blend_opt[MAX_RTS];
    uint32_t binding_stride[MAX_VBS];
    uint8_t attrib_bindings[MAX_VERTEX_ATTRIBS];
    uint32_t attrib_ends[MAX_VERTEX_ATTRIBS];
@@ -2084,8 +2084,6 @@ struct radv_graphics_pipeline {
    /* Used for rbplus */
    uint32_t col_format_non_compacted;
 
-   bool mrt0_is_dual_src;
-   uint8_t need_src_alpha;
    bool need_null_export_workaround;
 
    bool uses_drawid;
diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h
index 50bc984bf00..871384a59a6 100644
--- a/src/amd/vulkan/radv_shader.h
+++ b/src/amd/vulkan/radv_shader.h
@@ -61,8 +61,6 @@ struct radv_ps_epilog_key {
    uint8_t enable_mrt_output_nan_fixup;
 
    bool mrt0_is_dual_src;
-
-   uint8_t need_src_alpha; /* XXX: Remove this when color blend equations are 
dynamic! */
 };
 
 struct radv_pipeline_key {

Reply via email to