anv: fix color write enable interaction with color mask
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Mon, 14 Mar 2022 07:52:35 +0000 (09:52 +0200)
committerMarge Bot <emma+marge@anholt.net>
Thu, 24 Mar 2022 10:49:07 +0000 (10:49 +0000)
Color writes & color masks occupy the same fields in the BLEND_STATE
structure. So we need to store color mask (which are not dynamic) on
the pipeline to merge that information with color writes.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Fixes: b15bfe92f7f8 ("anv: implement VK_EXT_color_write_enable")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6111
Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15310>

src/intel/vulkan/anv_pipeline.c
src/intel/vulkan/anv_private.h
src/intel/vulkan/genX_pipeline.c
src/intel/vulkan/gfx7_cmd_buffer.c
src/intel/vulkan/gfx8_cmd_buffer.c

index e7db921..7c6c0d4 100644 (file)
@@ -2058,6 +2058,16 @@ anv_pipeline_compile_cs(struct anv_compute_pipeline *pipeline,
    return VK_SUCCESS;
 }
 
+static bool
+anv_rendering_uses_color_attachment(const VkPipelineRenderingCreateInfo *rendering_info)
+{
+   for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) {
+      if (rendering_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED)
+         return true;
+   }
+   return false;
+}
+
 /**
  * Copy pipeline state not marked as dynamic.
  * Dynamic state is pipeline state which hasn't been provided at pipeline
@@ -2176,13 +2186,7 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
     *    disabled or if the subpass of the render pass the pipeline is
     *    created against does not use any color attachments.
     */
-   bool uses_color_att = false;
-   for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) {
-      if (rendering_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED) {
-         uses_color_att = true;
-         break;
-      }
-   }
+   bool uses_color_att = anv_rendering_uses_color_attachment(rendering_info);
 
    if (uses_color_att && !raster_discard) {
       assert(pCreateInfo->pColorBlendState);
@@ -2555,6 +2559,17 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
    pipeline->rasterization_samples =
       ms_info ? ms_info->rasterizationSamples : 1;
 
+   /* Store the color write masks, to be merged with color write enable if
+    * dynamic.
+    */
+   if (raster_enabled && anv_rendering_uses_color_attachment(rendering_info)) {
+      for (unsigned i = 0; i < pCreateInfo->pColorBlendState->attachmentCount; i++) {
+         const VkPipelineColorBlendAttachmentState *a =
+            &pCreateInfo->pColorBlendState->pAttachments[i];
+         pipeline->color_comp_writes[i] = a->colorWriteMask;
+      }
+   }
+
    return VK_SUCCESS;
 }
 
index 2d44d16..7e95f24 100644 (file)
@@ -3383,6 +3383,8 @@ struct anv_graphics_pipeline {
    VkPolygonMode                                polygon_mode;
    uint32_t                                     rasterization_samples;
 
+   VkColorComponentFlags                        color_comp_writes[MAX_RTS];
+
    struct anv_shader_bin *                      shaders[ANV_GRAPHICS_SHADER_STAGE_COUNT];
 
    VkShaderStageFlags                           active_stages;
@@ -3505,6 +3507,25 @@ anv_pipeline_is_mesh(const struct anv_graphics_pipeline *pipeline)
    return anv_pipeline_has_stage(pipeline, MESA_SHADER_MESH);
 }
 
+static inline bool
+anv_cmd_buffer_all_color_write_masked(const struct anv_cmd_buffer *cmd_buffer)
+{
+   const struct anv_cmd_graphics_state *state = &cmd_buffer->state.gfx;
+   uint8_t color_writes = state->dynamic.color_writes;
+
+   /* All writes disabled through vkCmdSetColorWriteEnableEXT */
+   if ((color_writes & ((1u << state->color_att_count) - 1)) == 0)
+      return true;
+
+   /* Or all write masks are empty */
+   for (uint32_t i = 0; i < state->color_att_count; i++) {
+      if (state->pipeline->color_comp_writes[i] != 0)
+         return false;
+   }
+
+   return true;
+}
+
 #define ANV_DECL_GET_GRAPHICS_PROG_DATA_FUNC(prefix, stage)             \
 static inline const struct brw_##prefix##_prog_data *                   \
 get_##prefix##_prog_data(const struct anv_graphics_pipeline *pipeline)  \
index a1bccf9..d2c707d 100644 (file)
@@ -1406,8 +1406,6 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
          .AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
 #endif
          .LogicOpEnable = info->logicOpEnable,
-         .LogicOpFunction = dynamic_states & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP ?
-                            0: genX(vk_to_intel_logic_op)[info->logicOp],
 
          /* Vulkan specification 1.2.168, VkLogicOp:
           *
@@ -1434,20 +1432,20 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
          .SourceAlphaBlendFactor = vk_to_intel_blend[a->srcAlphaBlendFactor],
          .DestinationAlphaBlendFactor = vk_to_intel_blend[a->dstAlphaBlendFactor],
          .AlphaBlendFunction = vk_to_intel_blend_op[a->alphaBlendOp],
-         .WriteDisableAlpha =
-            (dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
-            !(a->colorWriteMask & VK_COLOR_COMPONENT_A_BIT),
-         .WriteDisableRed =
-            (dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
-            !(a->colorWriteMask & VK_COLOR_COMPONENT_R_BIT),
-         .WriteDisableGreen =
-             (dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
-             !(a->colorWriteMask & VK_COLOR_COMPONENT_G_BIT),
-         .WriteDisableBlue =
-             (dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
-             !(a->colorWriteMask & VK_COLOR_COMPONENT_B_BIT),
       };
 
+      /* Write logic op if not dynamic */
+      if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP))
+         entry.LogicOpFunction = genX(vk_to_intel_logic_op)[info->logicOp];
+
+      /* Write blending color if not dynamic */
+      if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)) {
+         entry.WriteDisableAlpha = !(a->colorWriteMask & VK_COLOR_COMPONENT_A_BIT);
+         entry.WriteDisableRed   = !(a->colorWriteMask & VK_COLOR_COMPONENT_R_BIT);
+         entry.WriteDisableGreen = !(a->colorWriteMask & VK_COLOR_COMPONENT_G_BIT);
+         entry.WriteDisableBlue  = !(a->colorWriteMask & VK_COLOR_COMPONENT_B_BIT);
+      }
+
       if (a->srcColorBlendFactor != a->srcAlphaBlendFactor ||
           a->dstColorBlendFactor != a->dstAlphaBlendFactor ||
           a->colorBlendOp != a->alphaBlendOp) {
@@ -2319,11 +2317,11 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
          wm_prog_data->has_side_effects ||
          wm_prog_data->uses_kill;
 
-      if (pipeline->force_fragment_thread_dispatch ||
-          !has_color_buffer_write_enabled(pipeline, blend)) {
-         /* Only set this value in non dynamic mode. */
+      /* Only set this value in non dynamic mode. */
+      if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)) {
          wm.ForceThreadDispatchEnable =
-            !(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) ? ForceON : 0;
+            (pipeline->force_fragment_thread_dispatch ||
+             !has_color_buffer_write_enabled(pipeline, blend)) ? ForceON : 0;
       }
 #endif
 
@@ -2352,10 +2350,11 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
          wm_prog_data->has_side_effects ||
          wm.PixelShaderKillsPixel;
 
-      if (pipeline->force_fragment_thread_dispatch ||
-          has_color_buffer_write_enabled(pipeline, blend)) {
-         /* Only set this value in non dynamic mode. */
-         wm.ThreadDispatchEnable = !(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE);
+      /* Only set this value in non dynamic mode. */
+      if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)) {
+         wm.ThreadDispatchEnable =
+            pipeline->force_fragment_thread_dispatch ||
+            has_color_buffer_write_enabled(pipeline, blend);
       }
 
       if (multisample && multisample->rasterizationSamples > 1) {
index 285d140..cf18342 100644 (file)
@@ -290,13 +290,12 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
          genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
                                    primitive_topology);
 
-      const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
       uint32_t dwords[GENX(3DSTATE_WM_length)];
       struct GENX(3DSTATE_WM) wm = {
          GENX(3DSTATE_WM_header),
 
          .ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch ||
-                                 color_writes,
+                                 !anv_cmd_buffer_all_color_write_masked(cmd_buffer),
          .MultisampleRasterizationMode =
                                  genX(ms_rasterization_mode)(pipeline,
                                                              dynamic_raster_mode),
@@ -317,8 +316,6 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
                                           ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
                                           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;
 
       uint32_t blend_dws[GENX(BLEND_STATE_length) +
                          MAX_RTS * GENX(BLEND_STATE_ENTRY_length)];
@@ -328,19 +325,24 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
       /* Skip this part */
       dws += GENX(BLEND_STATE_length);
 
-      bool dirty_logic_op =
-         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
-
       for (uint32_t i = 0; i < MAX_RTS; i++) {
-         bool write_disabled = dirty_color_blend &&
-            (color_writes & BITFIELD_BIT(i)) == 0;
+         /* Disable anything above the current number of color attachments. */
+         bool write_disabled = i >= cmd_buffer->state.gfx.color_att_count ||
+                               (color_writes & BITFIELD_BIT(i)) == 0;
          struct GENX(BLEND_STATE_ENTRY) entry = {
-            .WriteDisableAlpha = write_disabled,
-            .WriteDisableRed   = write_disabled,
-            .WriteDisableGreen = write_disabled,
-            .WriteDisableBlue  = write_disabled,
-            .LogicOpFunction =
-               dirty_logic_op ? genX(vk_to_intel_logic_op)[d->logic_op] : 0,
+            .WriteDisableAlpha = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_A_BIT) == 0,
+            .WriteDisableRed   = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_R_BIT) == 0,
+            .WriteDisableGreen = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_G_BIT) == 0,
+            .WriteDisableBlue  = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_B_BIT) == 0,
+            .LogicOpFunction   = genX(vk_to_intel_logic_op)[d->logic_op],
          };
          GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
          dws += GENX(BLEND_STATE_ENTRY_length);
index 5e16510..8f30e12 100644 (file)
@@ -642,7 +642,6 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
                                           ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
                                           ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP)) {
       const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
-
       /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders
        * threads.
        */
@@ -651,7 +650,8 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
          GENX(3DSTATE_WM_header),
 
          .ForceThreadDispatchEnable = (pipeline->force_fragment_thread_dispatch ||
-                                       !color_writes) ? ForceON : 0,
+                                       anv_cmd_buffer_all_color_write_masked(cmd_buffer)) ?
+                                      ForceON : 0,
       };
       GENX(3DSTATE_WM_pack)(NULL, wm_dwords, &wm);
 
@@ -677,18 +677,24 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
       /* Skip this part */
       dws += GENX(BLEND_STATE_length);
 
-      bool dirty_logic_op =
-         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
-
       for (uint32_t i = 0; i < MAX_RTS; i++) {
-         bool write_disabled = (color_writes & BITFIELD_BIT(i)) == 0;
+         /* Disable anything above the current number of color attachments. */
+         bool write_disabled = i >= cmd_buffer->state.gfx.color_att_count ||
+                               (color_writes & BITFIELD_BIT(i)) == 0;
          struct GENX(BLEND_STATE_ENTRY) entry = {
-            .WriteDisableAlpha = write_disabled,
-            .WriteDisableRed   = write_disabled,
-            .WriteDisableGreen = write_disabled,
-            .WriteDisableBlue  = write_disabled,
-            .LogicOpFunction =
-               dirty_logic_op ? genX(vk_to_intel_logic_op)[d->logic_op] : 0,
+            .WriteDisableAlpha = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_A_BIT) == 0,
+            .WriteDisableRed   = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_R_BIT) == 0,
+            .WriteDisableGreen = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_G_BIT) == 0,
+            .WriteDisableBlue  = write_disabled ||
+                                 (pipeline->color_comp_writes[i] &
+                                  VK_COLOR_COMPONENT_B_BIT) == 0,
+            .LogicOpFunction   = genX(vk_to_intel_logic_op)[d->logic_op],
          };
          GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
          dws += GENX(BLEND_STATE_ENTRY_length);