From 134afdfd32c5085c2cdf7067fb26404bdda567e3 Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Tue, 4 Feb 2020 17:43:49 +0100 Subject: [PATCH] v3dv: implement dynamic stencil states Part-of: --- src/broadcom/vulkan/v3dv_cmd_buffer.c | 135 ++++++++++++++++++++++++++++++++-- src/broadcom/vulkan/v3dv_pipeline.c | 69 +++++++++++++++-- src/broadcom/vulkan/v3dv_private.h | 30 +++++++- 3 files changed, 217 insertions(+), 17 deletions(-) diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index cda9254..52ccb1c 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -33,6 +33,21 @@ const struct v3dv_dynamic_state default_dynamic_state = { .scissor = { .count = 0, }, + .stencil_compare_mask = + { + .front = ~0u, + .back = ~0u, + }, + .stencil_write_mask = + { + .front = ~0u, + .back = ~0u, + }, + .stencil_reference = + { + .front = 0u, + .back = 0u, + }, }; void @@ -1412,6 +1427,30 @@ bind_dynamic_state(struct v3dv_cmd_buffer *cmd_buffer, } } + if (copy_mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK) { + if (memcmp(&dest->stencil_compare_mask, &src->stencil_compare_mask, + sizeof(src->stencil_compare_mask))) { + dest->stencil_compare_mask = src->stencil_compare_mask; + dest_mask |= V3DV_DYNAMIC_STENCIL_COMPARE_MASK; + } + } + + if (copy_mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK) { + if (memcmp(&dest->stencil_write_mask, &src->stencil_write_mask, + sizeof(src->stencil_write_mask))) { + dest->stencil_write_mask = src->stencil_write_mask; + dest_mask |= V3DV_DYNAMIC_STENCIL_WRITE_MASK; + } + } + + if (copy_mask & V3DV_DYNAMIC_STENCIL_REFERENCE) { + if (memcmp(&dest->stencil_reference, &src->stencil_reference, + sizeof(src->stencil_reference))) { + dest->stencil_reference = src->stencil_reference; + dest_mask |= V3DV_DYNAMIC_STENCIL_REFERENCE; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1687,6 +1726,51 @@ emit_viewport(struct v3dv_cmd_buffer *cmd_buffer) } static void +emit_stencil(struct v3dv_cmd_buffer *cmd_buffer) +{ + struct v3dv_job *job = cmd_buffer->state.job; + assert(job); + + struct v3dv_pipeline *pipeline = cmd_buffer->state.pipeline; + struct v3dv_dynamic_state *dynamic_state = &cmd_buffer->state.dynamic; + + const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK | + V3DV_DYNAMIC_STENCIL_WRITE_MASK | + V3DV_DYNAMIC_STENCIL_REFERENCE; + + for (uint32_t i = 0; i < 2; i++) { + if (pipeline->emit_stencil_cfg[i]) { + /* Our dynamic state bits signal whether a particular state is + * taken from the static pipeline definition (so it is not dynamic). + */ + if (!(dynamic_state->mask & dynamic_stencil_states)) { + /* At least one of the stencil states is dynamic */ + cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, + pipeline->stencil_cfg[i], config) { + if (!(dynamic_state->mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK)) { + config.stencil_test_mask = + i == 0 ? dynamic_state->stencil_compare_mask.front : + dynamic_state->stencil_compare_mask.back; + } + if (!(dynamic_state->mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK)) { + config.stencil_write_mask = + i == 0 ? dynamic_state->stencil_write_mask.front : + dynamic_state->stencil_write_mask.back; + } + if (!(dynamic_state->mask & V3DV_DYNAMIC_STENCIL_REFERENCE)) { + config.stencil_ref_value = + i == 0 ? dynamic_state->stencil_reference.front : + dynamic_state->stencil_reference.back; + } + } + } else { + cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[i]); + } + } + } +} + +static void cmd_buffer_emit_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer) { struct v3dv_job *job = cmd_buffer->state.job; @@ -1821,11 +1905,7 @@ cmd_buffer_emit_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer) config.early_z_updates_enable = job->ez_state != VC5_EZ_DISABLED; } - if (pipeline->emit_stencil_cfg[0]) { - cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[0]); - if (pipeline->emit_stencil_cfg[1]) - cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[1]); - } + emit_stencil(cmd_buffer); /* FIXME: hardcoded values */ cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags); @@ -1980,3 +2060,48 @@ v3dv_CmdBindVertexBuffers(VkCommandBuffer commandBuffer, cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_VERTEX_BUFFER; } + +void +v3dv_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t compareMask) +{ + V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) + cmd_buffer->state.dynamic.stencil_compare_mask.front = compareMask & 0xff; + if (faceMask & VK_STENCIL_FACE_BACK_BIT) + cmd_buffer->state.dynamic.stencil_compare_mask.back = compareMask & 0xff; + + cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK; +} + +void +v3dv_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t writeMask) +{ + V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) + cmd_buffer->state.dynamic.stencil_write_mask.front = writeMask & 0xff; + if (faceMask & VK_STENCIL_FACE_BACK_BIT) + cmd_buffer->state.dynamic.stencil_write_mask.back = writeMask & 0xff; + + cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK; +} + +void +v3dv_CmdSetStencilReference(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t reference) +{ + V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) + cmd_buffer->state.dynamic.stencil_reference.front = reference & 0xff; + if (faceMask & VK_STENCIL_FACE_BACK_BIT) + cmd_buffer->state.dynamic.stencil_reference.back = reference & 0xff; + + cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE; +} diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c index 3f0dc07..069ca7f 100644 --- a/src/broadcom/vulkan/v3dv_pipeline.c +++ b/src/broadcom/vulkan/v3dv_pipeline.c @@ -870,6 +870,12 @@ v3dv_dynamic_state_mask(VkDynamicState state) return V3DV_DYNAMIC_VIEWPORT; case VK_DYNAMIC_STATE_SCISSOR: return V3DV_DYNAMIC_SCISSOR; + case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: + return V3DV_DYNAMIC_STENCIL_COMPARE_MASK; + case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: + return V3DV_DYNAMIC_STENCIL_WRITE_MASK; + case VK_DYNAMIC_STATE_STENCIL_REFERENCE: + return V3DV_DYNAMIC_STENCIL_REFERENCE; default: unreachable("Unhandled dynamic state"); } @@ -936,6 +942,27 @@ pipeline_init_dynamic_state(struct v3dv_pipeline *pipeline, } } + if (needed_states & V3DV_DYNAMIC_STENCIL_COMPARE_MASK) { + dynamic->stencil_compare_mask.front = + pCreateInfo->pDepthStencilState->front.compareMask; + dynamic->stencil_compare_mask.back = + pCreateInfo->pDepthStencilState->back.compareMask; + } + + if (needed_states & V3DV_DYNAMIC_STENCIL_WRITE_MASK) { + dynamic->stencil_write_mask.front = + pCreateInfo->pDepthStencilState->front.writeMask; + dynamic->stencil_write_mask.back = + pCreateInfo->pDepthStencilState->back.writeMask; + } + + if (needed_states & V3DV_DYNAMIC_STENCIL_REFERENCE) { + dynamic->stencil_reference.front = + pCreateInfo->pDepthStencilState->front.reference; + dynamic->stencil_reference.back = + pCreateInfo->pDepthStencilState->back.reference; + } + pipeline->dynamic_state.mask = states; } @@ -1022,7 +1049,8 @@ translate_stencil_op(enum pipe_stencil_op op) } static void -pack_single_stencil_cfg(uint8_t *stencil_cfg, +pack_single_stencil_cfg(struct v3dv_pipeline *pipeline, + uint8_t *stencil_cfg, bool is_front, bool is_back, const VkStencilOpState *stencil_state) @@ -1037,10 +1065,22 @@ pack_single_stencil_cfg(uint8_t *stencil_cfg, * * In our case, 's' is always 8, so we clamp to that to prevent our packing * functions to assert in debug mode if they see larger values. + * + * If we have dynamic state we need to make sure we set the corresponding + * state bits to 0, since cl_emit_with_prepacked ORs the new value with + * the old. */ - const uint8_t write_mask = stencil_state->writeMask & 0xff; - const uint8_t compare_mask = stencil_state->compareMask & 0xff; - const uint8_t reference = stencil_state->reference & 0xff; + const uint8_t write_mask = + pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK ? + stencil_state->writeMask & 0xff : 0; + + const uint8_t compare_mask = + pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ? + stencil_state->compareMask & 0xff : 0; + + const uint8_t reference = + pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ? + stencil_state->reference & 0xff : 0; v3dv_pack(stencil_cfg, STENCIL_CFG, config) { config.front_config = is_front; @@ -1064,18 +1104,31 @@ pack_stencil_cfg(struct v3dv_pipeline *pipeline, if (!ds_info || !ds_info->stencilTestEnable) return; + const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK | + V3DV_DYNAMIC_STENCIL_WRITE_MASK | + V3DV_DYNAMIC_STENCIL_REFERENCE; + + + /* If front != back or we have dynamic stencil state we can't emit a single + * packet for both faces. + */ + bool needs_front_and_back = false; + if (!(pipeline->dynamic_state.mask & dynamic_stencil_states) || + memcmp(&ds_info->front, &ds_info->back, sizeof(ds_info->front))) + needs_front_and_back = true; + /* If the front and back configurations are the same we can emit both with * a single packet. */ pipeline->emit_stencil_cfg[0] = true; - if (memcmp(&ds_info->front, &ds_info->back, sizeof(ds_info->front)) == 0) { - pack_single_stencil_cfg(pipeline->stencil_cfg[0], + if (!needs_front_and_back) { + pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0], true, true, &ds_info->front); } else { pipeline->emit_stencil_cfg[1] = true; - pack_single_stencil_cfg(pipeline->stencil_cfg[0], + pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0], true, false, &ds_info->front); - pack_single_stencil_cfg(pipeline->stencil_cfg[1], + pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[1], false, true, &ds_info->back); } } diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index f5f63c2..9b1a607 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -434,7 +434,10 @@ struct v3dv_scissor_state { enum v3dv_dynamic_state_bits { V3DV_DYNAMIC_VIEWPORT = 1 << 0, V3DV_DYNAMIC_SCISSOR = 1 << 1, - V3DV_DYNAMIC_ALL = (1 << 2) - 1, + V3DV_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 2, + V3DV_DYNAMIC_STENCIL_WRITE_MASK = 1 << 3, + V3DV_DYNAMIC_STENCIL_REFERENCE = 1 << 4, + V3DV_DYNAMIC_ALL = (1 << 5) - 1, }; /* To track which cmd buffer elements are "dirty" so would need an @@ -444,9 +447,13 @@ enum v3dv_dynamic_state_bits { enum v3dv_cmd_dirty_bits { V3DV_CMD_DIRTY_DYNAMIC_VIEWPORT = 1 << 0, V3DV_CMD_DIRTY_DYNAMIC_SCISSOR = 1 << 1, - V3DV_CMD_DIRTY_DYNAMIC_ALL = (1 << 2) - 1, - V3DV_CMD_DIRTY_PIPELINE = 1 << 2, - V3DV_CMD_DIRTY_VERTEX_BUFFER = 1 << 3, + V3DV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 2, + V3DV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK = 1 << 3, + V3DV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE = 1 << 4, + V3DV_CMD_DIRTY_DYNAMIC_ALL = (1 << 5) - 1, + + V3DV_CMD_DIRTY_PIPELINE = 1 << 5, + V3DV_CMD_DIRTY_VERTEX_BUFFER = 1 << 6, }; @@ -460,6 +467,21 @@ struct v3dv_dynamic_state { struct v3dv_viewport_state viewport; struct v3dv_scissor_state scissor; + + struct { + uint32_t front; + uint32_t back; + } stencil_compare_mask; + + struct { + uint32_t front; + uint32_t back; + } stencil_write_mask; + + struct { + uint32_t front; + uint32_t back; + } stencil_reference; }; extern const struct v3dv_dynamic_state default_dynamic_state; -- 2.7.4