diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index 77df27c2f03..77a558202b6 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -50,6 +50,7 @@ anv_cmd_state_init(struct anv_cmd_buffer *cmd_buffer) state->current_pipeline = UINT32_MAX; state->gfx.restart_index = UINT32_MAX; + state->gfx.object_preemption = true; state->gfx.dirty = 0; } diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h index 084671ae263..10a72fff399 100644 --- a/src/intel/vulkan/anv_genX.h +++ b/src/intel/vulkan/anv_genX.h @@ -192,3 +192,9 @@ genX(ray_tracing_pipeline_emit)(struct anv_ray_tracing_pipeline *pipeline); .KernelStartPointer = bin->kernel.offset, \ }; \ }) + +void +genX(batch_set_preemption)(struct anv_batch *batch, bool value); + +void +genX(cmd_buffer_set_preemption)(struct anv_cmd_buffer *cmd_buffer, bool value); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 10785e5c41a..e506caf93c8 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2569,6 +2569,8 @@ struct anv_cmd_graphics_state { uint32_t index_offset; struct vk_sample_locations_state sample_locations; + + bool object_preemption; }; enum anv_depth_reg_mode { @@ -3100,6 +3102,7 @@ struct anv_graphics_pipeline { bool kill_pixel; bool force_fragment_thread_dispatch; + bool uses_xfb; uint32_t vb_used; struct anv_pipeline_vertex_binding { diff --git a/src/intel/vulkan/genX_blorp_exec.c b/src/intel/vulkan/genX_blorp_exec.c index c6e86fec922..90c0a6125ff 100644 --- a/src/intel/vulkan/genX_blorp_exec.c +++ b/src/intel/vulkan/genX_blorp_exec.c @@ -370,6 +370,10 @@ genX(blorp_exec)(struct blorp_batch *batch, { struct anv_cmd_buffer *cmd_buffer = batch->driver_batch; + /* Turn on preemption if it was toggled off. */ + if (!cmd_buffer->state.gfx.object_preemption) + genX(cmd_buffer_set_preemption)(cmd_buffer, true); + if (!cmd_buffer->state.current_l3_config) { const struct intel_l3_config *cfg = intel_get_default_l3_config(cmd_buffer->device->info); diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index d4ac63f3d1c..de3e6f3c57a 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -3138,6 +3138,62 @@ cmd_buffer_emit_scissor(struct anv_cmd_buffer *cmd_buffer) } } +/* Set preemption on/off. */ +void +genX(batch_set_preemption)(struct anv_batch *batch, bool value) +{ +#if GFX_VERx10 >= 120 + anv_batch_write_reg(batch, GENX(CS_CHICKEN1), cc1) { + cc1.DisablePreemptionandHighPriorityPausingdueto3DPRIMITIVECommand = !value; + cc1.DisablePreemptionandHighPriorityPausingdueto3DPRIMITIVECommandMask = true; + } + + /* Wa_16013994831 - we need to insert CS_STALL and 250 noops. */ + anv_batch_emit(batch, GENX(PIPE_CONTROL), pipe) { + pipe.CommandStreamerStallEnable = true; + } + + for (unsigned i = 0; i < 250; i++) + anv_batch_emit(batch, GENX(MI_NOOP), noop); +#endif +} + +void +genX(cmd_buffer_set_preemption)(struct anv_cmd_buffer *cmd_buffer, bool value) +{ +#if GFX_VERx10 >= 120 + if (cmd_buffer->state.gfx.object_preemption == value) + return; + + genX(batch_set_preemption)(&cmd_buffer->batch, value); + cmd_buffer->state.gfx.object_preemption = value; +#endif +} + +static void +genX(streamout_prologue)(struct anv_cmd_buffer *cmd_buffer) +{ +#if GFX_VERx10 >= 120 + /* Wa_16013994831 - Disable preemption during streamout, enable back + * again if XFB not used by the current pipeline. + * + * Although this workaround applies to Gfx12+, we already disable object + * level preemption for another reason in genX_state.c so we can skip this + * for Gfx12. + */ + if (!intel_device_info_is_dg2(cmd_buffer->device->info)) + return; + + if (cmd_buffer->state.gfx.pipeline->uses_xfb) { + genX(cmd_buffer_set_preemption)(cmd_buffer, false); + return; + } + + if (!cmd_buffer->state.gfx.object_preemption) + genX(cmd_buffer_set_preemption)(cmd_buffer, true); +#endif +} + static void cmd_buffer_emit_streamout(struct anv_cmd_buffer *cmd_buffer) { @@ -3166,6 +3222,8 @@ cmd_buffer_emit_streamout(struct anv_cmd_buffer *cmd_buffer) unreachable("Invalid provoking vertex mode"); } + genX(streamout_prologue)(cmd_buffer); + GENX(3DSTATE_STREAMOUT_pack)(NULL, dwords, &so); anv_batch_emit_merge(&cmd_buffer->batch, dwords, pipeline->gfx8.streamout_state); } @@ -3627,6 +3685,12 @@ genX(EndCommandBuffer)( genX(cmd_buffer_flush_generated_draws)(cmd_buffer); #endif + /* Turn on object level preemption if it is disabled to have it in known + * state at the beginning of new command buffer. + */ + if (!cmd_buffer->state.gfx.object_preemption) + genX(cmd_buffer_set_preemption)(cmd_buffer, true); + /* We want every command buffer to start with the PMA fix in a known state, * so we disable it at the end of the command buffer. */ @@ -3661,6 +3725,10 @@ genX(CmdExecuteCommands)( */ genX(cmd_buffer_enable_pma_fix)(primary, false); + /* Turn on preemption in case it was toggled off. */ + if (!primary->state.gfx.object_preemption) + genX(cmd_buffer_set_preemption)(primary, true); + /* 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 b43eeeb6539..15bc0dd2a2d 100644 --- a/src/intel/vulkan/genX_gpu_memcpy.c +++ b/src/intel/vulkan/genX_gpu_memcpy.c @@ -80,6 +80,10 @@ emit_common_so_memcpy(struct anv_batch *batch, struct anv_device *device, anv_batch_emit(batch, GENX(3DSTATE_MESH_CONTROL), mesh); anv_batch_emit(batch, GENX(3DSTATE_TASK_CONTROL), task); } + + /* Wa_16013994831 - Disable preemption during streamout. */ + if (intel_device_info_is_dg2(device->info)) + genX(batch_set_preemption)(batch, false); #endif anv_batch_emit(batch, GENX(3DSTATE_SBE), sbe) { @@ -259,6 +263,9 @@ genX(emit_so_memcpy_fini)(struct anv_memcpy_state *state) if ((state->batch->next - state->batch->start) & 4) anv_batch_emit(state->batch, GENX(MI_NOOP), noop); + + if (intel_device_info_is_dg2(state->device->info)) + genX(batch_set_preemption)(state->batch, true); } void diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index 62e4acdc929..132dd9f8cbf 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -1115,6 +1115,8 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, }; if (xfb_info) { + pipeline->uses_xfb = true; + so.SOFunctionEnable = true; so.SOStatisticsEnable = true;