Mesa (master): radv: add support for dynamic depth/stencil states

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jul 13 08:45:58 UTC 2020


Module: Mesa
Branch: master
Commit: 9cc99baa4ad64685d8f24683613d836706713366
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9cc99baa4ad64685d8f24683613d836706713366

Author: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Date:   Mon Apr 13 14:47:08 2020 +0200

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 <samuel.pitoiset at gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5718>

---

 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 *			\



More information about the mesa-commit mailing list