From d82826ad44465423407d1e4413d7d66bee82737c Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Sun, 4 Oct 2020 09:15:36 -0500 Subject: [PATCH] anv: Implement VK_EXT_transform_feedback on Gen7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Things work a little different on Gen7 than they do on Gen8+. In particular, SOBufferEnable lives in 3DSTATE_STREAMOUT but BufferPitch lives in 3DSTATE_SO_BUFFER. This leaves us having to marshal data around a bit more than we did on Gen8. Still, it's not too bad. Normally, I don't spend much time on Gen7 but XFB just became a hard requirement for DXVK so it stopped working for all our Haswell users. Let's get them happily playing their games again. 😸 Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3532 Reviewed-by: Lionel Landwerlin Part-of: --- src/intel/vulkan/anv_device.c | 4 +++- src/intel/vulkan/anv_extensions.py | 2 +- src/intel/vulkan/anv_private.h | 1 + src/intel/vulkan/genX_cmd_buffer.c | 20 +++++++++++++++----- src/intel/vulkan/genX_pipeline.c | 24 ++++++++++++++++++------ 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 4df2dd690ce..2b30f4c1177 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -2126,7 +2126,9 @@ void anv_GetPhysicalDeviceProperties2( props->transformFeedbackQueries = true; props->transformFeedbackStreamsLinesTriangles = false; props->transformFeedbackRasterizationStreamSelect = false; - props->transformFeedbackDraw = true; + /* This requires MI_MATH */ + props->transformFeedbackDraw = pdevice->info.is_haswell || + pdevice->info.gen >= 8; break; } diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index 445e6cb166d..1617e2e3665 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -163,7 +163,7 @@ EXTENSIONS = [ Extension('VK_EXT_shader_viewport_index_layer', 1, True), Extension('VK_EXT_subgroup_size_control', 2, True), Extension('VK_EXT_texel_buffer_alignment', 1, True), - Extension('VK_EXT_transform_feedback', 1, 'device->info.gen >= 8'), + Extension('VK_EXT_transform_feedback', 1, True), Extension('VK_EXT_vertex_attribute_divisor', 3, True), Extension('VK_EXT_ycbcr_image_arrays', 1, True), Extension('VK_ANDROID_external_memory_android_hardware_buffer', 3, 'ANDROID'), diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index f24b6929b49..2935bef4bc2 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -3471,6 +3471,7 @@ struct anv_graphics_pipeline { uint32_t sf[7]; uint32_t depth_stencil_state[3]; uint32_t clip[4]; + uint32_t xfb_bo_pitch[4]; } gen7; struct { diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 0644f07ce0b..259e1759ce1 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -3424,8 +3424,9 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) cmd_buffer->state.gfx.vb_dirty &= ~vb_emit; -#if GEN_GEN >= 8 - if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_XFB_ENABLE) { + if ((cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_XFB_ENABLE) || + (GEN_GEN == 7 && (cmd_buffer->state.gfx.dirty & + ANV_CMD_DIRTY_PIPELINE))) { /* We don't need any per-buffer dirty tracking because you're not * allowed to bind different XFB buffers while XFB is enabled. */ @@ -3440,13 +3441,23 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) #endif if (cmd_buffer->state.xfb_enabled && xfb->buffer && xfb->size != 0) { - sob.SOBufferEnable = true; sob.MOCS = cmd_buffer->device->isl_dev.mocs.internal, - sob.StreamOffsetWriteEnable = false; sob.SurfaceBaseAddress = anv_address_add(xfb->buffer->address, xfb->offset); +#if GEN_GEN >= 8 + sob.SOBufferEnable = true; + sob.StreamOffsetWriteEnable = false; /* Size is in DWords - 1 */ sob.SurfaceSize = DIV_ROUND_UP(xfb->size, 4) - 1; +#else + /* We don't have SOBufferEnable in 3DSTATE_SO_BUFFER on Gen7 so + * we trust in SurfaceEndAddress = SurfaceBaseAddress = 0 (the + * default for an empty SO_BUFFER packet) to disable them. + */ + sob.SurfacePitch = pipeline->gen7.xfb_bo_pitch[idx]; + sob.SurfaceEndAddress = anv_address_add(xfb->buffer->address, + xfb->offset + xfb->size); +#endif } } } @@ -3455,7 +3466,6 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) if (GEN_GEN >= 10) cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_CS_STALL_BIT; } -#endif if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) { anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->base.batch); diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index d4b93688da1..205e8677f19 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -1370,7 +1370,6 @@ static void emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, const VkPipelineRasterizationStateCreateInfo *rs_info) { -#if GEN_GEN >= 8 const struct brw_vue_prog_data *prog_data = anv_pipeline_get_last_vue_prog_data(pipeline); const struct brw_vue_map *vue_map = &prog_data->vue_map; @@ -1382,12 +1381,10 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, xfb_info = pipeline->shaders[MESA_SHADER_TESS_EVAL]->xfb_info; else xfb_info = pipeline->shaders[MESA_SHADER_VERTEX]->xfb_info; -#endif anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_STREAMOUT), so) { so.RenderingDisable = rs_info->rasterizerDiscardEnable; -#if GEN_GEN >= 8 if (xfb_info) { so.SOFunctionEnable = true; so.SOStatisticsEnable = true; @@ -1397,10 +1394,28 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, so.RenderStreamSelect = stream_info ? stream_info->rasterizationStream : 0; +#if GEN_GEN >= 8 so.Buffer0SurfacePitch = xfb_info->buffers[0].stride; so.Buffer1SurfacePitch = xfb_info->buffers[1].stride; so.Buffer2SurfacePitch = xfb_info->buffers[2].stride; so.Buffer3SurfacePitch = xfb_info->buffers[3].stride; +#else + pipeline->gen7.xfb_bo_pitch[0] = xfb_info->buffers[0].stride; + pipeline->gen7.xfb_bo_pitch[1] = xfb_info->buffers[1].stride; + pipeline->gen7.xfb_bo_pitch[2] = xfb_info->buffers[2].stride; + pipeline->gen7.xfb_bo_pitch[3] = xfb_info->buffers[3].stride; + + /* On Gen7, the SO buffer enables live in 3DSTATE_STREAMOUT which + * is a bit inconvenient because we don't know what buffers will + * actually be enabled until draw time. We do our best here by + * setting them based on buffers_written and we disable them + * as-needed at draw time by setting EndAddress = BaseAddress. + */ + so.SOBufferEnable0 = xfb_info->buffers_written & (1 << 0); + so.SOBufferEnable1 = xfb_info->buffers_written & (1 << 1); + so.SOBufferEnable2 = xfb_info->buffers_written & (1 << 2); + so.SOBufferEnable3 = xfb_info->buffers_written & (1 << 3); +#endif int urb_entry_read_offset = 0; int urb_entry_read_length = @@ -1419,10 +1434,8 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, so.Stream3VertexReadOffset = urb_entry_read_offset; so.Stream3VertexReadLength = urb_entry_read_length - 1; } -#endif /* GEN_GEN >= 8 */ } -#if GEN_GEN >= 8 if (xfb_info) { struct GENX(SO_DECL) so_decl[MAX_XFB_STREAMS][128]; int next_offset[MAX_XFB_BUFFERS] = {0, 0, 0, 0}; @@ -1521,7 +1534,6 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, }); } } -#endif /* GEN_GEN >= 8 */ } static uint32_t