aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/amd/vulkan/radv_cmd_buffer.c4
-rw-r--r--src/amd/vulkan/radv_pipeline.c131
-rw-r--r--src/amd/vulkan/radv_private.h2
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;