[Mesa-dev] [PATCH 2/2] radv: avoid PS partial flushes when viewports/scissors don't change

Samuel Pitoiset samuel.pitoiset at gmail.com
Fri Jan 5 17:26:12 UTC 2018


For Vega10 and Raven that need a special workaround for the
scissor bug.

This seems to give a minor boost for Talos and Dota 2, at least.

To reduce the cost of memcmp, the driver checks if it's
really useful to do the comparison.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
 src/amd/vulkan/radv_cmd_buffer.c | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c
index 665ee876a9..d8f780cfd7 100644
--- a/src/amd/vulkan/radv_cmd_buffer.c
+++ b/src/amd/vulkan/radv_cmd_buffer.c
@@ -2733,15 +2733,28 @@ void radv_CmdSetViewport(
 	const VkViewport*                           pViewports)
 {
 	RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
+	struct radv_cmd_state *state = &cmd_buffer->state;
 	MAYBE_UNUSED const uint32_t total_count = firstViewport + viewportCount;
 
 	assert(firstViewport < MAX_VIEWPORTS);
 	assert(total_count >= 1 && total_count <= MAX_VIEWPORTS);
 
-	memcpy(cmd_buffer->state.dynamic.viewport.viewports + firstViewport,
-	       pViewports, viewportCount * sizeof(*pViewports));
+	if (cmd_buffer->device->physical_device->has_scissor_bug) {
+		/* Try to skip unnecessary PS partial flushes when the viewports
+		 * don't change.
+		 */
+		if (!(state->dirty & (RADV_CMD_DIRTY_DYNAMIC_VIEWPORT |
+				      RADV_CMD_DIRTY_DYNAMIC_SCISSOR)) &&
+		    !memcmp(state->dynamic.viewport.viewports + firstViewport,
+			    pViewports, viewportCount * sizeof(*pViewports))) {
+			return;
+		}
+	}
+
+	memcpy(state->dynamic.viewport.viewports + firstViewport, pViewports,
+	       viewportCount * sizeof(*pViewports));
 
-	cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_VIEWPORT;
+	state->dirty |= RADV_CMD_DIRTY_DYNAMIC_VIEWPORT;
 }
 
 void radv_CmdSetScissor(
@@ -2751,14 +2764,28 @@ void radv_CmdSetScissor(
 	const VkRect2D*                             pScissors)
 {
 	RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
+	struct radv_cmd_state *state = &cmd_buffer->state;
 	MAYBE_UNUSED const uint32_t total_count = firstScissor + scissorCount;
 
 	assert(firstScissor < MAX_SCISSORS);
 	assert(total_count >= 1 && total_count <= MAX_SCISSORS);
 
-	memcpy(cmd_buffer->state.dynamic.scissor.scissors + firstScissor,
-	       pScissors, scissorCount * sizeof(*pScissors));
-	cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_SCISSOR;
+	if (cmd_buffer->device->physical_device->has_scissor_bug) {
+		/* Try to skip unnecessary PS partial flushes when the scissors
+		 * don't change.
+		 */
+		if (!(state->dirty & (RADV_CMD_DIRTY_DYNAMIC_VIEWPORT |
+				      RADV_CMD_DIRTY_DYNAMIC_SCISSOR)) &&
+		    !memcmp(state->dynamic.scissor.scissors + firstScissor,
+			    pScissors, scissorCount * sizeof(*pScissors))) {
+			return;
+		}
+	}
+
+	memcpy(state->dynamic.scissor.scissors + firstScissor, pScissors,
+	       scissorCount * sizeof(*pScissors));
+
+	state->dirty |= RADV_CMD_DIRTY_DYNAMIC_SCISSOR;
 }
 
 void radv_CmdSetLineWidth(
-- 
2.15.1



More information about the mesa-dev mailing list