Mesa (main): anv: fix emitting dynamic primitive topology

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 23 12:25:34 UTC 2021


Module: Mesa
Branch: main
Commit: 55951ac28e7a30c2fae762990962a4410669c989
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=55951ac28e7a30c2fae762990962a4410669c989

Author: Tapani Pälli <tapani.palli at intel.com>
Date:   Tue Jun 15 09:55:51 2021 +0300

anv: fix emitting dynamic primitive topology

Initial implementation missed various fields that derive from the
primitive topology. This patch fixes 3DSTATE_RASTER/3DSTATE_SF,
3DSTATE_CLIP and 3DSTATE_WM (gen7.x) emission in the dynamic case.

Fixes: f6fa4a80000 ("anv: add support for dynamic primitive topology change")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4924
Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11379>

---

 src/intel/vulkan/anv_genX.h        |  14 +++
 src/intel/vulkan/anv_pipeline.c    |  43 ++++++++-
 src/intel/vulkan/anv_private.h     |  17 ++++
 src/intel/vulkan/genX_cmd_buffer.c |  19 ++++
 src/intel/vulkan/genX_pipeline.c   | 179 +++++++++++++++++++------------------
 src/intel/vulkan/gfx7_cmd_buffer.c |  87 +++++++++++++-----
 src/intel/vulkan/gfx8_cmd_buffer.c |  62 +++++++++----
 7 files changed, 295 insertions(+), 126 deletions(-)

diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h
index 3f7aa7eaba2..1a595029d2f 100644
--- a/src/intel/vulkan/anv_genX.h
+++ b/src/intel/vulkan/anv_genX.h
@@ -126,3 +126,17 @@ void genX(blorp_exec)(struct blorp_batch *batch,
 void genX(cmd_emit_timestamp)(struct anv_batch *batch,
                               struct anv_bo *bo,
                               uint32_t offset);
+
+void
+genX(rasterization_mode)(VkPolygonMode raster_mode,
+                         VkLineRasterizationModeEXT line_mode,
+                         uint32_t *api_mode,
+                         bool *msaa_rasterization_enable);
+
+uint32_t
+genX(ms_rasterization_mode)(struct anv_graphics_pipeline *pipeline,
+                            VkPolygonMode raster_mode);
+
+VkPolygonMode
+genX(raster_polygon_mode)(struct anv_graphics_pipeline *pipeline,
+                          VkPrimitiveTopology primitive_topology);
diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index 3eee533628f..2855e36cc17 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -2244,7 +2244,8 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
        ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
        ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE |
        ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE |
-       ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP);
+       ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP |
+       ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY);
 }
 
 static void
@@ -2321,6 +2322,25 @@ anv_pipeline_setup_l3_config(struct anv_pipeline *pipeline, bool needs_slm)
    pipeline->l3_config = intel_get_l3_config(devinfo, w);
 }
 
+static VkLineRasterizationModeEXT
+vk_line_rasterization_mode(const VkPipelineRasterizationLineStateCreateInfoEXT *line_info,
+                           const VkPipelineMultisampleStateCreateInfo *ms_info)
+{
+   VkLineRasterizationModeEXT line_mode =
+      line_info ? line_info->lineRasterizationMode :
+                  VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
+
+   if (line_mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT) {
+      if (ms_info && ms_info->rasterizationSamples > 1) {
+         return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
+      } else {
+         return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
+      }
+   }
+
+   return line_mode;
+}
+
 VkResult
 anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
                            struct anv_device *device,
@@ -2461,6 +2481,27 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
    else
       pipeline->topology = vk_to_intel_primitive_type[ia_info->topology];
 
+   /* If rasterization is not enabled, ms_info must be ignored. */
+   const bool raster_enabled =
+      !pCreateInfo->pRasterizationState->rasterizerDiscardEnable ||
+      (pipeline->dynamic_states &
+       ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
+
+   const VkPipelineMultisampleStateCreateInfo *ms_info =
+      raster_enabled ? pCreateInfo->pMultisampleState : NULL;
+
+   const VkPipelineRasterizationLineStateCreateInfoEXT *line_info =
+      vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
+                           PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
+
+   /* Store line mode, polygon mode and rasterization samples, these are used
+    * for dynamic primitive topology.
+    */
+   pipeline->line_mode = vk_line_rasterization_mode(line_info, ms_info);
+   pipeline->polygon_mode = pCreateInfo->pRasterizationState->polygonMode;
+   pipeline->rasterization_samples =
+      ms_info ? ms_info->rasterizationSamples : 1;
+
    return VK_SUCCESS;
 }
 
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index be2d7ff3cb7..4172b07439e 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -3529,6 +3529,13 @@ struct anv_graphics_pipeline {
 
    uint32_t                                     topology;
 
+   /* These fields are required with dynamic primitive topology,
+    * rasterization_samples used only with gen < 8.
+    */
+   VkLineRasterizationModeEXT                   line_mode;
+   VkPolygonMode                                polygon_mode;
+   uint32_t                                     rasterization_samples;
+
    struct anv_subpass *                         subpass;
 
    struct anv_shader_bin *                      shaders[MESA_SHADER_STAGES];
@@ -4441,6 +4448,16 @@ anv_sanitize_image_offset(const VkImageType imageType,
    }
 }
 
+static inline uint32_t
+anv_rasterization_aa_mode(VkPolygonMode raster_mode,
+                          VkLineRasterizationModeEXT line_mode)
+{
+   if (raster_mode == VK_POLYGON_MODE_LINE &&
+       line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT)
+      return true;
+   return false;
+}
+
 VkFormatFeatureFlags
 anv_get_image_format_features(const struct intel_device_info *devinfo,
                               VkFormat vk_format,
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index 5e2b5b37796..47aba611b1f 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -3468,12 +3468,30 @@ cmd_buffer_emit_clip(struct anv_cmd_buffer *cmd_buffer)
       ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE |
       ANV_CMD_DIRTY_DYNAMIC_CULL_MODE |
 #endif
+      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY |
       ANV_CMD_DIRTY_DYNAMIC_VIEWPORT |
       ANV_CMD_DIRTY_PIPELINE;
 
    if ((cmd_buffer->state.gfx.dirty & clip_states) == 0)
       return;
 
+   /* Take dynamic primitive topology in to account with
+    *    3DSTATE_CLIP::ViewportXYClipTestEnable
+    */
+   bool xy_clip_test_enable = 0;
+
+   if (cmd_buffer->state.gfx.pipeline->dynamic_states &
+       ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
+      VkPrimitiveTopology primitive_topology =
+         cmd_buffer->state.gfx.dynamic.primitive_topology;
+
+      VkPolygonMode dynamic_raster_mode =
+         genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
+                                   primitive_topology);
+
+      xy_clip_test_enable = (dynamic_raster_mode == VK_POLYGON_MODE_FILL);
+   }
+
 #if GFX_VER <= 7
    const struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic;
 #endif
@@ -3483,6 +3501,7 @@ cmd_buffer_emit_clip(struct anv_cmd_buffer *cmd_buffer)
       .FrontWinding = genX(vk_to_intel_front_face)[d->front_face],
       .CullMode     = genX(vk_to_intel_cullmode)[d->cull_mode],
 #endif
+      .ViewportXYClipTestEnable = xy_clip_test_enable,
    };
    uint32_t dwords[GENX(3DSTATE_CLIP_length)];
 
diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c
index e7d79de63e8..005782f467b 100644
--- a/src/intel/vulkan/genX_pipeline.c
+++ b/src/intel/vulkan/genX_pipeline.c
@@ -445,34 +445,14 @@ emit_3dstate_sbe(struct anv_graphics_pipeline *pipeline)
 #endif
 }
 
-static VkLineRasterizationModeEXT
-vk_line_rasterization_mode(const VkPipelineRasterizationLineStateCreateInfoEXT *line_info,
-                           const VkPipelineMultisampleStateCreateInfo *ms_info)
-{
-   VkLineRasterizationModeEXT line_mode =
-      line_info ? line_info->lineRasterizationMode :
-                  VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
-
-   if (line_mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT) {
-      if (ms_info && ms_info->rasterizationSamples > 1) {
-         return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
-      } else {
-         return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
-      }
-   }
-
-   return line_mode;
-}
-
 /** Returns the final polygon mode for rasterization
  *
  * This function takes into account polygon mode, primitive topology and the
  * different shader stages which might generate their own type of primitives.
  */
-static VkPolygonMode
-anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline,
-                        const VkPipelineInputAssemblyStateCreateInfo *ia_info,
-                        const VkPipelineRasterizationStateCreateInfo *rs_info)
+VkPolygonMode
+genX(raster_polygon_mode)(struct anv_graphics_pipeline *pipeline,
+                          VkPrimitiveTopology primitive_topology)
 {
    if (anv_pipeline_has_stage(pipeline, MESA_SHADER_GEOMETRY)) {
       switch (get_gs_prog_data(pipeline)->output_topology) {
@@ -491,7 +471,7 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline,
       case _3DPRIM_QUADLIST:
       case _3DPRIM_QUADSTRIP:
       case _3DPRIM_POLYGON:
-         return rs_info->polygonMode;
+         return pipeline->polygon_mode;
       }
       unreachable("Unsupported GS output topology");
    } else if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) {
@@ -504,11 +484,11 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline,
 
       case BRW_TESS_OUTPUT_TOPOLOGY_TRI_CW:
       case BRW_TESS_OUTPUT_TOPOLOGY_TRI_CCW:
-         return rs_info->polygonMode;
+         return pipeline->polygon_mode;
       }
       unreachable("Unsupported TCS output topology");
    } else {
-      switch (ia_info->topology) {
+      switch (primitive_topology) {
       case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
          return VK_POLYGON_MODE_POINT;
 
@@ -523,7 +503,7 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline,
       case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
       case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
       case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
-         return rs_info->polygonMode;
+         return pipeline->polygon_mode;
 
       default:
          unreachable("Unsupported primitive topology");
@@ -531,21 +511,13 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline,
    }
 }
 
-#if GFX_VER <= 7
-static uint32_t
-gfx7_ms_rast_mode(struct anv_graphics_pipeline *pipeline,
-                  const VkPipelineInputAssemblyStateCreateInfo *ia_info,
-                  const VkPipelineRasterizationStateCreateInfo *rs_info,
-                  const VkPipelineMultisampleStateCreateInfo *ms_info)
+uint32_t
+genX(ms_rasterization_mode)(struct anv_graphics_pipeline *pipeline,
+                            VkPolygonMode raster_mode)
 {
-   const VkPipelineRasterizationLineStateCreateInfoEXT *line_info =
-      vk_find_struct_const(rs_info->pNext,
-                           PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
-
-   VkPolygonMode raster_mode =
-      anv_raster_polygon_mode(pipeline, ia_info, rs_info);
+#if GFX_VER <= 7
    if (raster_mode == VK_POLYGON_MODE_LINE) {
-      switch (vk_line_rasterization_mode(line_info, ms_info)) {
+      switch (pipeline->line_mode) {
       case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
          return MSRASTMODE_ON_PATTERN;
 
@@ -557,11 +529,13 @@ gfx7_ms_rast_mode(struct anv_graphics_pipeline *pipeline,
          unreachable("Unsupported line rasterization mode");
       }
    } else {
-      return (ms_info && ms_info->rasterizationSamples > 1) ?
-             MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL;
+      return pipeline->rasterization_samples > 1 ?
+         MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL;
    }
-}
+#else
+   unreachable("Only on gen7");
 #endif
+}
 
 static VkProvokingVertexModeEXT
 vk_provoking_vertex_mode(const VkPipelineRasterizationStateCreateInfo *rs_info)
@@ -603,6 +577,49 @@ vk_conservative_rasterization_mode(const VkPipelineRasterizationStateCreateInfo
 }
 #endif
 
+void
+genX(rasterization_mode)(VkPolygonMode raster_mode,
+                         VkLineRasterizationModeEXT line_mode,
+                         uint32_t *api_mode,
+                         bool *msaa_rasterization_enable)
+{
+#if GFX_VER >= 8
+   if (raster_mode == VK_POLYGON_MODE_LINE) {
+      /* Unfortunately, configuring our line rasterization hardware on gfx8
+       * and later is rather painful.  Instead of giving us bits to tell the
+       * hardware what line mode to use like we had on gfx7, we now have an
+       * arcane combination of API Mode and MSAA enable bits which do things
+       * in a table which are expected to magically put the hardware into the
+       * right mode for your API.  Sadly, Vulkan isn't any of the APIs the
+       * hardware people thought of so nothing works the way you want it to.
+       *
+       * Look at the table titled "Multisample Rasterization Modes" in Vol 7
+       * of the Skylake PRM for more details.
+       */
+      switch (line_mode) {
+      case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
+         *api_mode = DX100;
+         *msaa_rasterization_enable = true;
+         break;
+
+      case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
+      case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
+         *api_mode = DX9OGL;
+         *msaa_rasterization_enable = false;
+         break;
+
+      default:
+         unreachable("Unsupported line rasterization mode");
+      }
+   } else {
+      *api_mode = DX100;
+      *msaa_rasterization_enable = true;
+   }
+#else
+   unreachable("Invalid call");
+#endif
+}
+
 static void
 emit_rs_state(struct anv_graphics_pipeline *pipeline,
               const VkPipelineInputAssemblyStateCreateInfo *ia_info,
@@ -667,45 +684,18 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
 #endif
 
    VkPolygonMode raster_mode =
-      anv_raster_polygon_mode(pipeline, ia_info, rs_info);
-   VkLineRasterizationModeEXT line_mode =
-      vk_line_rasterization_mode(line_info, ms_info);
+      genX(raster_polygon_mode)(pipeline, ia_info->topology);
+   bool dynamic_primitive_topology =
+      dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY;
 
    /* For details on 3DSTATE_RASTER multisample state, see the BSpec table
     * "Multisample Modes State".
     */
 #if GFX_VER >= 8
-   if (raster_mode == VK_POLYGON_MODE_LINE) {
-      /* Unfortunately, configuring our line rasterization hardware on gfx8
-       * and later is rather painful.  Instead of giving us bits to tell the
-       * hardware what line mode to use like we had on gfx7, we now have an
-       * arcane combination of API Mode and MSAA enable bits which do things
-       * in a table which are expected to magically put the hardware into the
-       * right mode for your API.  Sadly, Vulkan isn't any of the APIs the
-       * hardware people thought of so nothing works the way you want it to.
-       *
-       * Look at the table titled "Multisample Rasterization Modes" in Vol 7
-       * of the Skylake PRM for more details.
-       */
-      switch (line_mode) {
-      case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
-         raster.APIMode = DX100;
-         raster.DXMultisampleRasterizationEnable = true;
-         break;
-
-      case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
-      case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
-         raster.APIMode = DX9OGL;
-         raster.DXMultisampleRasterizationEnable = false;
-         break;
-
-      default:
-         unreachable("Unsupported line rasterization mode");
-      }
-   } else {
-      raster.APIMode = DX100;
-      raster.DXMultisampleRasterizationEnable = true;
-   }
+   if (!dynamic_primitive_topology)
+      genX(rasterization_mode)(raster_mode, pipeline->line_mode,
+                               &raster.APIMode,
+                               &raster.DXMultisampleRasterizationEnable);
 
    /* NOTE: 3DSTATE_RASTER::ForcedSampleCount affects the BDW and SKL PMA fix
     * computations.  If we ever set this bit to a different value, they will
@@ -714,13 +704,17 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
    raster.ForcedSampleCount = FSC_NUMRASTSAMPLES_0;
    raster.ForceMultisampling = false;
 #else
-   raster.MultisampleRasterizationMode =
-      gfx7_ms_rast_mode(pipeline, ia_info, rs_info, ms_info);
+   uint32_t ms_rast_mode = 0;
+
+   if (!dynamic_primitive_topology)
+      ms_rast_mode = genX(ms_rasterization_mode)(pipeline, raster_mode);
+
+   raster.MultisampleRasterizationMode = ms_rast_mode;
 #endif
 
-   if (raster_mode == VK_POLYGON_MODE_LINE &&
-       line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT)
-      raster.AntialiasingEnable = true;
+   raster.AntialiasingEnable =
+      dynamic_primitive_topology ? 0 :
+      anv_rasterization_aa_mode(raster_mode, pipeline->line_mode);
 
    raster.FrontWinding =
       dynamic_states & ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE ?
@@ -1423,8 +1417,10 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
     * points and lines so we get "pop-free" clipping.
     */
    VkPolygonMode raster_mode =
-      anv_raster_polygon_mode(pipeline, ia_info, rs_info);
-   clip.ViewportXYClipTestEnable = (raster_mode == VK_POLYGON_MODE_FILL);
+      genX(raster_polygon_mode)(pipeline, ia_info->topology);
+   clip.ViewportXYClipTestEnable =
+      dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY ?
+         0 : (raster_mode == VK_POLYGON_MODE_FILL);
 
 #if GFX_VER >= 8
    clip.VertexSubPixelPrecisionSelect = _8Bit;
@@ -2133,14 +2129,25 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline, struct anv_subpass *subp
       } else {
          wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE;
       }
+
+      VkPolygonMode raster_mode =
+         genX(raster_polygon_mode)(pipeline, ia->topology);
+
       wm.MultisampleRasterizationMode =
-         gfx7_ms_rast_mode(pipeline, ia, raster, multisample);
+         dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY ? 0 :
+         genX(ms_rasterization_mode)(pipeline, raster_mode);
 #endif
 
       wm.LineStippleEnable = line && line->stippledLineEnable;
    }
 
-   if (dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) {
+   uint32_t dynamic_wm_states = ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
+
+#if GFX_VER < 8
+   dynamic_wm_states |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY;
+#endif
+
+   if (dynamic_states & dynamic_wm_states) {
       const struct intel_device_info *devinfo = &pipeline->base.device->info;
       uint32_t *dws = devinfo->ver >= 8 ? pipeline->gfx8.wm : pipeline->gfx7.wm;
       GENX(3DSTATE_WM_pack)(NULL, dws, &wm);
diff --git a/src/intel/vulkan/gfx7_cmd_buffer.c b/src/intel/vulkan/gfx7_cmd_buffer.c
index ff808f27f3d..b092bd8c377 100644
--- a/src/intel/vulkan/gfx7_cmd_buffer.c
+++ b/src/intel/vulkan/gfx7_cmd_buffer.c
@@ -206,13 +206,42 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
    struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
    struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic;
 
+   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
+      uint32_t topology;
+      if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
+         topology = pipeline->topology;
+      else
+         topology = genX(vk_to_intel_primitive_type)[d->primitive_topology];
+
+      cmd_buffer->state.gfx.primitive_topology = topology;
+   }
+
    if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
                                       ANV_CMD_DIRTY_RENDER_TARGETS |
                                       ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH |
                                       ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS |
                                       ANV_CMD_DIRTY_DYNAMIC_CULL_MODE |
                                       ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE |
-                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE)) {
+                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE |
+                                      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) {
+      /* Take dynamic primitive topology in to account with
+       *    3DSTATE_SF::MultisampleRasterizationMode
+       */
+      uint32_t ms_rast_mode = 0;
+
+      if (cmd_buffer->state.gfx.pipeline->dynamic_states &
+          ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
+         VkPrimitiveTopology primitive_topology =
+            cmd_buffer->state.gfx.dynamic.primitive_topology;
+
+         VkPolygonMode dynamic_raster_mode =
+            genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
+                                      primitive_topology);
+
+         ms_rast_mode =
+            genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode);
+      }
+
       uint32_t sf_dw[GENX(3DSTATE_SF_length)];
       struct GENX(3DSTATE_SF) sf = {
          GENX(3DSTATE_SF_header),
@@ -226,6 +255,7 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
          .GlobalDepthOffsetEnableSolid = d->depth_bias_enable,
          .GlobalDepthOffsetEnableWireframe = d->depth_bias_enable,
          .GlobalDepthOffsetEnablePoint = d->depth_bias_enable,
+         .MultisampleRasterizationMode = ms_rast_mode,
       };
       GENX(3DSTATE_SF_pack)(NULL, sf_dw, &sf);
 
@@ -339,45 +369,56 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
       }
    }
 
-   if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
-                                      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) {
-      uint32_t topology;
-      if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
-         topology = pipeline->topology;
-      else
-         topology = genX(vk_to_intel_primitive_type)[d->primitive_topology];
-
-      cmd_buffer->state.gfx.primitive_topology = topology;
-   }
-
-   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
-      genX(emit_multisample)(&cmd_buffer->batch,
-                             cmd_buffer->state.gfx.dynamic.sample_locations.samples,
-                             cmd_buffer->state.gfx.dynamic.sample_locations.locations);
-   }
-
+   /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders
+    * threads or if we have dirty dynamic primitive topology state and
+    * need to toggle 3DSTATE_WM::MultisampleRasterizationMode dynamically.
+    */
    if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE ||
-       cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) {
+       cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
       const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
-      /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders
-       * threads.
-       */
+
       bool dirty_color_blend =
          cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
 
-      if (dirty_color_blend) {
+      bool dirty_primitive_topology =
+         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY;
+
+      VkPolygonMode dynamic_raster_mode;
+      VkPrimitiveTopology primitive_topology =
+         cmd_buffer->state.gfx.dynamic.primitive_topology;
+      dynamic_raster_mode =
+         genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
+                                   primitive_topology);
+
+      if (dirty_color_blend || dirty_primitive_topology) {
          uint32_t dwords[GENX(3DSTATE_WM_length)];
          struct GENX(3DSTATE_WM) wm = {
             GENX(3DSTATE_WM_header),
 
             .ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch ||
                                     color_writes,
+            .MultisampleRasterizationMode =
+               genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode),
          };
          GENX(3DSTATE_WM_pack)(NULL, dwords, &wm);
 
          anv_batch_emit_merge(&cmd_buffer->batch, dwords, pipeline->gfx7.wm);
       }
 
+   }
+
+   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
+      genX(emit_multisample)(&cmd_buffer->batch,
+                             cmd_buffer->state.gfx.dynamic.sample_locations.samples,
+                             cmd_buffer->state.gfx.dynamic.sample_locations.locations);
+   }
+
+   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE ||
+       cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) {
+      const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
+      bool dirty_color_blend =
+         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
+
       /* Blend states of each RT */
       uint32_t surface_count = 0;
       struct anv_pipeline_bind_map *map;
diff --git a/src/intel/vulkan/gfx8_cmd_buffer.c b/src/intel/vulkan/gfx8_cmd_buffer.c
index f428c022cf8..05092caab6c 100644
--- a/src/intel/vulkan/gfx8_cmd_buffer.c
+++ b/src/intel/vulkan/gfx8_cmd_buffer.c
@@ -420,6 +420,20 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
    struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
    struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic;
 
+   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
+      uint32_t topology;
+      if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
+         topology = pipeline->topology;
+      else
+         topology = genX(vk_to_intel_primitive_type)[d->primitive_topology];
+
+      cmd_buffer->state.gfx.primitive_topology = topology;
+
+      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) {
+         vft.PrimitiveTopologyType = topology;
+      }
+   }
+
    if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
                                       ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH)) {
       uint32_t sf_dw[GENX(3DSTATE_SF_length)];
@@ -443,10 +457,41 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
                                       ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS |
                                       ANV_CMD_DIRTY_DYNAMIC_CULL_MODE |
                                       ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE |
-                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE)) {
+                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE |
+                                      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) {
+      /* Take dynamic primitive topology in to account with
+       *    3DSTATE_RASTER::APIMode
+       *    3DSTATE_RASTER::DXMultisampleRasterizationEnable
+       *    3DSTATE_RASTER::AntialiasingEnable
+       */
+      uint32_t api_mode = 0;
+      bool msaa_raster_enable = false;
+      bool aa_enable = 0;
+
+      if (cmd_buffer->state.gfx.pipeline->dynamic_states &
+          ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
+         VkPrimitiveTopology primitive_topology =
+            cmd_buffer->state.gfx.dynamic.primitive_topology;
+
+         VkPolygonMode dynamic_raster_mode =
+            genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
+                                      primitive_topology);
+
+         genX(rasterization_mode)(
+            dynamic_raster_mode, pipeline->line_mode, &api_mode,
+            &msaa_raster_enable);
+
+         aa_enable =
+            anv_rasterization_aa_mode(dynamic_raster_mode,
+                                      pipeline->line_mode);
+      }
+
       uint32_t raster_dw[GENX(3DSTATE_RASTER_length)];
       struct GENX(3DSTATE_RASTER) raster = {
          GENX(3DSTATE_RASTER_header),
+         .APIMode = api_mode,
+         .DXMultisampleRasterizationEnable = msaa_raster_enable,
+         .AntialiasingEnable = aa_enable,
          .GlobalDepthOffsetConstant = d->depth_bias.bias,
          .GlobalDepthOffsetScale = d->depth_bias.slope,
          .GlobalDepthOffsetClamp = d->depth_bias.clamp,
@@ -638,21 +683,6 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
       }
    }
 
-   if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
-                                      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) {
-      uint32_t topology;
-      if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
-         topology = pipeline->topology;
-      else
-         topology = genX(vk_to_intel_primitive_type)[d->primitive_topology];
-
-      cmd_buffer->state.gfx.primitive_topology = topology;
-
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) {
-         vft.PrimitiveTopologyType = topology;
-      }
-   }
-
    if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
       genX(emit_sample_pattern)(&cmd_buffer->batch,
                                 cmd_buffer->state.gfx.dynamic.sample_locations.samples,



More information about the mesa-commit mailing list