Mesa (master): anv: Implement VK_EXT_transform_feedback on Gen7

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Oct 5 22:41:17 UTC 2020


Module: Mesa
Branch: master
Commit: d82826ad44465423407d1e4413d7d66bee82737c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d82826ad44465423407d1e4413d7d66bee82737c

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Sun Oct  4 09:15:36 2020 -0500

anv: Implement VK_EXT_transform_feedback on Gen7

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 <lionel.g.landwerlin at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6997>

---

 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



More information about the mesa-commit mailing list