diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/amd/vulkan/radv_cmd_buffer.c | 4 | ||||
-rw-r--r-- | src/amd/vulkan/radv_pipeline.c | 131 | ||||
-rw-r--r-- | 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; |