diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h index 1dfbf3c2989..4aad150bb00 100644 --- a/src/intel/vulkan/anv_genX.h +++ b/src/intel/vulkan/anv_genX.h @@ -83,6 +83,8 @@ void genX(flush_pipeline_select_3d)(struct anv_cmd_buffer *cmd_buffer); void genX(flush_pipeline_select_gpgpu)(struct anv_cmd_buffer *cmd_buffer); void genX(emit_pipeline_select)(struct anv_batch *batch, uint32_t pipeline); +void genX(apply_task_urb_workaround)(struct anv_cmd_buffer *cmd_buffer); + enum anv_pipe_bits genX(emit_apply_pipe_flushes)(struct anv_batch *batch, struct anv_device *device, diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 4250bf219f7..023ba6df44c 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2571,6 +2571,7 @@ struct anv_cmd_graphics_state { VkShaderStageFlags push_constant_stages; uint32_t primitive_topology; + bool used_task_shader; struct anv_buffer *index_buffer; uint32_t index_type; /**< 3DSTATE_INDEX_BUFFER.IndexFormat */ diff --git a/src/intel/vulkan/genX_blorp_exec.c b/src/intel/vulkan/genX_blorp_exec.c index 90c0a6125ff..006dd1469a0 100644 --- a/src/intel/vulkan/genX_blorp_exec.c +++ b/src/intel/vulkan/genX_blorp_exec.c @@ -294,6 +294,9 @@ blorp_exec_on_render(struct blorp_batch *batch, genX(flush_pipeline_select_3d)(cmd_buffer); + /* Wa_14015814527 */ + genX(apply_task_urb_workaround)(cmd_buffer); + /* Apply any outstanding flushes in case pipeline select haven't. */ genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer); diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 5753bca7992..f28f31cdf75 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -3244,6 +3244,19 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer) genX(flush_pipeline_select_3d)(cmd_buffer); + /* Wa_14015814527 + * + * Apply task URB workaround when switching from task to primitive. + */ + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) { + if (anv_pipeline_is_primitive(pipeline)) { + genX(apply_task_urb_workaround)(cmd_buffer); + } else if (anv_pipeline_has_stage(cmd_buffer->state.gfx.pipeline, + MESA_SHADER_TASK)) { + cmd_buffer->state.gfx.used_task_shader = true; + } + } + /* Apply any pending pipeline flushes we may have. We want to apply them * now because, if any of those flushes are for things like push constants, * the GPU will read the state at weird times. @@ -3696,6 +3709,12 @@ genX(EndCommandBuffer)( */ genX(cmd_buffer_enable_pma_fix)(cmd_buffer, false); + /* Wa_14015814527 + * + * Apply task URB workaround in the end of primary or secondary cmd_buffer. + */ + genX(apply_task_urb_workaround)(cmd_buffer); + genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer); emit_isp_disable(cmd_buffer); @@ -3729,6 +3748,12 @@ genX(CmdExecuteCommands)( if (!primary->state.gfx.object_preemption) genX(cmd_buffer_set_preemption)(primary, true); + /* Wa_14015814527 + * + * Apply task URB workaround before secondary cmd buffers. + */ + genX(apply_task_urb_workaround)(primary); + /* The secondary command buffer doesn't know which textures etc. have been * flushed prior to their execution. Apply those flushes now. */ diff --git a/src/intel/vulkan/genX_gpu_memcpy.c b/src/intel/vulkan/genX_gpu_memcpy.c index 5108d9d9747..a41bd44a1d0 100644 --- a/src/intel/vulkan/genX_gpu_memcpy.c +++ b/src/intel/vulkan/genX_gpu_memcpy.c @@ -298,6 +298,10 @@ genX(cmd_buffer_so_memcpy)(struct anv_cmd_buffer *cmd_buffer, #if GFX_VER == 9 genX(cmd_buffer_set_binding_for_gfx8_vb_flush)(cmd_buffer, 32, src, size); #endif + + /* Wa_14015814527 */ + genX(apply_task_urb_workaround)(cmd_buffer); + genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer); genX(flush_pipeline_select_3d)(cmd_buffer); diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c index 21bff0c34b4..cb5f3dcc9a9 100644 --- a/src/intel/vulkan/genX_state.c +++ b/src/intel/vulkan/genX_state.c @@ -995,3 +995,44 @@ VkResult genX(CreateSampler)( return VK_SUCCESS; } + +/* Wa_14015814527 + * + * Check if task shader was utilized within cmd_buffer, if so + * commit empty URB states and null prim. + */ +void +genX(apply_task_urb_workaround)(struct anv_cmd_buffer *cmd_buffer) +{ +#if GFX_VERx10 != 125 + return; +#else + if (cmd_buffer->state.current_pipeline != _3D || + !cmd_buffer->state.gfx.used_task_shader) + return; + + cmd_buffer->state.gfx.used_task_shader = false; + + /* Wa_14015821291 mentions that WA below is not required if we have + * a pipeline flush going on. It will get flushed during + * cmd_buffer_flush_state before draw. + */ + if ((cmd_buffer->state.pending_pipe_bits & ANV_PIPE_CS_STALL_BIT)) + return; + + for (int i = 0; i <= MESA_SHADER_GEOMETRY; i++) { + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_URB_VS), urb) { + urb._3DCommandSubOpcode += i; + } + } + + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_URB_ALLOC_MESH), zero); + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_URB_ALLOC_TASK), zero); + + /* Issue 'nullprim' to commit the state. */ + anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) { + pc.PostSyncOperation = WriteImmediateData; + pc.Address = cmd_buffer->device->workaround_address; + } +#endif +}