diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 7c3b6e95515..dc5a026b06e 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -3392,6 +3392,25 @@ tu_CmdSetColorBlendEquationEXT(VkCommandBuffer commandBuffer, cmd->state.dirty |= TU_CMD_DIRTY_BLEND; } +VKAPI_ATTR void VKAPI_CALL +tu_CmdSetColorWriteMaskEXT(VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorComponentFlags *pColorWriteMasks) +{ + TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); + + for (unsigned i = 0; i < attachmentCount; i++) { + unsigned att = i + firstAttachment; + cmd->state.rb_mrt_control[att] = + (cmd->state.rb_mrt_control[att] & + ~A6XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK) | + A6XX_RB_MRT_CONTROL_COMPONENT_ENABLE(pColorWriteMasks[i]); + } + + cmd->state.dirty |= TU_CMD_DIRTY_BLEND; +} + static void tu_flush_for_access(struct tu_cache_state *cache, enum tu_cmd_access_mask src_mask, diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index 821efa66854..bcce1f06fcc 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -780,7 +780,7 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->extendedDynamicState3SampleLocationsEnable = true; features->extendedDynamicState3ColorBlendEnable = true; features->extendedDynamicState3ColorBlendEquation = true; - features->extendedDynamicState3ColorWriteMask = false; + features->extendedDynamicState3ColorWriteMask = true; features->extendedDynamicState3ViewportWScalingEnable = false; features->extendedDynamicState3ViewportSwizzle = false; features->extendedDynamicState3ShadingRateImageEnable = false; diff --git a/src/freedreno/vulkan/tu_lrz.c b/src/freedreno/vulkan/tu_lrz.c index 599f1817d01..b96cc7bca0e 100644 --- a/src/freedreno/vulkan/tu_lrz.c +++ b/src/freedreno/vulkan/tu_lrz.c @@ -689,6 +689,25 @@ tu6_calculate_lrz_state(struct tu_cmd_buffer *cmd, gras_lrz_cntl.lrz_write = false; } + if ((cmd->state.pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_BLEND))) { + for (unsigned i = 0; i < cmd->state.subpass->color_count; i++) { + unsigned a = cmd->state.subpass->color_attachments[i].attachment; + if (a == VK_ATTACHMENT_UNUSED) + continue; + + VkFormat format = cmd->state.pass->attachments[a].format; + unsigned mask = MASK(vk_format_get_nr_components(format)); + if ((cmd->state.rb_mrt_control[i] & + A6XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK) >> + A6XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT != mask) { + if (gras_lrz_cntl.lrz_write) + perf_debug(cmd->device, "disabling lrz write due to dynamic color write mask"); + gras_lrz_cntl.lrz_write = false; + break; + } + } + } + if ((cmd->state.pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_COLOR_WRITE_ENABLE)) && (cmd->state.color_write_enable & diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index 04ac934685c..075988c5648 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -2286,13 +2286,19 @@ tu6_emit_rb_mrt_controls(struct tu_pipeline *pipeline, uint32_t rb_mrt_blend_control = 0; if (format != VK_FORMAT_UNDEFINED && (!color_info || color_info->pColorWriteEnables[i])) { - rb_mrt_control = - tu6_rb_mrt_control(att); - rb_mrt_blend_control = tu6_rb_mrt_blend_control(att); + const uint64_t blend_att_states = + BIT(TU_DYNAMIC_STATE_COLOR_WRITE_MASK) | + BIT(TU_DYNAMIC_STATE_BLEND_ENABLE) | + BIT(TU_DYNAMIC_STATE_BLEND_EQUATION); + if ((pipeline->dynamic_state_mask & blend_att_states) != blend_att_states) { + rb_mrt_control = tu6_rb_mrt_control(att); + rb_mrt_blend_control = tu6_rb_mrt_blend_control(att); + } /* calculate bpp based on format and write mask */ uint32_t write_bpp = 0; - if (att->colorWriteMask == 0xf) { + if ((pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_COLOR_WRITE_MASK)) || + att->colorWriteMask == 0xf) { write_bpp = vk_format_get_blocksizebits(format); } else { const enum pipe_format pipe_format = vk_format_to_pipe_format(format); @@ -3784,6 +3790,12 @@ tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder, pipeline->blend.sp_blend_cntl_mask &= ~A6XX_SP_BLEND_CNTL_DUAL_COLOR_IN_ENABLE; pipeline->blend.rb_blend_cntl_mask &= ~A6XX_RB_BLEND_CNTL_DUAL_COLOR_IN_ENABLE; break; + case VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT: + pipeline->dynamic_state_mask |= + BIT(TU_DYNAMIC_STATE_BLEND) | + BIT(TU_DYNAMIC_STATE_COLOR_WRITE_MASK); + pipeline->blend.rb_mrt_control_mask &= ~A6XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK; + break; default: assert(!"unsupported dynamic state"); break; @@ -4576,18 +4588,25 @@ tu_pipeline_builder_parse_multisample_and_color_blend( BIT(TU_DYNAMIC_STATE_BLEND_ENABLE)))) pipeline->lrz.force_disable_mask |= TU_LRZ_FORCE_DISABLE_WRITE; - for (int i = 0; i < blend_info->attachmentCount; i++) { - VkPipelineColorBlendAttachmentState blendAttachment = blend_info->pAttachments[i]; - /* From the PoV of LRZ, having masked color channels is - * the same as having blend enabled, in that the draw will - * care about the fragments from an earlier draw. - */ - VkFormat format = builder->color_attachment_formats[i]; - unsigned mask = MASK(vk_format_get_nr_components(format)); - if (format != VK_FORMAT_UNDEFINED && - ((blendAttachment.colorWriteMask & mask) != mask || - !(pipeline->blend.color_write_enable & BIT(i)))) { - pipeline->lrz.force_disable_mask |= TU_LRZ_FORCE_DISABLE_WRITE; + if (!(pipeline->dynamic_state_mask & + BIT(TU_DYNAMIC_STATE_COLOR_WRITE_ENABLE)) && + (pipeline->blend.color_write_enable & MASK(pipeline->blend.num_rts)) != + MASK(pipeline->blend.num_rts)) + pipeline->lrz.force_disable_mask |= TU_LRZ_FORCE_DISABLE_WRITE; + + if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_BLEND))) { + for (int i = 0; i < blend_info->attachmentCount; i++) { + VkPipelineColorBlendAttachmentState blendAttachment = blend_info->pAttachments[i]; + /* From the PoV of LRZ, having masked color channels is + * the same as having blend enabled, in that the draw will + * care about the fragments from an earlier draw. + */ + VkFormat format = builder->color_attachment_formats[i]; + unsigned mask = MASK(vk_format_get_nr_components(format)); + if (format != VK_FORMAT_UNDEFINED && + (blendAttachment.colorWriteMask & mask) != mask) { + pipeline->lrz.force_disable_mask |= TU_LRZ_FORCE_DISABLE_WRITE; + } } } diff --git a/src/freedreno/vulkan/tu_pipeline.h b/src/freedreno/vulkan/tu_pipeline.h index 29db8de17c6..1008ea9ce3a 100644 --- a/src/freedreno/vulkan/tu_pipeline.h +++ b/src/freedreno/vulkan/tu_pipeline.h @@ -46,6 +46,7 @@ enum tu_dynamic_state TU_DYNAMIC_STATE_PROVOKING_VTX, TU_DYNAMIC_STATE_BLEND_ENABLE, TU_DYNAMIC_STATE_BLEND_EQUATION, + TU_DYNAMIC_STATE_COLOR_WRITE_MASK, /* re-use the line width enum as it uses GRAS_SU_CNTL: */ TU_DYNAMIC_STATE_RAST = VK_DYNAMIC_STATE_LINE_WIDTH, };