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: