diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h index 8e8a1cfd5f7..64ccc949185 100644 --- a/src/freedreno/ir3/ir3_shader.h +++ b/src/freedreno/ir3/ir3_shader.h @@ -618,6 +618,7 @@ struct ir3_shader_output { uint8_t slot; uint8_t regid; uint8_t view; + uint8_t aliased_components : 4; bool half : 1; }; diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc index 5ec17133979..d52e53c83dc 100644 --- a/src/freedreno/vulkan/tu_shader.cc +++ b/src/freedreno/vulkan/tu_shader.cc @@ -1821,12 +1821,30 @@ tu6_emit_fs_outputs(struct tu_cs *cs, int output_reg_count = 0; uint32_t fragdata_regid[8]; + uint32_t fragdata_aliased_components = 0; assert(!fs->color0_mrt); for (uint32_t i = 0; i < ARRAY_SIZE(fragdata_regid); i++) { - fragdata_regid[i] = ir3_find_output_regid(fs, FRAG_RESULT_DATA0 + i); - if (VALIDREG(fragdata_regid[i])) + int output_idx = + ir3_find_output(fs, (gl_varying_slot) (FRAG_RESULT_DATA0 + i)); + + if (output_idx < 0) { + fragdata_regid[i] = INVALID_REG; + continue; + } + + const struct ir3_shader_output *fragdata = &fs->outputs[output_idx]; + fragdata_regid[i] = ir3_get_output_regid(fragdata); + + if (VALIDREG(fragdata_regid[i]) || fragdata->aliased_components) { + /* An invalid reg is only allowed if all components are aliased. */ + assert(VALIDREG(fragdata_regid[i] || + fragdata->aliased_components == 0xf)); + output_reg_count = i + 1; + fragdata_aliased_components |= fragdata->aliased_components + << (i * 4); + } } tu_cs_emit_pkt4(cs, REG_A6XX_SP_FS_OUTPUT_CNTL0, 1); @@ -1847,7 +1865,8 @@ tu6_emit_fs_outputs(struct tu_cs *cs, (COND(fragdata_regid[i] & HALF_REG_ID, A6XX_SP_FS_OUTPUT_REG_HALF_PRECISION))); - if (VALIDREG(fragdata_regid[i])) { + if (VALIDREG(fragdata_regid[i]) || + (fragdata_aliased_components & (0xf << (i * 4)))) { fs_render_components |= 0xf << (i * 4); } } @@ -1855,6 +1874,16 @@ tu6_emit_fs_outputs(struct tu_cs *cs, tu_cs_emit_regs(cs, A6XX_SP_FS_RENDER_COMPONENTS(.dword = fs_render_components)); + if (CHIP >= A7XX) { + tu_cs_emit_regs( + cs, + A7XX_SP_PS_ALIASED_COMPONENTS_CONTROL( + .enabled = fragdata_aliased_components != 0), + A7XX_SP_PS_ALIASED_COMPONENTS(.dword = fragdata_aliased_components)); + } else { + assert(fragdata_aliased_components == 0); + } + tu_cs_emit_pkt4(cs, REG_A6XX_RB_FS_OUTPUT_CNTL0, 1); tu_cs_emit(cs, COND(fs->writes_pos, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_Z) | COND(fs->writes_smask, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK) |