radv: add support for compiling PS epilogs on-demand

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20201>
This commit is contained in:
Samuel Pitoiset
2022-12-06 16:00:29 +01:00
committed by Marge Bot
parent 11469f7553
commit eb07a11b8f
4 changed files with 116 additions and 17 deletions

View File

@@ -4099,6 +4099,68 @@ radv_cmp_ps_epilog(const void *a_, const void *b_)
return memcmp(a, b, sizeof(*a)) == 0;
}
static struct radv_shader_part *
lookup_ps_epilog(struct radv_cmd_buffer *cmd_buffer)
{
const struct radv_graphics_pipeline *pipeline = cmd_buffer->state.graphics_pipeline;
const struct radv_rendering_state *render = &cmd_buffer->state.render;
const struct radv_dynamic_state *d = &cmd_buffer->state.dynamic;
struct radv_device *device = cmd_buffer->device;
struct radv_shader_part *epilog = NULL;
struct radv_ps_epilog_state state = {0};
state.color_attachment_count = render->color_att_count;
for (unsigned i = 0; i < render->color_att_count; ++i) {
state.color_attachment_formats[i] = render->color_att[i].format;
}
for (unsigned i = 0; i < MAX_RTS; i++) {
state.color_write_mask |= d->vk.cb.attachments[i].write_mask << (4 * i);
state.color_blend_enable |= d->vk.cb.attachments[i].blend_enable << (4 * i);
}
state.mrt0_is_dual_src = pipeline->mrt0_is_dual_src;
state.need_src_alpha = pipeline->need_src_alpha;
if (d->vk.ms.alpha_to_coverage_enable) {
/* Select a color export format with alpha when alpha to coverage is enabled. */
state.need_src_alpha |= 0x1;
}
struct radv_ps_epilog_key key = radv_generate_ps_epilog_key(pipeline, &state, true);
uint32_t hash = radv_hash_ps_epilog(&key);
u_rwlock_rdlock(&device->ps_epilogs_lock);
struct hash_entry *epilog_entry =
_mesa_hash_table_search_pre_hashed(device->ps_epilogs, hash, &key);
u_rwlock_rdunlock(&device->ps_epilogs_lock);
if (!epilog_entry) {
u_rwlock_wrlock(&device->ps_epilogs_lock);
epilog_entry = _mesa_hash_table_search_pre_hashed(device->ps_epilogs, hash, &key);
if (epilog_entry) {
u_rwlock_wrunlock(&device->ps_epilogs_lock);
return epilog_entry->data;
}
epilog = radv_create_ps_epilog(device, &key);
struct radv_ps_epilog_key *key2 = malloc(sizeof(*key2));
if (!epilog || !key2) {
radv_shader_part_unref(device, epilog);
free(key2);
u_rwlock_wrunlock(&device->ps_epilogs_lock);
return NULL;
}
memcpy(key2, &key, sizeof(*key2));
_mesa_hash_table_insert_pre_hashed(device->ps_epilogs, hash, key2, epilog);
u_rwlock_wrunlock(&device->ps_epilogs_lock);
return epilog;
}
return epilog_entry->data;
}
static void
radv_emit_msaa_state(struct radv_cmd_buffer *cmd_buffer)
{
@@ -8457,9 +8519,28 @@ radv_emit_all_graphics_states(struct radv_cmd_buffer *cmd_buffer, const struct r
const struct radv_device *device = cmd_buffer->device;
bool late_scissor_emission;
if (cmd_buffer->state.graphics_pipeline->ps_epilog)
radv_emit_ps_epilog_state(cmd_buffer, cmd_buffer->state.graphics_pipeline->ps_epilog,
pipeline_is_dirty);
if (cmd_buffer->state.graphics_pipeline->base.shaders[MESA_SHADER_FRAGMENT]->info.ps.has_epilog) {
struct radv_shader_part *ps_epilog = NULL;
if (cmd_buffer->state.graphics_pipeline->ps_epilog) {
ps_epilog = cmd_buffer->state.graphics_pipeline->ps_epilog;
} else if ((cmd_buffer->state.emitted_graphics_pipeline != cmd_buffer->state.graphics_pipeline ||
(cmd_buffer->state.dirty & (RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_MASK |
RADV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_ENABLE |
RADV_CMD_DIRTY_DYNAMIC_ALPHA_TO_COVERAGE_ENABLE)))) {
ps_epilog = lookup_ps_epilog(cmd_buffer);
if (!ps_epilog) {
vk_command_buffer_set_error(&cmd_buffer->vk, VK_ERROR_OUT_OF_HOST_MEMORY);
return;
}
cmd_buffer->state.col_format_non_compacted = ps_epilog->spi_shader_col_format;
cmd_buffer->state.dirty |= RADV_CMD_DIRTY_RBPLUS;
}
if (ps_epilog)
radv_emit_ps_epilog_state(cmd_buffer, ps_epilog, pipeline_is_dirty);
}
if (cmd_buffer->state.dirty & RADV_CMD_DIRTY_RBPLUS)
radv_emit_rbplus_state(cmd_buffer);

View File

@@ -2305,6 +2305,15 @@ radv_graphics_pipeline_link(const struct radv_pipeline *pipeline,
}
}
static bool
radv_pipeline_has_dynamic_ps_epilog(const struct radv_graphics_pipeline *pipeline)
{
/* These dynamic states need to compile PS epilogs on-demand. */
return pipeline->dynamic_states & (RADV_DYNAMIC_COLOR_BLEND_ENABLE |
RADV_DYNAMIC_COLOR_WRITE_MASK |
RADV_DYNAMIC_ALPHA_TO_COVERAGE_ENABLE);
}
struct radv_pipeline_key
radv_generate_pipeline_key(const struct radv_pipeline *pipeline, VkPipelineCreateFlags flags)
{
@@ -2327,19 +2336,7 @@ radv_generate_pipeline_key(const struct radv_pipeline *pipeline, VkPipelineCreat
return key;
}
struct radv_ps_epilog_state
{
uint8_t color_attachment_count;
VkFormat color_attachment_formats[MAX_RTS];
uint32_t color_write_mask;
uint32_t color_blend_enable;
bool mrt0_is_dual_src;
uint8_t need_src_alpha;
};
static struct radv_ps_epilog_key
struct radv_ps_epilog_key
radv_generate_ps_epilog_key(const struct radv_graphics_pipeline *pipeline,
const struct radv_ps_epilog_state *state,
bool disable_mrt_compaction)
@@ -2404,6 +2401,7 @@ radv_generate_ps_epilog_key(const struct radv_graphics_pipeline *pipeline,
key.color_is_int10 = device->physical_device->rad_info.gfx_level < GFX8 ? is_int10 : 0;
key.enable_mrt_output_nan_fixup = device->instance->enable_mrt_output_nan_fixup ? is_float32 : 0;
key.mrt0_is_dual_src = state->mrt0_is_dual_src;
key.need_src_alpha = state->need_src_alpha;
return key;
}
@@ -3920,7 +3918,7 @@ radv_pipeline_emit_blend_state(struct radeon_cmdbuf *ctx_cs,
const struct radv_graphics_pipeline *pipeline,
const struct radv_blend_state *blend)
{
if (pipeline->ps_epilog)
if (pipeline->ps_epilog || radv_pipeline_has_dynamic_ps_epilog(pipeline))
return;
radeon_set_context_reg(ctx_cs, R_028714_SPI_SHADER_COL_FORMAT, blend->spi_shader_col_format);
@@ -5189,6 +5187,7 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline *pipeline, struct radv
pipeline->col_format_non_compacted = blend.spi_shader_col_format;
pipeline->mrt0_is_dual_src = key.ps.epilog.mrt0_is_dual_src;
pipeline->need_src_alpha = key.ps.epilog.need_src_alpha;
struct radv_shader *ps = pipeline->base.shaders[MESA_SHADER_FRAGMENT];
bool enable_mrt_compaction = !key.ps.epilog.mrt0_is_dual_src && !ps->info.ps.has_epilog;

View File

@@ -1712,6 +1712,22 @@ bool radv_cmp_vs_prolog(const void *a_, const void *b_);
uint32_t radv_hash_ps_epilog(const void *key_);
bool radv_cmp_ps_epilog(const void *a_, const void *b_);
struct radv_ps_epilog_state
{
uint8_t color_attachment_count;
VkFormat color_attachment_formats[MAX_RTS];
uint32_t color_write_mask;
uint32_t color_blend_enable;
bool mrt0_is_dual_src;
uint8_t need_src_alpha;
};
struct radv_ps_epilog_key radv_generate_ps_epilog_key(const struct radv_graphics_pipeline *pipeline,
const struct radv_ps_epilog_state *state,
bool disable_mrt_compaction);
void radv_cmd_buffer_reset_rendering(struct radv_cmd_buffer *cmd_buffer);
bool radv_cmd_buffer_upload_alloc(struct radv_cmd_buffer *cmd_buffer, unsigned size,
unsigned *out_offset, void **ptr);
@@ -2044,6 +2060,7 @@ struct radv_graphics_pipeline {
uint32_t col_format_non_compacted;
bool mrt0_is_dual_src;
uint8_t need_src_alpha;
bool uses_drawid;
bool uses_baseinstance;

View File

@@ -61,6 +61,8 @@ struct radv_ps_epilog_key {
uint8_t enable_mrt_output_nan_fixup;
bool mrt0_is_dual_src;
uint8_t need_src_alpha; /* XXX: Remove this when color blend equations are dynamic! */
};
struct radv_pipeline_key {