From 1d250b7b959d2a206280e4f83db05780a83e0927 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 14 Mar 2022 09:52:35 +0200 Subject: [PATCH] anv: fix color write enable interaction with color mask MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Fixes: b15bfe92f7f8 ("anv: implement VK_EXT_color_write_enable") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6111 Reviewed-by: Tapani Pälli Part-of: --- src/intel/vulkan/anv_pipeline.c | 29 ++++++++++++++++++------- src/intel/vulkan/anv_private.h | 21 +++++++++++++++++++ src/intel/vulkan/genX_pipeline.c | 43 +++++++++++++++++++------------------- src/intel/vulkan/gfx7_cmd_buffer.c | 32 +++++++++++++++------------- src/intel/vulkan/gfx8_cmd_buffer.c | 30 +++++++++++++++----------- 5 files changed, 99 insertions(+), 56 deletions(-) diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index e7db921..7c6c0d4 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -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; } diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 2d44d16..7e95f24 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -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) \ diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index a1bccf9..d2c707d 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -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) { diff --git a/src/intel/vulkan/gfx7_cmd_buffer.c b/src/intel/vulkan/gfx7_cmd_buffer.c index 285d140..cf18342 100644 --- a/src/intel/vulkan/gfx7_cmd_buffer.c +++ b/src/intel/vulkan/gfx7_cmd_buffer.c @@ -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); diff --git a/src/intel/vulkan/gfx8_cmd_buffer.c b/src/intel/vulkan/gfx8_cmd_buffer.c index 5e16510..8f30e12 100644 --- a/src/intel/vulkan/gfx8_cmd_buffer.c +++ b/src/intel/vulkan/gfx8_cmd_buffer.c @@ -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); -- 2.7.4