diff --git a/src/amd/vulkan/radv_instance.c b/src/amd/vulkan/radv_instance.c
index 31e06ca9d7d..7b07da3321c 100644
--- a/src/amd/vulkan/radv_instance.c
+++ b/src/amd/vulkan/radv_instance.c
@@ -150,6 +150,7 @@ static const driOptionDescription radv_dri_options[] = {
DRI_CONF_RADV_TEX_NON_UNIFORM(false)
DRI_CONF_RADV_FLUSH_BEFORE_TIMESTAMP_WRITE(false)
DRI_CONF_RADV_RT_WAVE64(false)
+ DRI_CONF_DUAL_COLOR_BLEND_BY_LOCATION(false)
DRI_CONF_RADV_APP_LAYER()
DRI_CONF_SECTION_END
};
@@ -206,6 +207,8 @@ radv_init_dri_options(struct radv_instance *instance)
driQueryOptionb(&instance->dri_options, "radv_flush_before_timestamp_write");
instance->force_rt_wave64 = driQueryOptionb(&instance->dri_options, "radv_rt_wave64");
+
+ instance->dual_color_blend_by_location = driQueryOptionb(&instance->dri_options, "dual_color_blend_by_location");
}
static const struct vk_instance_extension_table radv_instance_extensions_supported = {
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index ec5fd4dc23c..89bd9123ea7 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -260,6 +260,8 @@ radv_get_hash_flags(const struct radv_device *device, bool stats)
hash_flags |= RADV_HASH_SHADER_NGG_STREAMOUT;
if (device->instance->debug_flags & RADV_DEBUG_NO_RT)
hash_flags |= RADV_HASH_SHADER_NO_RT;
+ if (device->instance->dual_color_blend_by_location)
+ hash_flags |= RADV_HASH_SHADER_DUAL_BLEND_MRT1;
return hash_flags;
}
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 0cbf669ba59..f58b9ed045e 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -410,6 +410,7 @@ struct radv_instance {
bool tex_non_uniform;
bool flush_before_timestamp_write;
bool force_rt_wave64;
+ bool dual_color_blend_by_location;
char *app_layer;
};
@@ -2122,6 +2123,7 @@ struct radv_event {
#define RADV_HASH_SHADER_NO_FMASK (1 << 19)
#define RADV_HASH_SHADER_NGG_STREAMOUT (1 << 20)
#define RADV_HASH_SHADER_NO_RT (1 << 21)
+#define RADV_HASH_SHADER_DUAL_BLEND_MRT1 (1 << 22)
struct radv_pipeline_key;
struct radv_ray_tracing_group;
diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c
index 9c09299d4a5..1ef0f371458 100644
--- a/src/amd/vulkan/radv_shader.c
+++ b/src/amd/vulkan/radv_shader.c
@@ -325,6 +325,24 @@ is_not_xfb_output(nir_variable *var, void *data)
return !var->data.explicit_xfb_buffer && !var->data.explicit_xfb_stride;
}
+/* If the shader doesn't have an index=1 output, then assume that it meant for a location=1 to be used. This works on
+ * some older hardware because the MRT1 target is used for both location=1 and index=1, but GFX11 works differently.
+ */
+static void
+fix_dual_src_mrt1_export(nir_shader *nir)
+{
+ nir_foreach_shader_out_variable (var, nir) {
+ if (var->data.location == FRAG_RESULT_DATA0 && var->data.index == 1)
+ return;
+ }
+
+ nir_variable *loc1_var = nir_find_variable_with_location(nir, nir_var_shader_out, FRAG_RESULT_DATA1);
+ if (loc1_var) {
+ loc1_var->data.location = FRAG_RESULT_DATA0;
+ loc1_var->data.index = 1;
+ }
+}
+
nir_shader *
radv_shader_spirv_to_nir(struct radv_device *device, const struct radv_shader_stage *stage,
const struct radv_pipeline_key *key, bool is_internal)
@@ -510,6 +528,10 @@ radv_shader_spirv_to_nir(struct radv_device *device, const struct radv_shader_st
NIR_PASS(_, nir, nir_remove_dead_variables,
nir_var_shader_in | nir_var_shader_out | nir_var_system_value | nir_var_mem_shared, &dead_vars_opts);
+ if (nir->info.stage == MESA_SHADER_FRAGMENT && key->ps.epilog.mrt0_is_dual_src &&
+ device->instance->dual_color_blend_by_location)
+ fix_dual_src_mrt1_export(nir);
+
/* Variables can make nir_propagate_invariant more conservative
* than it needs to be.
*/
diff --git a/src/util/00-radv-defaults.conf b/src/util/00-radv-defaults.conf
index 904003462bf..9434dba1e3f 100644
--- a/src/util/00-radv-defaults.conf
+++ b/src/util/00-radv-defaults.conf
@@ -105,6 +105,7 @@ Application bugs worked around in this file:
+