From 8efa8971683f50a3b9473a0be7d2027f0465a6dd Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Mon, 17 May 2021 10:41:24 +0200 Subject: [PATCH] radv: implement dynamic logic op This is part of VK_EXT_extended_dynamic_state2. Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 39 +++++++++++++++++- src/amd/vulkan/radv_meta.c | 6 ++- src/amd/vulkan/radv_meta.h | 2 + src/amd/vulkan/radv_pipeline.c | 68 +++++++++----------------------- src/amd/vulkan/radv_private.h | 44 +++++++++++++++++++++ 5 files changed, 107 insertions(+), 52 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index cb4ca507c02..76f010773e1 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -115,6 +115,7 @@ const struct radv_dynamic_state default_dynamic_state = { .depth_bias_enable = 0u, .primitive_restart_enable = 0u, .rasterizer_discard_enable = 0u, + .logic_op = 0u, }; static void @@ -327,6 +328,13 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_dy } } + if (copy_mask & RADV_DYNAMIC_LOGIC_OP) { + if (dest->logic_op != src->logic_op) { + dest->logic_op = src->logic_op; + dest_mask |= RADV_DYNAMIC_LOGIC_OP; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1282,6 +1290,11 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) pipeline->graphics.pa_cl_clip_cntl) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE; + if (!cmd_buffer->state.emitted_pipeline || + cmd_buffer->state.emitted_pipeline->graphics.cb_color_control != + pipeline->graphics.cb_color_control) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP; + if (!cmd_buffer->state.emitted_pipeline) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY | RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | @@ -1598,6 +1611,18 @@ radv_emit_rasterizer_discard_enable(struct radv_cmd_buffer *cmd_buffer) radeon_set_context_reg(cmd_buffer->cs, R_028810_PA_CL_CLIP_CNTL, pa_cl_clip_cntl); } +static void +radv_emit_logic_op(struct radv_cmd_buffer *cmd_buffer) +{ + unsigned cb_color_control = cmd_buffer->state.pipeline->graphics.cb_color_control; + struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; + + cb_color_control &= C_028808_ROP3; + cb_color_control |= S_028808_ROP3(d->logic_op); + + radeon_set_context_reg(cmd_buffer->cs, R_028808_CB_COLOR_CONTROL, cb_color_control); +} + static void radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer, int index, struct radv_color_buffer_info *cb, struct radv_image_view *iview, @@ -2598,6 +2623,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) if (states & RADV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE) radv_emit_rasterizer_discard_enable(cmd_buffer); + if (states & RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP) + radv_emit_logic_op(cmd_buffer); + cmd_buffer->state.dirty &= ~states; } @@ -4765,7 +4793,16 @@ radv_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer, uint32_t patchCo void radv_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer, VkLogicOp logicOp) { - /* not implemented */ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + unsigned logic_op = si_translate_blend_logic_op(logicOp); + + if (state->dynamic.logic_op == logic_op) + return; + + state->dynamic.logic_op = logic_op; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP; } void diff --git a/src/amd/vulkan/radv_meta.c b/src/amd/vulkan/radv_meta.c index b54e4bd183c..bc3729e32e7 100644 --- a/src/amd/vulkan/radv_meta.c +++ b/src/amd/vulkan/radv_meta.c @@ -97,6 +97,8 @@ radv_meta_save(struct radv_meta_saved_state *state, struct radv_cmd_buffer *cmd_ state->primitive_restart_enable = cmd_buffer->state.dynamic.primitive_restart_enable; state->rasterizer_discard_enable = cmd_buffer->state.dynamic.rasterizer_discard_enable; + + state->logic_op = cmd_buffer->state.dynamic.logic_op; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { @@ -186,6 +188,8 @@ radv_meta_restore(const struct radv_meta_saved_state *state, struct radv_cmd_buf cmd_buffer->state.dynamic.rasterizer_discard_enable = state->rasterizer_discard_enable; + cmd_buffer->state.dynamic.logic_op = state->logic_op; + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_VIEWPORT | RADV_CMD_DIRTY_DYNAMIC_SCISSOR | RADV_CMD_DIRTY_DYNAMIC_CULL_MODE | RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE | @@ -195,7 +199,7 @@ radv_meta_restore(const struct radv_meta_saved_state *state, struct radv_cmd_buf RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP | RADV_CMD_DIRTY_DYNAMIC_FRAGMENT_SHADING_RATE | RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE | RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE | - RADV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE; + RADV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE | RADV_CMD_DIRTY_DYNAMIC_LOGIC_OP; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { diff --git a/src/amd/vulkan/radv_meta.h b/src/amd/vulkan/radv_meta.h index d04da9d3a2b..da9c00441e1 100644 --- a/src/amd/vulkan/radv_meta.h +++ b/src/amd/vulkan/radv_meta.h @@ -94,6 +94,8 @@ struct radv_meta_saved_state { bool depth_bias_enable; bool primitive_restart_enable; bool rasterizer_discard_enable; + + unsigned logic_op; }; VkResult radv_device_init_meta_clear_state(struct radv_device *device, bool on_demand); diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index a8b028a568a..3ff3161438d 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -51,7 +51,6 @@ struct radv_blend_state { uint32_t blend_enable_4bit; uint32_t need_src_alpha; - uint32_t cb_color_control; uint32_t cb_target_mask; uint32_t cb_target_enabled_4bit; uint32_t sx_mrt_blend_opt[8]; @@ -275,47 +274,6 @@ radv_pipeline_init_scratch(const struct radv_device *device, struct radv_pipelin pipeline->max_waves = max_waves; } -static uint32_t -si_translate_blend_logic_op(VkLogicOp op) -{ - switch (op) { - case VK_LOGIC_OP_CLEAR: - return V_028808_ROP3_CLEAR; - case VK_LOGIC_OP_AND: - return V_028808_ROP3_AND; - case VK_LOGIC_OP_AND_REVERSE: - return V_028808_ROP3_AND_REVERSE; - case VK_LOGIC_OP_COPY: - return V_028808_ROP3_COPY; - case VK_LOGIC_OP_AND_INVERTED: - return V_028808_ROP3_AND_INVERTED; - case VK_LOGIC_OP_NO_OP: - return V_028808_ROP3_NO_OP; - case VK_LOGIC_OP_XOR: - return V_028808_ROP3_XOR; - case VK_LOGIC_OP_OR: - return V_028808_ROP3_OR; - case VK_LOGIC_OP_NOR: - return V_028808_ROP3_NOR; - case VK_LOGIC_OP_EQUIVALENT: - return V_028808_ROP3_EQUIVALENT; - case VK_LOGIC_OP_INVERT: - return V_028808_ROP3_INVERT; - case VK_LOGIC_OP_OR_REVERSE: - return V_028808_ROP3_OR_REVERSE; - case VK_LOGIC_OP_COPY_INVERTED: - return V_028808_ROP3_COPY_INVERTED; - case VK_LOGIC_OP_OR_INVERTED: - return V_028808_ROP3_OR_INVERTED; - case VK_LOGIC_OP_NAND: - return V_028808_ROP3_NAND; - case VK_LOGIC_OP_SET: - return V_028808_ROP3_SET; - default: - unreachable("Unhandled logic op"); - } -} - static uint32_t si_translate_blend_function(VkBlendOp op) { @@ -656,7 +614,7 @@ radv_blend_check_commutativity(struct radv_blend_state *blend, VkBlendOp op, VkB } static struct radv_blend_state -radv_pipeline_init_blend_state(const struct radv_pipeline *pipeline, +radv_pipeline_init_blend_state(struct radv_pipeline *pipeline, const VkGraphicsPipelineCreateInfo *pCreateInfo, const struct radv_graphics_pipeline_create_info *extra) { @@ -666,6 +624,7 @@ radv_pipeline_init_blend_state(const struct radv_pipeline *pipeline, radv_pipeline_get_multisample_state(pCreateInfo); struct radv_blend_state blend = {0}; unsigned mode = V_028808_CB_NORMAL; + unsigned cb_color_control = 0; int i; if (extra && extra->custom_blend_mode) { @@ -673,12 +632,11 @@ radv_pipeline_init_blend_state(const struct radv_pipeline *pipeline, mode = extra->custom_blend_mode; } - blend.cb_color_control = 0; if (vkblend) { if (vkblend->logicOpEnable) - blend.cb_color_control |= S_028808_ROP3(si_translate_blend_logic_op(vkblend->logicOp)); + cb_color_control |= S_028808_ROP3(si_translate_blend_logic_op(vkblend->logicOp)); else - blend.cb_color_control |= S_028808_ROP3(V_028808_ROP3_COPY); + cb_color_control |= S_028808_ROP3(V_028808_ROP3_COPY); } blend.db_alpha_to_mask = S_028B70_ALPHA_TO_MASK_OFFSET0(3) | S_028B70_ALPHA_TO_MASK_OFFSET1(1) | @@ -819,15 +777,18 @@ radv_pipeline_init_blend_state(const struct radv_pipeline *pipeline, */ if (blend.mrt0_is_dual_src || (vkblend && vkblend->logicOpEnable) || mode == V_028808_CB_RESOLVE) - blend.cb_color_control |= S_028808_DISABLE_DUAL_QUAD(1); + cb_color_control |= S_028808_DISABLE_DUAL_QUAD(1); } if (blend.cb_target_mask) - blend.cb_color_control |= S_028808_MODE(mode); + cb_color_control |= S_028808_MODE(mode); else - blend.cb_color_control |= S_028808_MODE(V_028808_CB_DISABLE); + cb_color_control |= S_028808_MODE(V_028808_CB_DISABLE); radv_pipeline_compute_spi_color_formats(pipeline, pCreateInfo, &blend); + + pipeline->graphics.cb_color_control = cb_color_control; + return blend; } @@ -1760,6 +1721,14 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, pCreateInfo->pRasterizationState->rasterizerDiscardEnable; } + if (subpass->has_color_att && states & RADV_DYNAMIC_LOGIC_OP) { + if (pCreateInfo->pColorBlendState->logicOpEnable) { + dynamic->logic_op = si_translate_blend_logic_op(pCreateInfo->pColorBlendState->logicOp); + } else { + dynamic->logic_op = V_028808_ROP3_COPY; + } + } + pipeline->dynamic_state.mask = states; } @@ -4253,7 +4222,6 @@ radv_pipeline_generate_blend_state(struct radeon_cmdbuf *ctx_cs, { radeon_set_context_reg_seq(ctx_cs, R_028780_CB_BLEND0_CONTROL, 8); radeon_emit_array(ctx_cs, blend->cb_blend_control, 8); - radeon_set_context_reg(ctx_cs, R_028808_CB_COLOR_CONTROL, blend->cb_color_control); radeon_set_context_reg(ctx_cs, R_028B70_DB_ALPHA_TO_MASK, blend->db_alpha_to_mask); if (pipeline->device->physical_device->rad_info.has_rbplus) { diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index d9dd39ff3ff..e0917f1b6ec 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1229,6 +1229,8 @@ struct radv_dynamic_state { bool depth_bias_enable; bool primitive_restart_enable; bool rasterizer_discard_enable; + + unsigned logic_op; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -1750,6 +1752,7 @@ struct radv_pipeline { unsigned pa_su_sc_mode_cntl; unsigned db_depth_control; unsigned pa_cl_clip_cntl; + unsigned cb_color_control; bool uses_dynamic_stride; /* Used for rbplus */ @@ -2698,6 +2701,47 @@ si_translate_stencil_op(enum VkStencilOp op) } } +static inline uint32_t +si_translate_blend_logic_op(VkLogicOp op) +{ + switch (op) { + case VK_LOGIC_OP_CLEAR: + return V_028808_ROP3_CLEAR; + case VK_LOGIC_OP_AND: + return V_028808_ROP3_AND; + case VK_LOGIC_OP_AND_REVERSE: + return V_028808_ROP3_AND_REVERSE; + case VK_LOGIC_OP_COPY: + return V_028808_ROP3_COPY; + case VK_LOGIC_OP_AND_INVERTED: + return V_028808_ROP3_AND_INVERTED; + case VK_LOGIC_OP_NO_OP: + return V_028808_ROP3_NO_OP; + case VK_LOGIC_OP_XOR: + return V_028808_ROP3_XOR; + case VK_LOGIC_OP_OR: + return V_028808_ROP3_OR; + case VK_LOGIC_OP_NOR: + return V_028808_ROP3_NOR; + case VK_LOGIC_OP_EQUIVALENT: + return V_028808_ROP3_EQUIVALENT; + case VK_LOGIC_OP_INVERT: + return V_028808_ROP3_INVERT; + case VK_LOGIC_OP_OR_REVERSE: + return V_028808_ROP3_OR_REVERSE; + case VK_LOGIC_OP_COPY_INVERTED: + return V_028808_ROP3_COPY_INVERTED; + case VK_LOGIC_OP_OR_INVERTED: + return V_028808_ROP3_OR_INVERTED; + case VK_LOGIC_OP_NAND: + return V_028808_ROP3_NAND; + case VK_LOGIC_OP_SET: + return V_028808_ROP3_SET; + default: + unreachable("Unhandled logic op"); + } +} + /** * Helper used for debugging compiler issues by enabling/disabling LLVM for a * specific shader stage (developers only).