radv/gfx9: emit sx_mrt_blend registers
authorDave Airlie <airlied@redhat.com>
Mon, 21 Aug 2017 06:17:27 +0000 (07:17 +0100)
committerDave Airlie <airlied@redhat.com>
Thu, 24 Aug 2017 00:14:14 +0000 (01:14 +0100)
GFX9 needs the SX MRT blend registers programmed, port over
the code from radeonsi to workout the values from the blend
state, and program the registers on rbplus systems.

This fixes lots of:
dEQP-VK.pipeline.blend.*

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Cc: "17.2" <mesa-stable@lists.freedesktop.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/amd/vulkan/radv_cmd_buffer.c
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_private.h

index e45f61298726bf7dca7c00b080bb7c5ed61fa181..ea17e33092491985e51ae245fa21081e456b393c 100644 (file)
@@ -368,6 +368,10 @@ radv_emit_graphics_blend_state(struct radv_cmd_buffer *cmd_buffer,
        radeon_set_context_reg(cmd_buffer->cs, R_028B70_DB_ALPHA_TO_MASK, pipeline->graphics.blend.db_alpha_to_mask);
 
        if (cmd_buffer->device->physical_device->has_rbplus) {
+
+               radeon_set_context_reg_seq(cmd_buffer->cs, R_028760_SX_MRT0_BLEND_OPT, 8);
+               radeon_emit_array(cmd_buffer->cs, pipeline->graphics.blend.sx_mrt_blend_opt, 8);
+
                radeon_set_context_reg_seq(cmd_buffer->cs, R_028754_SX_PS_DOWNCONVERT, 3);
                radeon_emit(cmd_buffer->cs, 0); /* R_028754_SX_PS_DOWNCONVERT */
                radeon_emit(cmd_buffer->cs, 0); /* R_028758_SX_BLEND_OPT_EPSILON */
index 75371a0be5af5d8e48bc0712c20558d2a3c9c185..23b9e72f92ac0a9b2fb35b958aa7eb401bb3e2bd 100644 (file)
@@ -849,6 +849,79 @@ static uint32_t si_translate_blend_factor(VkBlendFactor factor)
        }
 }
 
+static uint32_t si_translate_blend_opt_function(VkBlendOp op)
+{
+       switch (op) {
+       case VK_BLEND_OP_ADD:
+               return V_028760_OPT_COMB_ADD;
+       case VK_BLEND_OP_SUBTRACT:
+               return V_028760_OPT_COMB_SUBTRACT;
+       case VK_BLEND_OP_REVERSE_SUBTRACT:
+               return V_028760_OPT_COMB_REVSUBTRACT;
+       case VK_BLEND_OP_MIN:
+               return V_028760_OPT_COMB_MIN;
+       case VK_BLEND_OP_MAX:
+               return V_028760_OPT_COMB_MAX;
+       default:
+               return V_028760_OPT_COMB_BLEND_DISABLED;
+       }
+}
+
+static uint32_t si_translate_blend_opt_factor(VkBlendFactor factor, bool is_alpha)
+{
+       switch (factor) {
+       case VK_BLEND_FACTOR_ZERO:
+               return V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_ALL;
+       case VK_BLEND_FACTOR_ONE:
+               return V_028760_BLEND_OPT_PRESERVE_ALL_IGNORE_NONE;
+       case VK_BLEND_FACTOR_SRC_COLOR:
+               return is_alpha ? V_028760_BLEND_OPT_PRESERVE_A1_IGNORE_A0
+                               : V_028760_BLEND_OPT_PRESERVE_C1_IGNORE_C0;
+       case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
+               return is_alpha ? V_028760_BLEND_OPT_PRESERVE_A0_IGNORE_A1
+                               : V_028760_BLEND_OPT_PRESERVE_C0_IGNORE_C1;
+       case VK_BLEND_FACTOR_SRC_ALPHA:
+               return V_028760_BLEND_OPT_PRESERVE_A1_IGNORE_A0;
+       case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
+               return V_028760_BLEND_OPT_PRESERVE_A0_IGNORE_A1;
+       case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:
+               return is_alpha ? V_028760_BLEND_OPT_PRESERVE_ALL_IGNORE_NONE
+                               : V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_A0;
+       default:
+               return V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
+       }
+}
+
+/**
+ * Get rid of DST in the blend factors by commuting the operands:
+ *    func(src * DST, dst * 0) ---> func(src * 0, dst * SRC)
+ */
+static void si_blend_remove_dst(unsigned *func, unsigned *src_factor,
+                               unsigned *dst_factor, unsigned expected_dst,
+                               unsigned replacement_src)
+{
+       if (*src_factor == expected_dst &&
+           *dst_factor == VK_BLEND_FACTOR_ZERO) {
+               *src_factor = VK_BLEND_FACTOR_ZERO;
+               *dst_factor = replacement_src;
+
+               /* Commuting the operands requires reversing subtractions. */
+               if (*func == VK_BLEND_OP_SUBTRACT)
+                       *func = VK_BLEND_OP_REVERSE_SUBTRACT;
+               else if (*func == VK_BLEND_OP_REVERSE_SUBTRACT)
+                       *func = VK_BLEND_OP_SUBTRACT;
+       }
+}
+
+static bool si_blend_factor_uses_dst(unsigned factor)
+{
+       return factor == VK_BLEND_FACTOR_DST_COLOR ||
+               factor == VK_BLEND_FACTOR_DST_ALPHA ||
+               factor == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE ||
+               factor == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA ||
+               factor == VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
+}
+
 static bool is_dual_src(VkBlendFactor factor)
 {
        switch (factor) {
@@ -1146,6 +1219,7 @@ radv_pipeline_init_blend_state(struct radv_pipeline *pipeline,
        for (i = 0; i < vkblend->attachmentCount; i++) {
                const VkPipelineColorBlendAttachmentState *att = &vkblend->pAttachments[i];
                unsigned blend_cntl = 0;
+               unsigned srcRGB_opt, dstRGB_opt, srcA_opt, dstA_opt;
                VkBlendOp eqRGB = att->colorBlendOp;
                VkBlendFactor srcRGB = att->srcColorBlendFactor;
                VkBlendFactor dstRGB = att->dstColorBlendFactor;
@@ -1153,7 +1227,7 @@ radv_pipeline_init_blend_state(struct radv_pipeline *pipeline,
                VkBlendFactor srcA = att->srcAlphaBlendFactor;
                VkBlendFactor dstA = att->dstAlphaBlendFactor;
 
-               blend->sx_mrt0_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);
+               blend->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);
 
                if (!att->colorWriteMask)
                        continue;
@@ -1177,6 +1251,50 @@ radv_pipeline_init_blend_state(struct radv_pipeline *pipeline,
                        dstA = VK_BLEND_FACTOR_ONE;
                }
 
+               /* 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. */
+               blend->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));
@@ -1200,8 +1318,14 @@ radv_pipeline_init_blend_state(struct radv_pipeline *pipeline,
                    dstRGB == VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
                        blend_need_alpha |= 1 << i;
        }
-       for (i = vkblend->attachmentCount; i < 8; i++)
+       for (i = vkblend->attachmentCount; i < 8; i++) {
                blend->cb_blend_control[i] = 0;
+               blend->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);
+       }
+
+       /* disable RB+ for now */
+       if (pipeline->device->physical_device->has_rbplus)
+               blend->cb_color_control |= S_028808_DISABLE_DUAL_QUAD(1);
 
        if (blend->cb_target_mask)
                blend->cb_color_control |= S_028808_MODE(mode);
@@ -2199,6 +2323,9 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
                S_02880C_EXEC_ON_HIER_FAIL(ps->info.fs.writes_memory) |
                S_02880C_EXEC_ON_NOOP(ps->info.fs.writes_memory);
 
+       if (pipeline->device->physical_device->has_rbplus)
+               pipeline->graphics.db_shader_control |= S_02880C_DUAL_QUAD_DISABLE(1);
+
        pipeline->graphics.shader_z_format =
                ps->info.fs.writes_sample_mask ? V_028710_SPI_SHADER_32_ABGR :
                ps->info.fs.writes_stencil ? V_028710_SPI_SHADER_32_GR :
index ca985da16d56f0ed5b26474f13e3f266f4be3164..0d46cf6c960a73641cf47e74daa876ecf92ec17d 100644 (file)
@@ -1026,7 +1026,7 @@ struct radv_depth_stencil_state {
 struct radv_blend_state {
        uint32_t cb_color_control;
        uint32_t cb_target_mask;
-       uint32_t sx_mrt0_blend_opt[8];
+       uint32_t sx_mrt_blend_opt[8];
        uint32_t cb_blend_control[8];
 
        uint32_t spi_shader_col_format;