summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Antognolli <[email protected]>2019-08-19 17:01:10 -0700
committerRafael Antognolli <[email protected]>2019-08-23 15:55:18 -0700
commit2b7ba9f239c09049408d86eb71be18887691dc58 (patch)
treeb3cb50c39caf8954fd435cc825b5c184e8b8fc1c
parent21a85fd7d8c56aae2f6dd3862900f4d8597eac8e (diff)
anv: Only re-emit non-dynamic state that has changed.
On commit f6e7de41d7b, we started emitting 3DSTATE_LINE_STIPPLE as part of the non-dynamic state. That gets re-emitted every time we bind a new VkPipeline. But that instruction is non-pipelined, and it caused a perf regression of about 9-10% on Dota2. This commit makes anv_dynamic_state_copy() return a mask with only the state that has changed when copying it. 3DSTATE_LINE_STIPPLE won't be emitted anymore unless it has changed, fixing the problem above. v2: Improve commit message and add documentation about skipped checks (Jason) Fixes: f6e7de41d7b ("anv: Implement VK_EXT_line_rasterization") Reviewed-by: Jason Ekstrand <[email protected]> Reviewed-by: Lionel Landwerlin <[email protected]>
-rw-r--r--src/intel/vulkan/anv_cmd_buffer.c68
-rw-r--r--src/intel/vulkan/anv_private.h6
2 files changed, 50 insertions, 24 deletions
diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c
index 96c75e06ae8..59a281d6053 100644
--- a/src/intel/vulkan/anv_cmd_buffer.c
+++ b/src/intel/vulkan/anv_cmd_buffer.c
@@ -78,46 +78,72 @@ const struct anv_dynamic_state default_dynamic_state = {
},
};
-void
+/**
+ * Copy the dynamic state from src to dest based on the copy_mask.
+ *
+ * Avoid copying states that have not changed, except for VIEWPORT, SCISSOR and
+ * BLEND_CONSTANTS (always copy them if they are in the copy_mask).
+ *
+ * Returns a mask of the states which changed.
+ */
+anv_cmd_dirty_mask_t
anv_dynamic_state_copy(struct anv_dynamic_state *dest,
const struct anv_dynamic_state *src,
anv_cmd_dirty_mask_t copy_mask)
{
+ anv_cmd_dirty_mask_t changed = 0;
+
if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_VIEWPORT) {
dest->viewport.count = src->viewport.count;
typed_memcpy(dest->viewport.viewports, src->viewport.viewports,
src->viewport.count);
+ changed |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT;
}
if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_SCISSOR) {
dest->scissor.count = src->scissor.count;
typed_memcpy(dest->scissor.scissors, src->scissor.scissors,
src->scissor.count);
+ changed |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR;
}
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH)
- dest->line_width = src->line_width;
+ if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS) {
+ typed_memcpy(dest->blend_constants, src->blend_constants, 4);
+ changed |= ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS;
+ }
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS)
- dest->depth_bias = src->depth_bias;
+#define ANV_CMP_COPY(field, flag) \
+ if (copy_mask & flag) { \
+ if (dest->field != src->field) { \
+ dest->field = src->field; \
+ changed |= flag; \
+ } \
+ }
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS)
- typed_memcpy(dest->blend_constants, src->blend_constants, 4);
+ ANV_CMP_COPY(line_width, ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH);
+
+ ANV_CMP_COPY(depth_bias.bias, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS);
+ ANV_CMP_COPY(depth_bias.clamp, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS);
+ ANV_CMP_COPY(depth_bias.slope, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS);
+
+ ANV_CMP_COPY(depth_bounds.min, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS);
+ ANV_CMP_COPY(depth_bounds.max, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS);
+
+ ANV_CMP_COPY(stencil_compare_mask.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK);
+ ANV_CMP_COPY(stencil_compare_mask.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK);
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS)
- dest->depth_bounds = src->depth_bounds;
+ ANV_CMP_COPY(stencil_write_mask.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK);
+ ANV_CMP_COPY(stencil_write_mask.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK);
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK)
- dest->stencil_compare_mask = src->stencil_compare_mask;
+ ANV_CMP_COPY(stencil_reference.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE);
+ ANV_CMP_COPY(stencil_reference.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE);
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK)
- dest->stencil_write_mask = src->stencil_write_mask;
+ ANV_CMP_COPY(line_stipple.factor, ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE);
+ ANV_CMP_COPY(line_stipple.pattern, ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE);
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE)
- dest->stencil_reference = src->stencil_reference;
+#undef ANV_CMP_COPY
- if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE)
- dest->line_stipple = src->line_stipple;
+ return changed;
}
static void
@@ -378,10 +404,10 @@ void anv_CmdBindPipeline(
cmd_buffer->state.descriptors_dirty |= pipeline->active_stages;
/* Apply the dynamic state from the pipeline */
- cmd_buffer->state.gfx.dirty |= pipeline->dynamic_state_mask;
- anv_dynamic_state_copy(&cmd_buffer->state.gfx.dynamic,
- &pipeline->dynamic_state,
- pipeline->dynamic_state_mask);
+ cmd_buffer->state.gfx.dirty |=
+ anv_dynamic_state_copy(&cmd_buffer->state.gfx.dynamic,
+ &pipeline->dynamic_state,
+ pipeline->dynamic_state_mask);
break;
default:
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 78b5b0793e5..b6bb2019bb3 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2275,9 +2275,9 @@ struct anv_dynamic_state {
extern const struct anv_dynamic_state default_dynamic_state;
-void anv_dynamic_state_copy(struct anv_dynamic_state *dest,
- const struct anv_dynamic_state *src,
- uint32_t copy_mask);
+uint32_t anv_dynamic_state_copy(struct anv_dynamic_state *dest,
+ const struct anv_dynamic_state *src,
+ uint32_t copy_mask);
struct anv_surface_state {
struct anv_state state;