v3dv: StencilOp and StencilTestEnable are now dynamic

This commit introduces a significant change when we emit STENCIL_CFG,
with any dynamic state: we stop to use cl_emit_with_prepacked, and use
directly cl_emit. The reason is that now most of the STENCIL_CFG
parameters are dynamic, any improvement of using
cl_emit_with_prepacked is minimized. Also gets the code simpler, and
avoid the need to be extra careful with the fact that
cl_emit_with_prepaked doesn't override values.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27609>
This commit is contained in:
Alejandro Piñeiro
2024-03-27 12:56:18 +01:00
committed by Marge Bot
parent 2526f74ade
commit 60e9237e81
4 changed files with 57 additions and 50 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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.

View File

@@ -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);