From 52bf1035a6ed00bfee5719798bfbee1f955b8903 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Mon, 13 Apr 2020 11:33:44 +0200 Subject: [PATCH] radv: add support for dynamic cull mode and front face Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 79 ++++++++++++++++++++++++++++++++ src/amd/vulkan/radv_meta.c | 10 +++- src/amd/vulkan/radv_meta.h | 3 ++ src/amd/vulkan/radv_pipeline.c | 34 ++++++++++---- src/amd/vulkan/radv_private.h | 4 ++ 5 files changed, 119 insertions(+), 11 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 723a94c8192..8ad1a86f5ce 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -96,6 +96,8 @@ const struct radv_dynamic_state default_dynamic_state = { .factor = 0u, .pattern = 0u, }, + .cull_mode = 0u, + .front_face = 0u, }; static void @@ -221,6 +223,20 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, } } + if (copy_mask & RADV_DYNAMIC_CULL_MODE) { + if (dest->cull_mode != src->cull_mode) { + dest->cull_mode = src->cull_mode; + dest_mask |= RADV_DYNAMIC_CULL_MODE; + } + } + + if (copy_mask & RADV_DYNAMIC_FRONT_FACE) { + if (dest->front_face != src->front_face) { + dest->front_face = src->front_face; + dest_mask |= RADV_DYNAMIC_FRONT_FACE; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1188,6 +1204,12 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) pipeline->graphics.can_use_guardband) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_SCISSOR; + if (!cmd_buffer->state.emitted_pipeline || + cmd_buffer->state.emitted_pipeline->graphics.pa_su_sc_mode_cntl != + pipeline->graphics.pa_su_sc_mode_cntl) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_CULL_MODE | + RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE; + radeon_emit_array(cmd_buffer->cs, pipeline->cs.buf, pipeline->cs.cdw); if (!cmd_buffer->state.emitted_pipeline || @@ -1338,6 +1360,29 @@ radv_emit_line_stipple(struct radv_cmd_buffer *cmd_buffer) S_028A0C_AUTO_RESET_CNTL(auto_reset_cntl)); } +static void +radv_emit_culling(struct radv_cmd_buffer *cmd_buffer, uint32_t states) +{ + unsigned pa_su_sc_mode_cntl = cmd_buffer->state.pipeline->graphics.pa_su_sc_mode_cntl; + struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; + + if (states & RADV_CMD_DIRTY_DYNAMIC_CULL_MODE) { + pa_su_sc_mode_cntl &= C_028814_CULL_FRONT; + pa_su_sc_mode_cntl |= S_028814_CULL_FRONT(!!(d->cull_mode & VK_CULL_MODE_FRONT_BIT)); + + pa_su_sc_mode_cntl &= C_028814_CULL_BACK; + pa_su_sc_mode_cntl |= S_028814_CULL_BACK(!!(d->cull_mode & VK_CULL_MODE_BACK_BIT)); + } + + if (states & RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE) { + pa_su_sc_mode_cntl &= C_028814_FACE; + pa_su_sc_mode_cntl |= S_028814_FACE(d->front_face); + } + + radeon_set_context_reg(cmd_buffer->cs, R_028814_PA_SU_SC_MODE_CNTL, + pa_su_sc_mode_cntl); +} + static void radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer, int index, @@ -2242,6 +2287,10 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) if (states & RADV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) radv_emit_line_stipple(cmd_buffer); + if (states & (RADV_CMD_DIRTY_DYNAMIC_CULL_MODE | + RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE)) + radv_emit_culling(cmd_buffer, states); + cmd_buffer->state.dirty &= ~states; } @@ -4191,6 +4240,36 @@ void radv_CmdSetLineStippleEXT( state->dirty |= RADV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE; } +void radv_CmdSetCullModeEXT( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.cull_mode == cullMode) + return; + + state->dynamic.cull_mode = cullMode; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_CULL_MODE; +} + +void radv_CmdSetFrontFaceEXT( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.front_face == frontFace) + return; + + state->dynamic.front_face = frontFace; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE; +} + void radv_CmdExecuteCommands( VkCommandBuffer commandBuffer, uint32_t commandBufferCount, diff --git a/src/amd/vulkan/radv_meta.c b/src/amd/vulkan/radv_meta.c index 1fb32f94621..2f56c92374c 100644 --- a/src/amd/vulkan/radv_meta.c +++ b/src/amd/vulkan/radv_meta.c @@ -62,6 +62,9 @@ radv_meta_save(struct radv_meta_saved_state *state, typed_memcpy(state->scissor.scissors, cmd_buffer->state.dynamic.scissor.scissors, MAX_SCISSORS); + + state->cull_mode = cmd_buffer->state.dynamic.cull_mode; + state->front_face = cmd_buffer->state.dynamic.front_face; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { @@ -123,8 +126,13 @@ radv_meta_restore(const struct radv_meta_saved_state *state, state->scissor.scissors, MAX_SCISSORS); + cmd_buffer->state.dynamic.cull_mode = state->cull_mode; + cmd_buffer->state.dynamic.front_face = state->front_face; + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_VIEWPORT | - RADV_CMD_DIRTY_DYNAMIC_SCISSOR; + RADV_CMD_DIRTY_DYNAMIC_SCISSOR | + RADV_CMD_DIRTY_DYNAMIC_CULL_MODE | + RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE; } 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 e3711aa4793..c3b4d9c72ea 100644 --- a/src/amd/vulkan/radv_meta.h +++ b/src/amd/vulkan/radv_meta.h @@ -58,6 +58,9 @@ struct radv_meta_saved_state { struct radv_attachment_state *attachments; struct radv_framebuffer *framebuffer; VkRect2D render_area; + + VkCullModeFlags cull_mode; + VkFrontFace front_face; }; 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 0c36fb7b96c..c03e0f43c75 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -1298,6 +1298,10 @@ static unsigned radv_dynamic_state_mask(VkDynamicState state) return RADV_DYNAMIC_SAMPLE_LOCATIONS; case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT: return RADV_DYNAMIC_LINE_STIPPLE; + case VK_DYNAMIC_STATE_CULL_MODE_EXT: + return RADV_DYNAMIC_CULL_MODE; + case VK_DYNAMIC_STATE_FRONT_FACE_EXT: + return RADV_DYNAMIC_FRONT_FACE; default: unreachable("Unhandled dynamic state"); } @@ -1412,6 +1416,16 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, pCreateInfo->pColorBlendState->blendConstants, 4); } + if (states & RADV_DYNAMIC_CULL_MODE) { + dynamic->cull_mode = + pCreateInfo->pRasterizationState->cullMode; + } + + if (states & RADV_DYNAMIC_FRONT_FACE) { + dynamic->front_face = + pCreateInfo->pRasterizationState->frontFace; + } + /* If there is no depthstencil attachment, then don't read * pDepthStencilState. The Vulkan spec states that pDepthStencilState may * be NULL in this case. Even if pDepthStencilState is non-NULL, there is @@ -3692,16 +3706,16 @@ radv_pipeline_generate_raster_state(struct radeon_cmdbuf *ctx_cs, S_028BE4_ROUND_MODE(V_028BE4_X_ROUND_TO_EVEN) | S_028BE4_QUANT_MODE(V_028BE4_X_16_8_FIXED_POINT_1_256TH)); - radeon_set_context_reg(ctx_cs, R_028814_PA_SU_SC_MODE_CNTL, - S_028814_FACE(vkraster->frontFace) | - S_028814_CULL_FRONT(!!(vkraster->cullMode & VK_CULL_MODE_FRONT_BIT)) | - S_028814_CULL_BACK(!!(vkraster->cullMode & VK_CULL_MODE_BACK_BIT)) | - S_028814_POLY_MODE(vkraster->polygonMode != VK_POLYGON_MODE_FILL) | - S_028814_POLYMODE_FRONT_PTYPE(si_translate_fill(vkraster->polygonMode)) | - S_028814_POLYMODE_BACK_PTYPE(si_translate_fill(vkraster->polygonMode)) | - S_028814_POLY_OFFSET_FRONT_ENABLE(vkraster->depthBiasEnable ? 1 : 0) | - S_028814_POLY_OFFSET_BACK_ENABLE(vkraster->depthBiasEnable ? 1 : 0) | - S_028814_POLY_OFFSET_PARA_ENABLE(vkraster->depthBiasEnable ? 1 : 0)); + pipeline->graphics.pa_su_sc_mode_cntl = + S_028814_FACE(vkraster->frontFace) | + S_028814_CULL_FRONT(!!(vkraster->cullMode & VK_CULL_MODE_FRONT_BIT)) | + S_028814_CULL_BACK(!!(vkraster->cullMode & VK_CULL_MODE_BACK_BIT)) | + S_028814_POLY_MODE(vkraster->polygonMode != VK_POLYGON_MODE_FILL) | + S_028814_POLYMODE_FRONT_PTYPE(si_translate_fill(vkraster->polygonMode)) | + S_028814_POLYMODE_BACK_PTYPE(si_translate_fill(vkraster->polygonMode)) | + S_028814_POLY_OFFSET_FRONT_ENABLE(vkraster->depthBiasEnable ? 1 : 0) | + S_028814_POLY_OFFSET_BACK_ENABLE(vkraster->depthBiasEnable ? 1 : 0) | + S_028814_POLY_OFFSET_PARA_ENABLE(vkraster->depthBiasEnable ? 1 : 0); /* Conservative rasterization. */ if (mode != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT) { diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 6903af4255f..6286a67962a 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1132,6 +1132,9 @@ struct radv_dynamic_state { uint32_t factor; uint16_t pattern; } line_stipple; + + VkCullModeFlags cull_mode; + VkFrontFace front_face; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -1650,6 +1653,7 @@ struct radv_pipeline { bool disable_out_of_order_rast_for_occlusion; uint8_t topology; unsigned tess_patch_control_points; + unsigned pa_su_sc_mode_cntl; /* Used for rbplus */ uint32_t col_format; -- 2.30.2