diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index 8fac620edb5..96e83c657e6 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -3006,6 +3006,7 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer, if (*dirty & (V3DV_CMD_DIRTY_PIPELINE) || BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_CULL_MODE) || BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_FRONT_FACE) || + BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE) || BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE)) { v3dv_X(device, cmd_buffer_emit_configuration_bits)(cmd_buffer); } @@ -3028,7 +3029,8 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer, bool any_dynamic_stencil_dirty = BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) || BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) || - BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE); + BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE) || + BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_OP); if (*dirty & V3DV_CMD_DIRTY_PIPELINE || any_dynamic_stencil_dirty) v3dv_X(device, cmd_buffer_emit_stencil)(cmd_buffer); diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 4adb1cd407e..d7fb087d9a8 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -1442,29 +1442,40 @@ v3dX(cmd_buffer_emit_stencil)(struct v3dv_cmd_buffer *cmd_buffer) bool any_dynamic_stencil_state = BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) || BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) || - BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE); + BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE) || + BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_OP); bool emitted_stencil = false; const struct vk_stencil_test_face_state *front = &dyn->ds.stencil.front; const struct vk_stencil_test_face_state *back = &dyn->ds.stencil.back; - for (uint32_t i = 0; i < 2; i++) { + const bool needs_front_and_back = any_dynamic_stencil_state ? + memcmp(front, back, sizeof(*front)) != 0 : + pipeline->emit_stencil_cfg[1] == true; + const unsigned stencil_packets = needs_front_and_back ? 2 : 1; + + for (uint32_t i = 0; i < stencil_packets; i++) { if (pipeline->emit_stencil_cfg[i]) { if (any_dynamic_stencil_state) { - cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, - pipeline->stencil_cfg[i], config) { - if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK)) { - config.stencil_test_mask = - i == 0 ? front->compare_mask : back->compare_mask; - } - if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK)) { - config.stencil_write_mask = - i == 0 ? front->write_mask : back->write_mask; - } - if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE)) { - config.stencil_ref_value = - i == 0 ? front->reference : back->reference; - } + const struct vk_stencil_test_face_state *stencil_state = + i == 0 ? front : back; + + /* If we have any dynamic stencil state we just emit the entire + * packet since for simplicity + */ + cl_emit(&job->bcl, STENCIL_CFG, config) { + config.front_config = !needs_front_and_back || i == 0; + config.back_config = !needs_front_and_back || i == 1; + config.stencil_test_mask = stencil_state->compare_mask & 0xff; + config.stencil_write_mask = stencil_state->write_mask & 0xff; + config.stencil_ref_value = stencil_state->reference & 0xff; + config.stencil_test_function = stencil_state->op.compare; + config.stencil_pass_op = + v3dX(translate_stencil_op)(stencil_state->op.pass); + config.depth_test_fail_op = + v3dX(translate_stencil_op)(stencil_state->op.depth_fail); + config.stencil_test_fail_op = + v3dX(translate_stencil_op)(stencil_state->op.fail); } } else { cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[i]); @@ -1476,6 +1487,7 @@ v3dX(cmd_buffer_emit_stencil)(struct v3dv_cmd_buffer *cmd_buffer) BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK); BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE); BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK); + BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_OP); } } @@ -1970,8 +1982,11 @@ v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer) struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state; + /* Disable depth/stencil if we don't have a D/S attachment */ bool has_depth = pipeline->rendering_info.depth_attachment_format != VK_FORMAT_UNDEFINED; + bool has_stencil = + pipeline->rendering_info.stencil_attachment_format != VK_FORMAT_UNDEFINED; cl_emit_with_prepacked(&job->bcl, CFG_BITS, pipeline->cfg_bits, config) { if (dyn->ds.depth.test_enable && has_depth) { @@ -1981,6 +1996,8 @@ v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer) config.depth_test_function = VK_COMPARE_OP_ALWAYS; } + config.stencil_enable = dyn->ds.stencil.test_enable && has_stencil; + cmd_buffer->state.z_updates_enable = config.z_updates_enable; #if V3D_VERSION == 42 bool enable_ez = cmd_buffer_update_ez_state(cmd_buffer, pipeline); @@ -2012,6 +2029,7 @@ v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer) BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_RS_CULL_MODE); BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_RS_FRONT_FACE); BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE); + BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE); } void diff --git a/src/broadcom/vulkan/v3dvx_pipeline.c b/src/broadcom/vulkan/v3dvx_pipeline.c index c944eee57a5..616a7730cd4 100644 --- a/src/broadcom/vulkan/v3dvx_pipeline.c +++ b/src/broadcom/vulkan/v3dvx_pipeline.c @@ -199,13 +199,6 @@ pack_cfg_bits(struct v3dv_pipeline *pipeline, config.blend_enable = pipeline->blend.enables != 0; - /* Disable depth/stencil if we don't have a D/S attachment */ - const struct vk_render_pass_state *ri = &pipeline->rendering_info; - bool has_stencil = ri->stencil_attachment_format != VK_FORMAT_UNDEFINED; - - config.stencil_enable = - ds_info ? ds_info->stencilTestEnable && has_stencil: false; - #if V3D_VERSION >= 71 /* From the Vulkan spec: * @@ -240,8 +233,8 @@ pack_cfg_bits(struct v3dv_pipeline *pipeline, }; } -static uint32_t -translate_stencil_op(VkStencilOp op) +uint32_t +v3dX(translate_stencil_op)(VkStencilOp op) { switch (op) { case VK_STENCIL_OP_KEEP: @@ -283,33 +276,20 @@ pack_single_stencil_cfg(struct v3dv_pipeline *pipeline, * * 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 = - BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) ? - 0 : stencil_state->writeMask & 0xff; - - const uint8_t compare_mask = - BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) ? - 0 : stencil_state->compareMask & 0xff; - - const uint8_t reference = - BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE) ? - 0 : stencil_state->reference & 0xff; - v3dvx_pack(stencil_cfg, STENCIL_CFG, config) { config.front_config = is_front; config.back_config = is_back; - config.stencil_write_mask = write_mask; - config.stencil_test_mask = compare_mask; + config.stencil_write_mask = stencil_state->writeMask & 0xff; + config.stencil_test_mask = stencil_state->compareMask & 0xff; config.stencil_test_function = stencil_state->compareOp; - config.stencil_pass_op = translate_stencil_op(stencil_state->passOp); - config.depth_test_fail_op = translate_stencil_op(stencil_state->depthFailOp); - config.stencil_test_fail_op = translate_stencil_op(stencil_state->failOp); - config.stencil_ref_value = reference; + config.stencil_pass_op = + v3dX(translate_stencil_op)(stencil_state->passOp); + config.depth_test_fail_op = + v3dX(translate_stencil_op)(stencil_state->depthFailOp); + config.stencil_test_fail_op = + v3dX(translate_stencil_op)(stencil_state->failOp); + config.stencil_ref_value = stencil_state->reference & 0xff; } } @@ -320,8 +300,10 @@ pack_stencil_cfg(struct v3dv_pipeline *pipeline, { assert(sizeof(pipeline->stencil_cfg) == 2 * cl_packet_length(STENCIL_CFG)); - if (!ds_info || !ds_info->stencilTestEnable) + if ((!ds_info || !ds_info->stencilTestEnable) && + (!BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE))) { return; + } const struct vk_render_pass_state *ri = &pipeline->rendering_info; if (ri->stencil_attachment_format == VK_FORMAT_UNDEFINED) @@ -330,7 +312,9 @@ pack_stencil_cfg(struct v3dv_pipeline *pipeline, const bool any_dynamic_stencil_states = BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) || BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) || - BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE); + BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE) || + BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE) || + BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_OP); /* If front != back or we have dynamic stencil state we can't emit a single * packet for both faces. diff --git a/src/broadcom/vulkan/v3dvx_private.h b/src/broadcom/vulkan/v3dvx_private.h index 98090377227..68df5db74ad 100644 --- a/src/broadcom/vulkan/v3dvx_private.h +++ b/src/broadcom/vulkan/v3dvx_private.h @@ -368,3 +368,6 @@ void v3dX(viewport_compute_xform)(const VkViewport *viewport, float scale[3], float translate[3]); + +uint32_t +v3dX(translate_stencil_op)(VkStencilOp op);