From 9c080100d336e4f90575d5138508b519ed334eef Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 21 Aug 2017 07:17:27 +0100 Subject: [PATCH] radv/gfx9: emit sx_mrt_blend registers 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 Cc: "17.2" Signed-off-by: Dave Airlie --- src/amd/vulkan/radv_cmd_buffer.c | 4 + src/amd/vulkan/radv_pipeline.c | 131 ++++++++++++++++++++++++++++++- src/amd/vulkan/radv_private.h | 2 +- 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index e45f6129872..ea17e330924 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -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 */ diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 75371a0be5a..23b9e72f92a 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -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 : diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index ca985da16d5..0d46cf6c960 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -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; -- 2.30.2