From ff3c3792b4f0d66af50c36b9d03373b1de5c9740 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Mon, 1 Jul 2024 16:16:33 -0700 Subject: [PATCH] anv/gfx12.5: Pass non-empty push constant data to PS stage for TBIMR workaround. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10728 Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11399 Fixes: 57decad9768a445 ("intel/xehp: Enable TBIMR by default.") Reviewed-by: Lionel Landwerlin Part-of: --- src/intel/vulkan/anv_pipeline.c | 3 +++ src/intel/vulkan/genX_cmd_draw.c | 44 +++++++++++++++++++++++++++++--- src/intel/vulkan/genX_pipeline.c | 6 +++-- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 42206ded7eb..0209e407c01 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -619,6 +619,9 @@ populate_wm_prog_key(struct anv_pipeline_stage *stage, key->coarse_pixel = device->vk.enabled_extensions.KHR_fragment_shading_rate && pipeline_has_coarse_pixel(dynamic, ms, fsr); + + key->null_push_constant_tbimr_workaround = + device->info->needs_null_push_constant_tbimr_workaround; } static void diff --git a/src/intel/vulkan/genX_cmd_draw.c b/src/intel/vulkan/genX_cmd_draw.c index 0e70f405418..9cd51af5c20 100644 --- a/src/intel/vulkan/genX_cmd_draw.c +++ b/src/intel/vulkan/genX_cmd_draw.c @@ -380,6 +380,35 @@ cmd_buffer_emit_push_constant(struct anv_cmd_buffer *cmd_buffer, } #if GFX_VER >= 12 +static void +emit_null_push_constant_tbimr_workaround(struct anv_cmd_buffer *cmd_buffer) +{ + /* Pass a single-register push constant payload for the PS + * stage even if empty, since PS invocations with zero push + * constant cycles have been found to cause hangs with TBIMR + * enabled. See HSDES #22020184996. + * + * XXX - Use workaround infrastructure and final workaround + * when provided by hardware team. + */ + const struct anv_address null_addr = { + .bo = cmd_buffer->device->workaround_bo, + .offset = 1024, + }; + uint32_t *dw = anv_batch_emitn( + &cmd_buffer->batch, 4, + GENX(3DSTATE_CONSTANT_ALL), + .ShaderUpdateEnable = (1 << MESA_SHADER_FRAGMENT), + .PointerBufferMask = 1, + .MOCS = isl_mocs(&cmd_buffer->device->isl_dev, 0, false)); + GENX(3DSTATE_CONSTANT_ALL_DATA_pack)( + &cmd_buffer->batch, dw + 2, + &(struct GENX(3DSTATE_CONSTANT_ALL_DATA)) { + .PointerToConstantBuffer = null_addr, + .ConstantBufferReadLength = 1, + }); +} + static void cmd_buffer_emit_push_constant_all(struct anv_cmd_buffer *cmd_buffer, uint32_t shader_mask, @@ -387,10 +416,19 @@ cmd_buffer_emit_push_constant_all(struct anv_cmd_buffer *cmd_buffer, uint32_t buffer_count) { if (buffer_count == 0) { - anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CONSTANT_ALL), c) { - c.ShaderUpdateEnable = shader_mask; - c.MOCS = isl_mocs(&cmd_buffer->device->isl_dev, 0, false); + if (cmd_buffer->device->info->needs_null_push_constant_tbimr_workaround && + (shader_mask & (1 << MESA_SHADER_FRAGMENT))) { + emit_null_push_constant_tbimr_workaround(cmd_buffer); + shader_mask &= ~(1 << MESA_SHADER_FRAGMENT); } + + if (shader_mask) { + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CONSTANT_ALL), c) { + c.ShaderUpdateEnable = shader_mask; + c.MOCS = isl_mocs(&cmd_buffer->device->isl_dev, 0, false); + } + } + return; } diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index 3f0926a2e56..33507d1a4d8 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -1704,8 +1704,10 @@ emit_3dstate_ps(struct anv_graphics_pipeline *pipeline, ps.SamplerCount = GFX_VER == 11 ? 0 : get_sampler_count(fs_bin); ps.BindingTableEntryCount = fs_bin->bind_map.surface_count; #if GFX_VER < 20 - ps.PushConstantEnable = wm_prog_data->base.nr_params > 0 || - wm_prog_data->base.ubo_ranges[0].length; + ps.PushConstantEnable = + devinfo->needs_null_push_constant_tbimr_workaround || + wm_prog_data->base.nr_params > 0 || + wm_prog_data->base.ubo_ranges[0].length; #endif ps.MaximumNumberofThreadsPerPSD = devinfo->max_threads_per_psd - 1;