radv: add support for dynamic depth/stencil states
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 13 Apr 2020 12:47:08 +0000 (14:47 +0200)
committerMarge Bot <eric+marge@anholt.net>
Mon, 13 Jul 2020 08:31:54 +0000 (08:31 +0000)
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 <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5718>

src/amd/vulkan/radv_cmd_buffer.c
src/amd/vulkan/radv_meta.c
src/amd/vulkan/radv_meta.h
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_private.h

index 9723c28f7cc603398e6ca0ed661bd2340e048663..91b1b0f2d805cd68c91d83069c4e1c5c8ab59122 100644 (file)
@@ -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,
index 0b482b51b2c419a13f502427db5212f8b3d581e2..596a0e7ea1cfe77e8ed01ff00eefbdba19ba93c5 100644 (file)
@@ -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) {
index cd4d1d64f6337693642ed71e8eea2c9db8993c92..c6f63f76e44e6de69403649ae518d7065489b838 100644 (file)
@@ -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);
index 00303b0627aa51f956c99326898cfe5186cd47b4..ea1f92891eabc69599d893a1455883e08c41b74c 100644 (file)
@@ -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
index bc6a46c5aa5e4c30acebb914ab908279b73ae03f..359110eeec2288331519c0fede5e115f3e67afdb 100644 (file)
@@ -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 *                      \