diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 1c9adb7f74b..599a0183c47 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -296,6 +296,20 @@ lower_drawid(nir_shader *shader) return nir_shader_instructions_pass(shader, lower_drawid_instr, nir_metadata_dominance, NULL); } +static bool +lower_dual_blend(nir_shader *shader) +{ + bool progress = false; + nir_variable *var = nir_find_variable_with_location(shader, nir_var_shader_out, FRAG_RESULT_DATA1); + if (var) { + var->data.location = FRAG_RESULT_DATA0; + var->data.index = 1; + progress = true; + } + nir_shader_preserve_all_metadata(shader); + return progress; +} + void zink_screen_init_compiler(struct zink_screen *screen) { @@ -450,6 +464,11 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, struct z NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL); optimize_nir(nir); } + if (zink_fs_key(key)->force_dual_color_blend && nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA1)) { + if (nir == zs->nir) + nir = nir_shader_clone(NULL, zs->nir); + NIR_PASS_V(nir, lower_dual_blend); + } } struct spirv_shader *spirv = nir_to_spirv(nir, streamout, shader_slot_map, shader_slots_reserved); assert(spirv); diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index f89901a6ded..24cc0daf76f 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -231,6 +231,7 @@ static void shader_key_fs_gen(struct zink_context *ctx, struct zink_shader *zs, struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key) { + struct zink_screen *screen = zink_screen(ctx->base.screen); struct zink_fs_key *fs_key = &key->key.fs; key->size = sizeof(struct zink_fs_key); @@ -243,6 +244,9 @@ shader_key_fs_gen(struct zink_context *ctx, struct zink_shader *zs, */ if (zs->nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK)) fs_key->samples = !!ctx->fb_state.samples; + fs_key->force_dual_color_blend = screen->driconf.dual_color_blend_by_location && + ctx->gfx_pipeline_state.blend_state->dual_src_blend && + ctx->gfx_pipeline_state.blend_state->attachments[1].blendEnable; } static void diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 52c377a06ba..f85ba1c9ed8 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -40,6 +40,7 @@ #include "util/u_screen.h" #include "util/u_string.h" #include "util/u_transfer_helper.h" +#include "util/xmlconfig.h" #include "frontend/sw_winsys.h" @@ -1283,6 +1284,9 @@ zink_internal_create_screen(const struct pipe_screen_config *config) slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16); + if (config) + screen->driconf.dual_color_blend_by_location = driQueryOptionb(config->options, "dual_color_blend_by_location"); + return screen; fail: diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index 3a4c9d93fb3..9ff6c55051a 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -115,6 +115,10 @@ struct zink_screen { PFN_vkUseIOSurfaceMVK vk_UseIOSurfaceMVK; PFN_vkGetIOSurfaceMVK vk_GetIOSurfaceMVK; #endif + + struct { + bool dual_color_blend_by_location; + } driconf; }; static inline struct zink_screen * diff --git a/src/gallium/drivers/zink/zink_shader_keys.h b/src/gallium/drivers/zink/zink_shader_keys.h index d773b690538..a9e396704e8 100644 --- a/src/gallium/drivers/zink/zink_shader_keys.h +++ b/src/gallium/drivers/zink/zink_shader_keys.h @@ -37,6 +37,7 @@ struct zink_fs_key { unsigned shader_id; //bool flat_shade; bool samples; + bool force_dual_color_blend; }; struct zink_tcs_key { diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 514d79102bb..3e19114d0e9 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -26,6 +26,8 @@ #include "zink_context.h" #include "zink_screen.h" +#include "compiler/shader_enums.h" +#include "util/u_dual_blend.h" #include "util/u_memory.h" #include @@ -275,6 +277,7 @@ zink_create_blend_state(struct pipe_context *pctx, cso->attachments[i] = att; } + cso->dual_src_blend = util_blend_state_is_dual(blend_state, 0); return cso; } diff --git a/src/gallium/drivers/zink/zink_state.h b/src/gallium/drivers/zink/zink_state.h index caa8194cbe3..e49c133c843 100644 --- a/src/gallium/drivers/zink/zink_state.h +++ b/src/gallium/drivers/zink/zink_state.h @@ -70,6 +70,7 @@ struct zink_blend_state { VkBool32 alpha_to_one; bool need_blend_constants; + bool dual_src_blend; }; struct zink_depth_stencil_alpha_hw_state {