diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 2b2fcd60243..99fca1a0f74 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -2712,8 +2712,9 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer, cmd->state.pipeline_color_write_enable = pipeline->blend.color_write_enable; cmd->state.dirty |= TU_CMD_DIRTY_BLEND; } - if (cmd->state.pipeline_blend_enable != pipeline->blend.blend_enable) { - cmd->state.pipeline_blend_enable = pipeline->blend.blend_enable; + if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_BLEND_ENABLE)) && + cmd->state.blend_enable != pipeline->blend.blend_enable) { + cmd->state.blend_enable = pipeline->blend.blend_enable; cmd->state.dirty |= TU_CMD_DIRTY_BLEND; } if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_LOGIC_OP_ENABLE)) && @@ -3314,6 +3315,29 @@ tu_CmdSetProvokingVertexModeEXT(VkCommandBuffer commandBuffer, provokingVertexMode == VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT; } +VKAPI_ATTR void VKAPI_CALL +tu_CmdSetColorBlendEnableEXT(VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkBool32 *pColorBlendEnables) +{ + TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); + + for (unsigned i = 0; i < attachmentCount; i++) { + unsigned att = i + firstAttachment; + cmd->state.blend_enable = + (cmd->state.blend_enable & ~BIT(att)) | + COND(pColorBlendEnables[i], BIT(att)); + const uint32_t blend_enable = + A6XX_RB_MRT_CONTROL_BLEND | A6XX_RB_MRT_CONTROL_BLEND2; + cmd->state.rb_mrt_control[i] = + (cmd->state.rb_mrt_control[i] & ~blend_enable) | + COND(pColorBlendEnables[i], blend_enable); + } + + 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, @@ -4609,7 +4633,7 @@ tu6_emit_blend(struct tu_cs *cs, struct tu_cmd_buffer *cmd) uint32_t blend_enable_mask = color_write_enable; if (!(cmd->state.logic_op_enabled && cmd->state.rop_reads_dst)) - blend_enable_mask &= cmd->state.pipeline_blend_enable; + blend_enable_mask &= cmd->state.blend_enable; tu_cs_emit_regs(cs, A6XX_SP_FS_OUTPUT_CNTL1(.mrt = num_rts)); tu_cs_emit_regs(cs, A6XX_RB_FS_OUTPUT_CNTL1(.mrt = num_rts)); diff --git a/src/freedreno/vulkan/tu_cmd_buffer.h b/src/freedreno/vulkan/tu_cmd_buffer.h index 1faec832b6d..9b89b71baac 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.h +++ b/src/freedreno/vulkan/tu_cmd_buffer.h @@ -341,7 +341,7 @@ struct tu_cmd_state uint32_t rb_mrt_control[MAX_RTS], rb_mrt_blend_control[MAX_RTS]; uint32_t rb_mrt_control_rop; uint32_t rb_blend_cntl, sp_blend_cntl; - uint32_t pipeline_color_write_enable, pipeline_blend_enable; + uint32_t pipeline_color_write_enable, blend_enable; uint32_t color_write_enable; bool logic_op_enabled; bool rop_reads_dst; diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index dffd9f8173a..993bd7b208a 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -778,7 +778,7 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->extendedDynamicState3LineStippleEnable = false; features->extendedDynamicState3ProvokingVertexMode = true; features->extendedDynamicState3SampleLocationsEnable = true; - features->extendedDynamicState3ColorBlendEnable = false; + features->extendedDynamicState3ColorBlendEnable = true; features->extendedDynamicState3ColorBlendEquation = false; features->extendedDynamicState3ColorWriteMask = false; features->extendedDynamicState3ViewportWScalingEnable = false; diff --git a/src/freedreno/vulkan/tu_lrz.c b/src/freedreno/vulkan/tu_lrz.c index 18a5d158ac7..599f1817d01 100644 --- a/src/freedreno/vulkan/tu_lrz.c +++ b/src/freedreno/vulkan/tu_lrz.c @@ -673,6 +673,7 @@ tu6_calculate_lrz_state(struct tu_cmd_buffer *cmd, gras_lrz_cntl.dir_write = cmd->state.lrz.gpu_dir_tracking; gras_lrz_cntl.disable_on_wrong_dir = cmd->state.lrz.gpu_dir_tracking; + /* See comment in tu_pipeline about disabling LRZ write for blending. */ if ((cmd->state.pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_LOGIC_OP)) && cmd->state.logic_op_enabled && cmd->state.rop_reads_dst) { @@ -681,6 +682,13 @@ 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_ENABLE)) && + cmd->state.blend_enable) { + if (gras_lrz_cntl.lrz_write) + perf_debug(cmd->device, "disabling lrz write due to dynamic blend"); + gras_lrz_cntl.lrz_write = false; + } + 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 c17a9504cb8..a17a8b5285b 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -2319,11 +2319,14 @@ tu6_emit_rb_mrt_controls(struct tu_pipeline *pipeline, total_bpp += write_bpp; pipeline->blend.color_write_enable |= BIT(i); - if (att->blendEnable) - pipeline->blend.blend_enable |= BIT(i); - if (att->blendEnable || (blend_info->logicOpEnable && *rop_reads_dst)) { - total_bpp += write_bpp; + if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_BLEND_ENABLE))) { + if (att->blendEnable) + pipeline->blend.blend_enable |= BIT(i); + + if (att->blendEnable || (blend_info->logicOpEnable && *rop_reads_dst)) { + total_bpp += write_bpp; + } } } @@ -3778,6 +3781,15 @@ tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder, case VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT: pipeline->dynamic_state_mask |= BIT(TU_DYNAMIC_STATE_PROVOKING_VTX); break; + case VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT: + pipeline->dynamic_state_mask |= + BIT(TU_DYNAMIC_STATE_BLEND) | + BIT(TU_DYNAMIC_STATE_BLEND_ENABLE); + pipeline->blend.rb_mrt_control_mask &= + ~(A6XX_RB_MRT_CONTROL_BLEND | A6XX_RB_MRT_CONTROL_BLEND2); + pipeline->blend.sp_blend_cntl_mask &= ~A6XX_SP_BLEND_CNTL_ENABLE_BLEND__MASK; + pipeline->blend.rb_blend_cntl_mask &= ~A6XX_RB_BLEND_CNTL_ENABLE_BLEND__MASK; + break; default: assert(!"unsupported dynamic state"); break; @@ -3881,6 +3893,7 @@ tu_pipeline_builder_parse_libraries(struct tu_pipeline_builder *builder, BIT(TU_DYNAMIC_STATE_SAMPLE_LOCATIONS) | BIT(TU_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE) | BIT(TU_DYNAMIC_STATE_BLEND) | + BIT(TU_DYNAMIC_STATE_BLEND_ENABLE) | BIT(TU_DYNAMIC_STATE_LOGIC_OP) | BIT(TU_DYNAMIC_STATE_LOGIC_OP_ENABLE) | BIT(TU_DYNAMIC_STATE_COLOR_WRITE_ENABLE) | @@ -4561,7 +4574,10 @@ tu_pipeline_builder_parse_multisample_and_color_blend( * Therefore, we need to emit it in a separate draw state. We keep * it disabled for sysmem path as well for the moment. */ - if (blend_enable_mask) + if (blend_enable_mask && + !(pipeline->dynamic_state_mask & + (BIT(TU_DYNAMIC_STATE_LOGIC_OP) | + 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++) { diff --git a/src/freedreno/vulkan/tu_pipeline.h b/src/freedreno/vulkan/tu_pipeline.h index df09186e3ee..0d5f029dd76 100644 --- a/src/freedreno/vulkan/tu_pipeline.h +++ b/src/freedreno/vulkan/tu_pipeline.h @@ -44,6 +44,7 @@ enum tu_dynamic_state TU_DYNAMIC_STATE_VIEWPORT_RANGE, TU_DYNAMIC_STATE_LINE_MODE, TU_DYNAMIC_STATE_PROVOKING_VTX, + TU_DYNAMIC_STATE_BLEND_ENABLE, /* re-use the line width enum as it uses GRAS_SU_CNTL: */ TU_DYNAMIC_STATE_RAST = VK_DYNAMIC_STATE_LINE_WIDTH, };