panvk: Support color attachment remapping

We take the color attachment remapping into account when emitting
blend descriptors, and we make sure we re-emit those when this color
attachment map is dirty.

We also need to take the remapping into account when checking the
render targets written by the fragment shader, hence the addition of
a color_attachment_written_mask() helper.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32540>
This commit is contained in:
Boris Brezillon
2025-01-24 11:23:36 +01:00
committed by Marge Bot
parent 9d5d03bf78
commit 244995e4af
5 changed files with 74 additions and 20 deletions
+4 -5
View File
@@ -441,15 +441,13 @@ prepare_blend(struct panvk_cmd_buffer *cmdbuf)
dyn_gfx_state_dirty(cmdbuf, CB_BLEND_EQUATIONS) ||
dyn_gfx_state_dirty(cmdbuf, CB_WRITE_MASKS) ||
dyn_gfx_state_dirty(cmdbuf, CB_BLEND_CONSTANTS) ||
dyn_gfx_state_dirty(cmdbuf, COLOR_ATTACHMENT_MAP) ||
fs_user_dirty(cmdbuf) || gfx_state_dirty(cmdbuf, RENDER_STATE);
if (!dirty)
return VK_SUCCESS;
const struct vk_dynamic_graphics_state *dyns =
&cmdbuf->vk.dynamic_graphics_state;
const struct vk_color_blend_state *cb = &dyns->cb;
unsigned bd_count = MAX2(cb->attachment_count, 1);
uint32_t bd_count = MAX2(cmdbuf->state.gfx.render.fb.info.rt_count, 1);
struct cs_builder *b =
panvk_get_cs_builder(cmdbuf, PANVK_SUBQUEUE_VERTEX_TILER);
struct panfrost_ptr ptr =
@@ -1519,7 +1517,8 @@ prepare_dcd(struct panvk_cmd_buffer *cmdbuf)
struct mali_dcd_flags_0_packed dcd0;
pan_pack(&dcd0, DCD_FLAGS_0, cfg) {
if (fs) {
uint8_t rt_written = fs->info.outputs_written >> FRAG_RESULT_DATA0;
uint8_t rt_written = color_attachment_written_mask(
fs, &cmdbuf->vk.dynamic_graphics_state.cal);
uint8_t rt_mask = cmdbuf->state.gfx.render.bound_attachments &
MESA_VK_RP_ATTACHMENT_ANY_COLOR_BITS;
+4 -3
View File
@@ -196,6 +196,7 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf,
dyn_gfx_state_dirty(cmdbuf, CB_BLEND_EQUATIONS) ||
dyn_gfx_state_dirty(cmdbuf, CB_WRITE_MASKS) ||
dyn_gfx_state_dirty(cmdbuf, CB_BLEND_CONSTANTS) ||
dyn_gfx_state_dirty(cmdbuf, COLOR_ATTACHMENT_MAP) ||
dyn_gfx_state_dirty(cmdbuf, DS_DEPTH_TEST_ENABLE) ||
dyn_gfx_state_dirty(cmdbuf, DS_DEPTH_WRITE_ENABLE) ||
dyn_gfx_state_dirty(cmdbuf, DS_DEPTH_COMPARE_OP) ||
@@ -220,12 +221,11 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf,
const struct vk_dynamic_graphics_state *dyns =
&cmdbuf->vk.dynamic_graphics_state;
const struct vk_rasterization_state *rs = &dyns->rs;
const struct vk_color_blend_state *cb = &dyns->cb;
const struct vk_depth_stencil_state *ds = &dyns->ds;
const struct vk_input_assembly_state *ia = &dyns->ia;
const struct panvk_shader *fs = get_fs(cmdbuf);
const struct pan_shader_info *fs_info = fs ? &fs->info : NULL;
unsigned bd_count = MAX2(cb->attachment_count, 1);
uint32_t bd_count = MAX2(cmdbuf->state.gfx.render.fb.info.rt_count, 1);
bool test_s = has_stencil_att(cmdbuf) && ds->stencil.test_enable;
bool test_z = has_depth_att(cmdbuf) && ds->depth.test_enable;
bool writes_z = writes_depth(cmdbuf);
@@ -282,7 +282,8 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf,
8));
}
uint8_t rt_written = fs_info->outputs_written >> FRAG_RESULT_DATA0;
uint8_t rt_written = color_attachment_written_mask(
fs, &cmdbuf->vk.dynamic_graphics_state.cal);
uint8_t rt_mask = cmdbuf->state.gfx.render.bound_attachments &
MESA_VK_RP_ATTACHMENT_ANY_COLOR_BITS;
cfg.properties.allow_forward_pixel_to_kill =
+4
View File
@@ -8,7 +8,9 @@
#include <stdbool.h>
#include "util/bitscan.h"
#include "util/hash_table.h"
#include "util/macros.h"
#include "util/simple_mtx.h"
#include "pan_blend.h"
@@ -16,6 +18,8 @@
#include "panvk_macros.h"
#include "panvk_mempool.h"
#include "vk_graphics_state.h"
struct panvk_cmd_buffer;
#ifdef PAN_ARCH
+22
View File
@@ -354,4 +354,26 @@ void
panvk_per_arch(cmd_prepare_draw_sysvals)(struct panvk_cmd_buffer *cmdbuf,
const struct panvk_draw_info *info);
static inline uint32_t
color_attachment_written_mask(
const struct panvk_shader *fs,
const struct vk_color_attachment_location_state *cal)
{
uint32_t written_by_shader =
(fs->info.outputs_written >> FRAG_RESULT_DATA0) & BITFIELD_MASK(8);
uint32_t catt_written_mask = 0;
for (uint32_t i = 0; i < MAX_RTS; i++) {
if (cal->color_map[i] == MESA_VK_ATTACHMENT_UNUSED)
continue;
uint32_t shader_rt = cal->color_map[i];
if (written_by_shader & BITFIELD_BIT(shader_rt))
catt_written_mask |= BITFIELD_BIT(i);
}
return catt_written_mask;
}
#endif
+40 -12
View File
@@ -124,14 +124,15 @@ out:
static void
emit_blend_desc(const struct pan_shader_info *fs_info, uint64_t fs_code,
const struct pan_blend_state *state, unsigned rt_idx,
uint64_t blend_shader, uint16_t constant,
const struct pan_blend_state *state, unsigned blend_idx,
unsigned rt_idx, uint64_t blend_shader, uint16_t constant,
struct mali_blend_packed *bd)
{
const struct pan_blend_rt_state *rt = &state->rts[rt_idx];
const struct pan_blend_rt_state *rt =
rt_idx != MESA_VK_ATTACHMENT_UNUSED ? &state->rts[rt_idx] : NULL;
pan_pack(bd, BLEND, cfg) {
if (!state->rt_count || !rt->equation.color_mask) {
if (!state->rt_count || !rt || !rt->equation.color_mask) {
cfg.enable = false;
cfg.internal.mode = MALI_BLEND_MODE_OFF;
continue;
@@ -154,7 +155,7 @@ emit_blend_desc(const struct pan_shader_info *fs_info, uint64_t fs_code,
cfg.internal.shader.pc = (uint32_t)blend_shader;
#if PAN_ARCH <= 7
uint32_t ret_offset = fs_info->bifrost.blend[rt_idx].return_offset;
uint32_t ret_offset = fs_info->bifrost.blend[blend_idx].return_offset;
/* If ret_offset is zero, we assume the BLEND is a terminal
* instruction and set return_value to zero, to let the
@@ -195,13 +196,13 @@ emit_blend_desc(const struct pan_shader_info *fs_info, uint64_t fs_code,
#if PAN_ARCH <= 7
if (fs_info->fs.untyped_color_outputs) {
nir_alu_type type = fs_info->bifrost.blend[rt_idx].type;
nir_alu_type type = fs_info->bifrost.blend[blend_idx].type;
cfg.internal.fixed_function.conversion.register_format =
GENX(pan_fixup_blend_type)(type, rt->format);
} else {
cfg.internal.fixed_function.conversion.register_format =
fs_info->bifrost.blend[rt_idx].format;
fs_info->bifrost.blend[blend_idx].format;
}
if (!opaque) {
@@ -302,6 +303,7 @@ panvk_per_arch(blend_emit_descs)(struct panvk_cmd_buffer *cmdbuf,
const struct vk_dynamic_graphics_state *dyns =
&cmdbuf->vk.dynamic_graphics_state;
const struct vk_color_blend_state *cb = &dyns->cb;
const struct vk_color_attachment_location_state *cal = &dyns->cal;
const struct panvk_shader *fs = cmdbuf->state.gfx.fs.shader;
const struct pan_shader_info *fs_info = fs ? &fs->info : NULL;
uint64_t fs_code = panvk_shader_get_dev_addr(fs);
@@ -325,11 +327,33 @@ panvk_per_arch(blend_emit_descs)(struct panvk_cmd_buffer *cmdbuf,
uint64_t blend_shaders[8] = {};
/* All bits set to one encodes unused fixed-function blend constant. */
unsigned ff_blend_constant = ~0;
uint8_t remap_catts[MAX_RTS] = {
MESA_VK_ATTACHMENT_UNUSED, MESA_VK_ATTACHMENT_UNUSED,
MESA_VK_ATTACHMENT_UNUSED, MESA_VK_ATTACHMENT_UNUSED,
MESA_VK_ATTACHMENT_UNUSED, MESA_VK_ATTACHMENT_UNUSED,
MESA_VK_ATTACHMENT_UNUSED, MESA_VK_ATTACHMENT_UNUSED,
};
uint32_t blend_count = MAX2(cmdbuf->state.gfx.render.fb.info.rt_count, 1);
static_assert(ARRAY_SIZE(remap_catts) <= ARRAY_SIZE(cal->color_map),
"vk_color_attachment_location_state::color_map is too small");
for (uint32_t i = 0; i < ARRAY_SIZE(remap_catts); i++) {
if (cal->color_map[i] != MESA_VK_ATTACHMENT_UNUSED) {
assert(cal->color_map[i] < MAX_RTS);
remap_catts[cal->color_map[i]] = i;
}
}
memset(blend_info, 0, sizeof(*blend_info));
for (uint8_t i = 0; i < cb->attachment_count; i++) {
struct pan_blend_rt_state *rt = &bs.rts[i];
if (cal->color_map[i] == MESA_VK_ATTACHMENT_UNUSED) {
rt->equation.color_mask = 0;
continue;
}
if (!(cb->color_write_enables & BITFIELD_BIT(i))) {
rt->equation.color_mask = 0;
continue;
@@ -387,8 +411,8 @@ panvk_per_arch(blend_emit_descs)(struct panvk_cmd_buffer *cmdbuf,
nir_alu_type src0_type = fs_info->bifrost.blend[i].type;
nir_alu_type src1_type = fs_info->bifrost.blend_src1_type;
VkResult result = get_blend_shader(dev, &bs, src0_type, src1_type, i,
&blend_shaders[i]);
VkResult result = get_blend_shader(dev, &bs, src0_type, src1_type,
i, &blend_shaders[i]);
if (result != VK_SUCCESS)
return result;
@@ -403,9 +427,13 @@ panvk_per_arch(blend_emit_descs)(struct panvk_cmd_buffer *cmdbuf,
ff_blend_constant = 0;
/* Now that we've collected all the information, we can emit. */
for (uint8_t i = 0; i < MAX2(cb->attachment_count, 1); i++) {
emit_blend_desc(fs_info, fs_code, &bs, i, blend_shaders[i],
ff_blend_constant, &bds[i]);
for (uint8_t i = 0; i < blend_count; i++) {
uint32_t catt_idx = remap_catts[i];
uint64_t blend_shader =
catt_idx != MESA_VK_ATTACHMENT_UNUSED ? blend_shaders[catt_idx] : 0;
emit_blend_desc(fs_info, fs_code, &bs, i, catt_idx,
blend_shader, ff_blend_constant, &bds[i]);
}
if (blend_info->shader_loads_blend_const)