From 2b7ba9f239c09049408d86eb71be18887691dc58 Mon Sep 17 00:00:00 2001 From: Rafael Antognolli Date: Mon, 19 Aug 2019 17:01:10 -0700 Subject: [PATCH] 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 Reviewed-by: Lionel Landwerlin --- src/intel/vulkan/anv_cmd_buffer.c | 68 +++++++++++++++++++++++++++------------ src/intel/vulkan/anv_private.h | 6 ++-- 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 96c75e0..59a281d 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 78b5b07..b6bb201 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; -- 2.7.4