radv: Fix a hang on CB change by adding flushes.

This workaround fixes a hang while loading a renderdoc trace for me.

Since the workload does 1 mip per cmdbuffer it is quite hard to confirm
what exactly the conditions for the hang are but this is the most
restrictive set I found and it corresponds to a workaround in AMDVLK as
well.

CC: mesa-stable
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7210>
This commit is contained in:
Bas Nieuwenhuizen 2020-10-19 02:53:39 +02:00 committed by Marge Bot
parent 8564715253
commit 4cce4d22a7
2 changed files with 76 additions and 0 deletions

View file

@ -2236,6 +2236,71 @@ radv_load_color_clear_metadata(struct radv_cmd_buffer *cmd_buffer,
}
}
/* GFX9+ metadata cache flushing workaround. metadata cache coherency is
* broken if the CB caches data of multiple mips of the same image at the
* same time.
*
* Insert some flushes to avoid this.
*/
static void
radv_emit_fb_mip_change_flush(struct radv_cmd_buffer *cmd_buffer)
{
struct radv_framebuffer *framebuffer = cmd_buffer->state.framebuffer;
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
bool color_mip_changed = false;
/* Entire workaround is not applicable before GFX9 */
if (cmd_buffer->device->physical_device->rad_info.chip_class < GFX9)
return;
if (!framebuffer)
return;
for (int i = 0; i < subpass->color_count; ++i) {
int idx = subpass->color_attachments[i].attachment;
struct radv_image_view *iview = cmd_buffer->state.attachments[idx].iview;
if ((radv_image_has_CB_metadata(iview->image) ||
radv_image_has_dcc(iview->image)) &&
cmd_buffer->state.cb_mip[i] != iview->base_mip)
color_mip_changed = true;
cmd_buffer->state.cb_mip[i] = iview->base_mip;
}
if (color_mip_changed) {
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB |
RADV_CMD_FLAG_FLUSH_AND_INV_CB_META;
}
}
/* This function does the flushes for mip changes if the levels are not zero for
* all render targets. This way we can assume at the start of the next cmd_buffer
* that rendering to mip 0 doesn't need any flushes. As that is the most common
* case that saves some flushes. */
static void
radv_emit_mip_change_flush_default(struct radv_cmd_buffer *cmd_buffer)
{
/* Entire workaround is not applicable before GFX9 */
if (cmd_buffer->device->physical_device->rad_info.chip_class < GFX9)
return;
bool need_color_mip_flush = false;
for (unsigned i = 0; i < 8; ++i) {
if (cmd_buffer->state.cb_mip[i]) {
need_color_mip_flush = true;
break;
}
}
if (need_color_mip_flush) {
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB |
RADV_CMD_FLAG_FLUSH_AND_INV_CB_META;
}
memset(cmd_buffer->state.cb_mip, 0, sizeof(cmd_buffer->state.cb_mip));
}
static void
radv_emit_framebuffer_state(struct radv_cmd_buffer *cmd_buffer)
{
@ -4075,6 +4140,8 @@ VkResult radv_EndCommandBuffer(
{
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
radv_emit_mip_change_flush_default(cmd_buffer);
if (cmd_buffer->queue_family_index != RADV_QUEUE_TRANSFER) {
if (cmd_buffer->device->physical_device->rad_info.chip_class == GFX6)
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_PS_PARTIAL_FLUSH | RADV_CMD_FLAG_WB_L2;
@ -4655,6 +4722,8 @@ void radv_CmdExecuteCommands(
assert(commandBufferCount > 0);
radv_emit_mip_change_flush_default(primary);
/* Emit pending flushes on primary prior to executing secondary */
si_emit_cache_flush(primary);
@ -4687,6 +4756,7 @@ void radv_CmdExecuteCommands(
* has been recorded without a framebuffer, otherwise
* fast color/depth clears can't work.
*/
radv_emit_fb_mip_change_flush(primary);
radv_emit_framebuffer_state(primary);
}
@ -5294,6 +5364,10 @@ radv_draw(struct radv_cmd_buffer *cmd_buffer,
return;
}
/* Need to apply this workaround early as it can set flush flags. */
if (cmd_buffer->state.dirty & RADV_CMD_DIRTY_FRAMEBUFFER)
radv_emit_fb_mip_change_flush(cmd_buffer);
/* Use optimal packet order based on whether we need to sync the
* pipeline.
*/

View file

@ -1391,6 +1391,8 @@ struct radv_cmd_state {
uint32_t num_layout_transitions;
bool pending_sqtt_barrier_end;
enum rgp_flush_bits sqtt_flush_bits;
uint8_t cb_mip[MAX_RTS];
};
struct radv_cmd_pool {