From 9cc99baa4ad64685d8f24683613d836706713366 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Mon, 13 Apr 2020 14:47:08 +0200 Subject: [PATCH] radv: add support for dynamic depth/stencil states Out-of-order rasterization is disabled if a pipeline uses an extended dynamic depth/stencil state because the driver doesn't support enabling/disabling out-of-order dynamically. Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 245 +++++++++++++++++++++++++++++++ src/amd/vulkan/radv_meta.c | 40 ++++- src/amd/vulkan/radv_meta.h | 22 +++ src/amd/vulkan/radv_pipeline.c | 125 +++++++++++----- src/amd/vulkan/radv_private.h | 47 ++++++ 5 files changed, 444 insertions(+), 35 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 9723c28f7cc..91b1b0f2d80 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -253,6 +253,49 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, } } + if (copy_mask & RADV_DYNAMIC_DEPTH_TEST_ENABLE) { + if (dest->depth_test_enable != src->depth_test_enable) { + dest->depth_test_enable = src->depth_test_enable; + dest_mask |= RADV_DYNAMIC_DEPTH_TEST_ENABLE; + } + } + + if (copy_mask & RADV_DYNAMIC_DEPTH_WRITE_ENABLE) { + if (dest->depth_write_enable != src->depth_write_enable) { + dest->depth_write_enable = src->depth_write_enable; + dest_mask |= RADV_DYNAMIC_DEPTH_WRITE_ENABLE; + } + } + + if (copy_mask & RADV_DYNAMIC_DEPTH_COMPARE_OP) { + if (dest->depth_compare_op != src->depth_compare_op) { + dest->depth_compare_op = src->depth_compare_op; + dest_mask |= RADV_DYNAMIC_DEPTH_COMPARE_OP; + } + } + + if (copy_mask & RADV_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE) { + if (dest->depth_bounds_test_enable != src->depth_bounds_test_enable) { + dest->depth_bounds_test_enable = src->depth_bounds_test_enable; + dest_mask |= RADV_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE; + } + } + + if (copy_mask & RADV_DYNAMIC_STENCIL_TEST_ENABLE) { + if (dest->stencil_test_enable != src->stencil_test_enable) { + dest->stencil_test_enable = src->stencil_test_enable; + dest_mask |= RADV_DYNAMIC_STENCIL_TEST_ENABLE; + } + } + + if (copy_mask & RADV_DYNAMIC_STENCIL_OP) { + if (memcmp(&dest->stencil_op, &src->stencil_op, + sizeof(src->stencil_op))) { + dest->stencil_op = src->stencil_op; + dest_mask |= RADV_DYNAMIC_STENCIL_OP; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1229,6 +1272,19 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) if (!cmd_buffer->state.emitted_pipeline) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; + if (!cmd_buffer->state.emitted_pipeline || + cmd_buffer->state.emitted_pipeline->graphics.db_depth_control != + pipeline->graphics.db_depth_control) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP; + + if (!cmd_buffer->state.emitted_pipeline) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP; + radeon_emit_array(cmd_buffer->cs, pipeline->cs.buf, pipeline->cs.cdw); if (!cmd_buffer->state.emitted_pipeline || @@ -1418,6 +1474,66 @@ radv_emit_primitive_topology(struct radv_cmd_buffer *cmd_buffer) } } +static void +radv_emit_depth_control(struct radv_cmd_buffer *cmd_buffer, uint32_t states) +{ + unsigned db_depth_control = cmd_buffer->state.pipeline->graphics.db_depth_control; + struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; + + if (states & RADV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE) { + db_depth_control &= C_028800_Z_ENABLE; + db_depth_control |= S_028800_Z_ENABLE(d->depth_test_enable ? 1 : 0); + } + + if (states & RADV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE) { + db_depth_control &= C_028800_Z_WRITE_ENABLE; + db_depth_control |= S_028800_Z_WRITE_ENABLE(d->depth_write_enable ? 1 : 0); + } + + if (states & RADV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP) { + db_depth_control &= C_028800_ZFUNC; + db_depth_control |= S_028800_ZFUNC(d->depth_compare_op); + } + + if (states & RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE) { + db_depth_control &= C_028800_DEPTH_BOUNDS_ENABLE; + db_depth_control |= S_028800_DEPTH_BOUNDS_ENABLE(d->depth_bounds_test_enable ? 1 : 0); + } + + if (states & RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE) { + db_depth_control &= C_028800_STENCIL_ENABLE; + db_depth_control |= S_028800_STENCIL_ENABLE(d->stencil_test_enable ? 1 : 0); + + db_depth_control &= C_028800_BACKFACE_ENABLE; + db_depth_control |= S_028800_BACKFACE_ENABLE(d->stencil_test_enable ? 1 : 0); + } + + if (states & RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP) { + db_depth_control &= C_028800_STENCILFUNC; + db_depth_control |= S_028800_STENCILFUNC(d->stencil_op.front.compare_op); + + db_depth_control &= C_028800_STENCILFUNC_BF; + db_depth_control |= S_028800_STENCILFUNC_BF(d->stencil_op.back.compare_op); + } + + radeon_set_context_reg(cmd_buffer->cs, R_028800_DB_DEPTH_CONTROL, + db_depth_control); +} + +static void +radv_emit_stencil_control(struct radv_cmd_buffer *cmd_buffer) +{ + struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; + + radeon_set_context_reg(cmd_buffer->cs, R_02842C_DB_STENCIL_CONTROL, + S_02842C_STENCILFAIL(si_translate_stencil_op(d->stencil_op.front.fail_op)) | + S_02842C_STENCILZPASS(si_translate_stencil_op(d->stencil_op.front.pass_op)) | + S_02842C_STENCILZFAIL(si_translate_stencil_op(d->stencil_op.front.depth_fail_op)) | + S_02842C_STENCILFAIL_BF(si_translate_stencil_op(d->stencil_op.back.fail_op)) | + S_02842C_STENCILZPASS_BF(si_translate_stencil_op(d->stencil_op.back.pass_op)) | + S_02842C_STENCILZFAIL_BF(si_translate_stencil_op(d->stencil_op.back.depth_fail_op))); +} + static void radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer, int index, @@ -2329,6 +2445,17 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) if (states & RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) radv_emit_primitive_topology(cmd_buffer); + if (states & (RADV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP)) + radv_emit_depth_control(cmd_buffer, states); + + if (states & RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP) + radv_emit_stencil_control(cmd_buffer); + cmd_buffer->state.dirty &= ~states; } @@ -4342,6 +4469,124 @@ void radv_CmdSetScissorWithCountEXT( radv_CmdSetScissor(commandBuffer, 0, scissorCount, pScissors); } +void radv_CmdSetDepthTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable) + +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.depth_test_enable == depthTestEnable) + return; + + state->dynamic.depth_test_enable = depthTestEnable; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE; +} + +void radv_CmdSetDepthWriteEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.depth_write_enable == depthWriteEnable) + return; + + state->dynamic.depth_write_enable = depthWriteEnable; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE; +} + +void radv_CmdSetDepthCompareOpEXT( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.depth_compare_op == depthCompareOp) + return; + + state->dynamic.depth_compare_op = depthCompareOp; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP; +} + +void radv_CmdSetDepthBoundsTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.depth_bounds_test_enable == depthBoundsTestEnable) + return; + + state->dynamic.depth_bounds_test_enable = depthBoundsTestEnable; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE; +} + +void radv_CmdSetStencilTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.stencil_test_enable == stencilTestEnable) + return; + + state->dynamic.stencil_test_enable = stencilTestEnable; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE; +} + +void radv_CmdSetStencilOpEXT( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + bool front_same = + state->dynamic.stencil_op.front.fail_op == failOp && + state->dynamic.stencil_op.front.pass_op == passOp && + state->dynamic.stencil_op.front.depth_fail_op == depthFailOp && + state->dynamic.stencil_op.front.compare_op == compareOp; + bool back_same = + state->dynamic.stencil_op.back.fail_op == failOp && + state->dynamic.stencil_op.back.pass_op == passOp && + state->dynamic.stencil_op.back.depth_fail_op == depthFailOp && + state->dynamic.stencil_op.back.compare_op == compareOp; + + if ((!(faceMask & VK_STENCIL_FACE_FRONT_BIT) || front_same) && + (!(faceMask & VK_STENCIL_FACE_BACK_BIT) || back_same)) + return; + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) { + state->dynamic.stencil_op.front.fail_op = failOp; + state->dynamic.stencil_op.front.pass_op = passOp; + state->dynamic.stencil_op.front.depth_fail_op = depthFailOp; + state->dynamic.stencil_op.front.compare_op = compareOp; + } + + if (faceMask & VK_STENCIL_FACE_BACK_BIT) { + state->dynamic.stencil_op.back.fail_op = failOp; + state->dynamic.stencil_op.back.pass_op = passOp; + state->dynamic.stencil_op.back.depth_fail_op = depthFailOp; + state->dynamic.stencil_op.back.compare_op = compareOp; + } + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP; +} + 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 0b482b51b2c..596a0e7ea1c 100644 --- a/src/amd/vulkan/radv_meta.c +++ b/src/amd/vulkan/radv_meta.c @@ -67,6 +67,22 @@ radv_meta_save(struct radv_meta_saved_state *state, state->front_face = cmd_buffer->state.dynamic.front_face; state->primitive_topology = cmd_buffer->state.dynamic.primitive_topology; + + state->depth_test_enable = cmd_buffer->state.dynamic.depth_test_enable; + state->depth_write_enable = cmd_buffer->state.dynamic.depth_write_enable; + state->depth_compare_op = cmd_buffer->state.dynamic.depth_compare_op; + state->depth_bounds_test_enable = cmd_buffer->state.dynamic.depth_bounds_test_enable; + state->stencil_test_enable = cmd_buffer->state.dynamic.stencil_test_enable; + + state->stencil_op.front.compare_op = cmd_buffer->state.dynamic.stencil_op.front.compare_op; + state->stencil_op.front.fail_op = cmd_buffer->state.dynamic.stencil_op.front.fail_op; + state->stencil_op.front.pass_op = cmd_buffer->state.dynamic.stencil_op.front.pass_op; + state->stencil_op.front.depth_fail_op = cmd_buffer->state.dynamic.stencil_op.front.depth_fail_op; + + state->stencil_op.back.compare_op = cmd_buffer->state.dynamic.stencil_op.back.compare_op; + state->stencil_op.back.fail_op = cmd_buffer->state.dynamic.stencil_op.back.fail_op; + state->stencil_op.back.pass_op = cmd_buffer->state.dynamic.stencil_op.back.pass_op; + state->stencil_op.back.depth_fail_op = cmd_buffer->state.dynamic.stencil_op.back.depth_fail_op; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { @@ -133,11 +149,33 @@ radv_meta_restore(const struct radv_meta_saved_state *state, cmd_buffer->state.dynamic.primitive_topology = state->primitive_topology; + cmd_buffer->state.dynamic.depth_test_enable = state->depth_test_enable; + cmd_buffer->state.dynamic.depth_write_enable = state->depth_write_enable; + cmd_buffer->state.dynamic.depth_compare_op = state->depth_compare_op; + cmd_buffer->state.dynamic.depth_bounds_test_enable = state->depth_bounds_test_enable; + cmd_buffer->state.dynamic.stencil_test_enable = state->stencil_test_enable; + + cmd_buffer->state.dynamic.stencil_op.front.compare_op = state->stencil_op.front.compare_op; + cmd_buffer->state.dynamic.stencil_op.front.fail_op = state->stencil_op.front.fail_op; + cmd_buffer->state.dynamic.stencil_op.front.pass_op = state->stencil_op.front.pass_op; + cmd_buffer->state.dynamic.stencil_op.front.depth_fail_op = state->stencil_op.front.depth_fail_op; + + cmd_buffer->state.dynamic.stencil_op.back.compare_op = state->stencil_op.back.compare_op; + cmd_buffer->state.dynamic.stencil_op.back.fail_op = state->stencil_op.back.fail_op; + cmd_buffer->state.dynamic.stencil_op.back.pass_op = state->stencil_op.back.pass_op; + cmd_buffer->state.dynamic.stencil_op.back.depth_fail_op = state->stencil_op.back.depth_fail_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 | - RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; + RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | + RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_STENCIL_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 cd4d1d64f63..c6f63f76e44 100644 --- a/src/amd/vulkan/radv_meta.h +++ b/src/amd/vulkan/radv_meta.h @@ -63,6 +63,28 @@ struct radv_meta_saved_state { VkFrontFace front_face; unsigned primitive_topology; + + bool depth_test_enable; + bool depth_write_enable; + unsigned depth_compare_op; + bool depth_bounds_test_enable; + bool stencil_test_enable; + + struct { + struct { + VkStencilOp fail_op; + VkStencilOp pass_op; + VkStencilOp depth_fail_op; + VkCompareOp compare_op; + } front; + + struct { + VkStencilOp fail_op; + VkStencilOp pass_op; + VkStencilOp depth_fail_op; + VkCompareOp compare_op; + } back; + } stencil_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 00303b0627a..ea1f92891ea 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -814,30 +814,6 @@ radv_pipeline_init_blend_state(struct radv_pipeline *pipeline, return blend; } -static uint32_t si_translate_stencil_op(enum VkStencilOp op) -{ - switch (op) { - case VK_STENCIL_OP_KEEP: - return V_02842C_STENCIL_KEEP; - case VK_STENCIL_OP_ZERO: - return V_02842C_STENCIL_ZERO; - case VK_STENCIL_OP_REPLACE: - return V_02842C_STENCIL_REPLACE_TEST; - case VK_STENCIL_OP_INCREMENT_AND_CLAMP: - return V_02842C_STENCIL_ADD_CLAMP; - case VK_STENCIL_OP_DECREMENT_AND_CLAMP: - return V_02842C_STENCIL_SUB_CLAMP; - case VK_STENCIL_OP_INVERT: - return V_02842C_STENCIL_INVERT; - case VK_STENCIL_OP_INCREMENT_AND_WRAP: - return V_02842C_STENCIL_ADD_WRAP; - case VK_STENCIL_OP_DECREMENT_AND_WRAP: - return V_02842C_STENCIL_SUB_WRAP; - default: - return 0; - } -} - static uint32_t si_translate_fill(VkPolygonMode func) { switch(func) { @@ -943,6 +919,30 @@ radv_order_invariant_stencil_state(const VkStencilOpState *state) radv_order_invariant_stencil_op(state->failOp)); } +static bool +radv_pipeline_has_dynamic_ds_states(const VkGraphicsPipelineCreateInfo *pCreateInfo) +{ + VkDynamicState ds_states[] = { + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT, + VK_DYNAMIC_STATE_STENCIL_OP_EXT, + }; + + if (pCreateInfo->pDynamicState) { + uint32_t count = pCreateInfo->pDynamicState->dynamicStateCount; + for (uint32_t i = 0; i < count; i++) { + for (uint32_t j = 0; j < ARRAY_SIZE(ds_states); j++) { + if (pCreateInfo->pDynamicState->pDynamicStates[i] == ds_states[j]) + return true; + } + } + } + + return false; +} + static bool radv_pipeline_out_of_order_rast(struct radv_pipeline *pipeline, struct radv_blend_state *blend, @@ -961,6 +961,13 @@ radv_pipeline_out_of_order_rast(struct radv_pipeline *pipeline, if (colormask && vkblend && vkblend->logicOpEnable) return false; + /* Be conservative if an extended dynamic depth/stencil state is + * enabled because the driver can't update out-of-order rasterization + * dynamically. + */ + if (radv_pipeline_has_dynamic_ds_states(pCreateInfo)) + return false; + /* Default depth/stencil invariance when no attachment is bound. */ struct radv_dsa_order_invariance dsa_order_invariant = { .zs = true, .pass_set = true @@ -1274,6 +1281,18 @@ static unsigned radv_dynamic_state_mask(VkDynamicState state) return RADV_DYNAMIC_FRONT_FACE; case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT: return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY; + case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT: + return RADV_DYNAMIC_DEPTH_TEST_ENABLE; + case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT: + return RADV_DYNAMIC_DEPTH_WRITE_ENABLE; + case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT: + return RADV_DYNAMIC_DEPTH_COMPARE_OP; + case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT: + return RADV_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE; + case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT: + return RADV_DYNAMIC_STENCIL_TEST_ENABLE; + case VK_DYNAMIC_STATE_STENCIL_OP_EXT: + return RADV_DYNAMIC_STENCIL_OP; default: unreachable("Unhandled dynamic state"); } @@ -1451,6 +1470,51 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, dynamic->stencil_reference.back = pCreateInfo->pDepthStencilState->back.reference; } + + if (states & RADV_DYNAMIC_DEPTH_TEST_ENABLE) { + dynamic->depth_test_enable = + pCreateInfo->pDepthStencilState->depthTestEnable; + } + + if (states & RADV_DYNAMIC_DEPTH_WRITE_ENABLE) { + dynamic->depth_write_enable = + pCreateInfo->pDepthStencilState->depthWriteEnable; + } + + if (states & RADV_DYNAMIC_DEPTH_COMPARE_OP) { + dynamic->depth_compare_op = + pCreateInfo->pDepthStencilState->depthCompareOp; + } + + if (states & RADV_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE) { + dynamic->depth_bounds_test_enable = + pCreateInfo->pDepthStencilState->depthBoundsTestEnable; + } + + if (states & RADV_DYNAMIC_STENCIL_TEST_ENABLE) { + dynamic->stencil_test_enable = + pCreateInfo->pDepthStencilState->stencilTestEnable; + } + + if (states & RADV_DYNAMIC_STENCIL_OP) { + dynamic->stencil_op.front.compare_op = + pCreateInfo->pDepthStencilState->front.compareOp; + dynamic->stencil_op.front.fail_op = + pCreateInfo->pDepthStencilState->front.failOp; + dynamic->stencil_op.front.pass_op = + pCreateInfo->pDepthStencilState->front.passOp; + dynamic->stencil_op.front.depth_fail_op = + pCreateInfo->pDepthStencilState->front.depthFailOp; + + dynamic->stencil_op.back.compare_op = + pCreateInfo->pDepthStencilState->back.compareOp; + dynamic->stencil_op.back.fail_op = + pCreateInfo->pDepthStencilState->back.failOp; + dynamic->stencil_op.back.pass_op = + pCreateInfo->pDepthStencilState->back.passOp; + dynamic->stencil_op.back.depth_fail_op = + pCreateInfo->pDepthStencilState->back.depthFailOp; + } } const VkPipelineDiscardRectangleStateCreateInfoEXT *discard_rectangle_info = @@ -3541,7 +3605,7 @@ radv_pipeline_generate_depth_stencil_state(struct radeon_cmdbuf *ctx_cs, struct radv_subpass *subpass = pass->subpasses + pCreateInfo->subpass; struct radv_shader_variant *ps = pipeline->shaders[MESA_SHADER_FRAGMENT]; struct radv_render_pass_attachment *attachment = NULL; - uint32_t db_depth_control = 0, db_stencil_control = 0; + uint32_t db_depth_control = 0; uint32_t db_render_control = 0, db_render_override2 = 0; uint32_t db_render_override = 0; @@ -3567,14 +3631,8 @@ radv_pipeline_generate_depth_stencil_state(struct radeon_cmdbuf *ctx_cs, if (has_stencil_attachment && vkds && vkds->stencilTestEnable) { db_depth_control |= S_028800_STENCIL_ENABLE(1) | S_028800_BACKFACE_ENABLE(1); db_depth_control |= S_028800_STENCILFUNC(vkds->front.compareOp); - db_stencil_control |= S_02842C_STENCILFAIL(si_translate_stencil_op(vkds->front.failOp)); - db_stencil_control |= S_02842C_STENCILZPASS(si_translate_stencil_op(vkds->front.passOp)); - db_stencil_control |= S_02842C_STENCILZFAIL(si_translate_stencil_op(vkds->front.depthFailOp)); db_depth_control |= S_028800_STENCILFUNC_BF(vkds->back.compareOp); - db_stencil_control |= S_02842C_STENCILFAIL_BF(si_translate_stencil_op(vkds->back.failOp)); - db_stencil_control |= S_02842C_STENCILZPASS_BF(si_translate_stencil_op(vkds->back.passOp)); - db_stencil_control |= S_02842C_STENCILZFAIL_BF(si_translate_stencil_op(vkds->back.depthFailOp)); } if (attachment && extra) { @@ -3606,12 +3664,11 @@ radv_pipeline_generate_depth_stencil_state(struct radeon_cmdbuf *ctx_cs, db_render_override |= S_02800C_DISABLE_VIEWPORT_CLAMP(1); } - radeon_set_context_reg(ctx_cs, R_028800_DB_DEPTH_CONTROL, db_depth_control); - radeon_set_context_reg(ctx_cs, R_02842C_DB_STENCIL_CONTROL, db_stencil_control); - radeon_set_context_reg(ctx_cs, R_028000_DB_RENDER_CONTROL, db_render_control); radeon_set_context_reg(ctx_cs, R_02800C_DB_RENDER_OVERRIDE, db_render_override); radeon_set_context_reg(ctx_cs, R_028010_DB_RENDER_OVERRIDE2, db_render_override2); + + pipeline->graphics.db_depth_control = db_depth_control; } static void diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index bc6a46c5aa5..359110eeec2 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1119,6 +1119,22 @@ struct radv_dynamic_state { uint32_t back; } stencil_write_mask; + struct { + struct { + VkStencilOp fail_op; + VkStencilOp pass_op; + VkStencilOp depth_fail_op; + VkCompareOp compare_op; + } front; + + struct { + VkStencilOp fail_op; + VkStencilOp pass_op; + VkStencilOp depth_fail_op; + VkCompareOp compare_op; + } back; + } stencil_op; + struct { uint32_t front; uint32_t back; @@ -1136,6 +1152,12 @@ struct radv_dynamic_state { VkCullModeFlags cull_mode; VkFrontFace front_face; unsigned primitive_topology; + + bool depth_test_enable; + bool depth_write_enable; + VkCompareOp depth_compare_op; + bool depth_bounds_test_enable; + bool stencil_test_enable; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -1655,6 +1677,7 @@ struct radv_pipeline { bool disable_out_of_order_rast_for_occlusion; unsigned tess_patch_control_points; unsigned pa_su_sc_mode_cntl; + unsigned db_depth_control; /* Used for rbplus */ uint32_t col_format; @@ -2522,6 +2545,30 @@ static inline uint32_t si_translate_prim(unsigned topology) } } +static inline uint32_t si_translate_stencil_op(enum VkStencilOp op) +{ + switch (op) { + case VK_STENCIL_OP_KEEP: + return V_02842C_STENCIL_KEEP; + case VK_STENCIL_OP_ZERO: + return V_02842C_STENCIL_ZERO; + case VK_STENCIL_OP_REPLACE: + return V_02842C_STENCIL_REPLACE_TEST; + case VK_STENCIL_OP_INCREMENT_AND_CLAMP: + return V_02842C_STENCIL_ADD_CLAMP; + case VK_STENCIL_OP_DECREMENT_AND_CLAMP: + return V_02842C_STENCIL_SUB_CLAMP; + case VK_STENCIL_OP_INVERT: + return V_02842C_STENCIL_INVERT; + case VK_STENCIL_OP_INCREMENT_AND_WRAP: + return V_02842C_STENCIL_ADD_WRAP; + case VK_STENCIL_OP_DECREMENT_AND_WRAP: + return V_02842C_STENCIL_SUB_WRAP; + default: + return 0; + } +} + #define RADV_DEFINE_HANDLE_CASTS(__radv_type, __VkType) \ \ static inline struct __radv_type * \ -- 2.30.2