tu: Implement dual-src blending
authorConnor Abbott <cwabbott0@gmail.com>
Thu, 14 May 2020 15:17:46 +0000 (17:17 +0200)
committerMarge Bot <eric+marge@anholt.net>
Thu, 14 May 2020 18:15:31 +0000 (18:15 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5039>

src/freedreno/vulkan/tu_pipeline.c

index 5882f3325f64798ed170c0198b67eb7e020efd70..54c5103aa3f07c42b73f8427f2c43a7b9030297e 100644 (file)
@@ -298,6 +298,7 @@ struct tu_pipeline_builder
    /* these states are affectd by rasterizer_discard */
    VkSampleCountFlagBits samples;
    bool use_color_attachments;
+   bool use_dual_src_blend;
    uint32_t color_attachment_count;
    VkFormat color_attachment_formats[MAX_RTS];
    VkFormat depth_attachment_format;
@@ -383,6 +384,37 @@ tu_blend_factor_no_dst_alpha(VkBlendFactor factor)
    }
 }
 
+static bool tu_blend_factor_is_dual_src(VkBlendFactor factor)
+{
+   switch (factor) {
+   case VK_BLEND_FACTOR_SRC1_COLOR:
+   case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
+   case VK_BLEND_FACTOR_SRC1_ALPHA:
+   case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
+      return true;
+   default:
+      return false;
+   }
+}
+
+static bool
+tu_blend_state_is_dual_src(const VkPipelineColorBlendStateCreateInfo *info)
+{
+   if (!info)
+      return false;
+
+   for (unsigned i = 0; i < info->attachmentCount; i++) {
+      const VkPipelineColorBlendAttachmentState *blend = &info->pAttachments[i];
+      if (tu_blend_factor_is_dual_src(blend->srcColorBlendFactor) ||
+          tu_blend_factor_is_dual_src(blend->dstColorBlendFactor) ||
+          tu_blend_factor_is_dual_src(blend->srcAlphaBlendFactor) ||
+          tu_blend_factor_is_dual_src(blend->dstAlphaBlendFactor))
+         return true;
+   }
+
+   return false;
+}
+
 static enum pc_di_primtype
 tu6_primtype(VkPrimitiveTopology topology)
 {
@@ -1305,7 +1337,7 @@ tu6_emit_fs_inputs(struct tu_cs *cs, const struct ir3_shader_variant *fs)
 static void
 tu6_emit_fs_outputs(struct tu_cs *cs,
                     const struct ir3_shader_variant *fs,
-                    uint32_t mrt_count)
+                    uint32_t mrt_count, bool dual_src_blend)
 {
    uint32_t smask_regid, posz_regid;
 
@@ -1327,6 +1359,7 @@ tu6_emit_fs_outputs(struct tu_cs *cs,
    tu_cs_emit_pkt4(cs, REG_A6XX_SP_FS_OUTPUT_CNTL0, 2);
    tu_cs_emit(cs, A6XX_SP_FS_OUTPUT_CNTL0_DEPTH_REGID(posz_regid) |
                   A6XX_SP_FS_OUTPUT_CNTL0_SAMPMASK_REGID(smask_regid) |
+                  COND(dual_src_blend, A6XX_SP_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE) |
                   0xfc000000);
    tu_cs_emit(cs, A6XX_SP_FS_OUTPUT_CNTL1_MRT(mrt_count));
 
@@ -1343,7 +1376,8 @@ tu6_emit_fs_outputs(struct tu_cs *cs,
 
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_FS_OUTPUT_CNTL0, 2);
    tu_cs_emit(cs, COND(fs->writes_pos, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_Z) |
-                  COND(fs->writes_smask, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK));
+                  COND(fs->writes_smask, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK) |
+                  COND(dual_src_blend, A6XX_RB_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE));
    tu_cs_emit(cs, A6XX_RB_FS_OUTPUT_CNTL1_MRT(mrt_count));
 
    tu_cs_emit_regs(cs,
@@ -1561,7 +1595,8 @@ tu6_emit_program(struct tu_cs *cs,
    tu6_emit_vpc(cs, vs, gs, fs, binning_pass, tf);
    tu6_emit_vpc_varying_modes(cs, fs, binning_pass);
    tu6_emit_fs_inputs(cs, fs);
-   tu6_emit_fs_outputs(cs, fs, builder->color_attachment_count);
+   tu6_emit_fs_outputs(cs, fs, builder->color_attachment_count,
+                       builder->use_dual_src_blend);
 
    tu6_emit_shader_object(cs, MESA_SHADER_VERTEX, vs, binary_bo,
       binning_pass ? builder->binning_vs_offset : builder->shader_offsets[MESA_SHADER_VERTEX]);
@@ -2029,6 +2064,7 @@ tu6_emit_rb_mrt_controls(struct tu_cs *cs,
 static void
 tu6_emit_blend_control(struct tu_cs *cs,
                        uint32_t blend_enable_mask,
+                       bool dual_src_blend,
                        const VkPipelineMultisampleStateCreateInfo *msaa_info)
 {
    assert(!msaa_info->alphaToOneEnable);
@@ -2036,6 +2072,8 @@ tu6_emit_blend_control(struct tu_cs *cs,
    uint32_t sp_blend_cntl = A6XX_SP_BLEND_CNTL_UNK8;
    if (blend_enable_mask)
       sp_blend_cntl |= A6XX_SP_BLEND_CNTL_ENABLED;
+   if (dual_src_blend)
+      sp_blend_cntl |= A6XX_SP_BLEND_CNTL_DUAL_COLOR_IN_ENABLE;
    if (msaa_info->alphaToCoverageEnable)
       sp_blend_cntl |= A6XX_SP_BLEND_CNTL_ALPHA_TO_COVERAGE;
 
@@ -2048,6 +2086,8 @@ tu6_emit_blend_control(struct tu_cs *cs,
       A6XX_RB_BLEND_CNTL_ENABLE_BLEND(blend_enable_mask) |
       A6XX_RB_BLEND_CNTL_INDEPENDENT_BLEND |
       A6XX_RB_BLEND_CNTL_SAMPLE_MASK(sample_mask);
+   if (dual_src_blend)
+      rb_blend_cntl |= A6XX_RB_BLEND_CNTL_DUAL_COLOR_IN_ENABLE;
    if (msaa_info->alphaToCoverageEnable)
       rb_blend_cntl |= A6XX_RB_BLEND_CNTL_ALPHA_TO_COVERAGE;
 
@@ -2478,7 +2518,8 @@ tu_pipeline_builder_parse_multisample_and_color_blend(
       tu6_emit_sample_locations(&blend_cs, samp_loc);
    }
 
-   tu6_emit_blend_control(&blend_cs, blend_enable_mask, msaa_info);
+   tu6_emit_blend_control(&blend_cs, blend_enable_mask,
+                          builder->use_dual_src_blend, msaa_info);
 
    pipeline->blend.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &blend_cs);
 }
@@ -2592,6 +2633,11 @@ tu_pipeline_builder_init_graphics(
          builder->color_attachment_formats[i] = pass->attachments[a].format;
          builder->use_color_attachments = true;
       }
+
+      if (tu_blend_state_is_dual_src(create_info->pColorBlendState)) {
+         builder->color_attachment_count++;
+         builder->use_dual_src_blend = true;
+      }
    }
 }