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
+3 -1
View File
@@ -3006,6 +3006,7 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer,
if (*dirty & (V3DV_CMD_DIRTY_PIPELINE) || if (*dirty & (V3DV_CMD_DIRTY_PIPELINE) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_CULL_MODE) || 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_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)) { BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE)) {
v3dv_X(device, cmd_buffer_emit_configuration_bits)(cmd_buffer); 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 = 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_COMPARE_MASK) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_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) if (*dirty & V3DV_CMD_DIRTY_PIPELINE || any_dynamic_stencil_dirty)
v3dv_X(device, cmd_buffer_emit_stencil)(cmd_buffer); v3dv_X(device, cmd_buffer_emit_stencil)(cmd_buffer);
+34 -16
View File
@@ -1442,29 +1442,40 @@ v3dX(cmd_buffer_emit_stencil)(struct v3dv_cmd_buffer *cmd_buffer)
bool any_dynamic_stencil_state = 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_COMPARE_MASK) ||
BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_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; bool emitted_stencil = false;
const struct vk_stencil_test_face_state *front = &dyn->ds.stencil.front; const struct vk_stencil_test_face_state *front = &dyn->ds.stencil.front;
const struct vk_stencil_test_face_state *back = &dyn->ds.stencil.back; 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 (pipeline->emit_stencil_cfg[i]) {
if (any_dynamic_stencil_state) { if (any_dynamic_stencil_state) {
cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, const struct vk_stencil_test_face_state *stencil_state =
pipeline->stencil_cfg[i], config) { i == 0 ? front : back;
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK)) {
config.stencil_test_mask = /* If we have any dynamic stencil state we just emit the entire
i == 0 ? front->compare_mask : back->compare_mask; * packet since for simplicity
} */
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK)) { cl_emit(&job->bcl, STENCIL_CFG, config) {
config.stencil_write_mask = config.front_config = !needs_front_and_back || i == 0;
i == 0 ? front->write_mask : back->write_mask; config.back_config = !needs_front_and_back || i == 1;
} config.stencil_test_mask = stencil_state->compare_mask & 0xff;
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE)) { config.stencil_write_mask = stencil_state->write_mask & 0xff;
config.stencil_ref_value = config.stencil_ref_value = stencil_state->reference & 0xff;
i == 0 ? front->reference : back->reference; 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 { } else {
cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[i]); 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_COMPARE_MASK);
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE); 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_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 = struct vk_dynamic_graphics_state *dyn =
&cmd_buffer->vk.dynamic_graphics_state; &cmd_buffer->vk.dynamic_graphics_state;
/* Disable depth/stencil if we don't have a D/S attachment */
bool has_depth = bool has_depth =
pipeline->rendering_info.depth_attachment_format != VK_FORMAT_UNDEFINED; 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) { cl_emit_with_prepacked(&job->bcl, CFG_BITS, pipeline->cfg_bits, config) {
if (dyn->ds.depth.test_enable && has_depth) { 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.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; cmd_buffer->state.z_updates_enable = config.z_updates_enable;
#if V3D_VERSION == 42 #if V3D_VERSION == 42
bool enable_ez = cmd_buffer_update_ez_state(cmd_buffer, pipeline); 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_CULL_MODE);
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_RS_FRONT_FACE); 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_DEPTH_BOUNDS_TEST_ENABLE);
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE);
} }
void void
+17 -33
View File
@@ -199,13 +199,6 @@ pack_cfg_bits(struct v3dv_pipeline *pipeline,
config.blend_enable = pipeline->blend.enables != 0; 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 #if V3D_VERSION >= 71
/* From the Vulkan spec: /* From the Vulkan spec:
* *
@@ -240,8 +233,8 @@ pack_cfg_bits(struct v3dv_pipeline *pipeline,
}; };
} }
static uint32_t uint32_t
translate_stencil_op(VkStencilOp op) v3dX(translate_stencil_op)(VkStencilOp op)
{ {
switch (op) { switch (op) {
case VK_STENCIL_OP_KEEP: 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 * 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. * 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) { v3dvx_pack(stencil_cfg, STENCIL_CFG, config) {
config.front_config = is_front; config.front_config = is_front;
config.back_config = is_back; config.back_config = is_back;
config.stencil_write_mask = write_mask; config.stencil_write_mask = stencil_state->writeMask & 0xff;
config.stencil_test_mask = compare_mask; config.stencil_test_mask = stencil_state->compareMask & 0xff;
config.stencil_test_function = stencil_state->compareOp; config.stencil_test_function = stencil_state->compareOp;
config.stencil_pass_op = translate_stencil_op(stencil_state->passOp); config.stencil_pass_op =
config.depth_test_fail_op = translate_stencil_op(stencil_state->depthFailOp); v3dX(translate_stencil_op)(stencil_state->passOp);
config.stencil_test_fail_op = translate_stencil_op(stencil_state->failOp); config.depth_test_fail_op =
config.stencil_ref_value = reference; 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)); 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; return;
}
const struct vk_render_pass_state *ri = &pipeline->rendering_info; const struct vk_render_pass_state *ri = &pipeline->rendering_info;
if (ri->stencil_attachment_format == VK_FORMAT_UNDEFINED) 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 = 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_WRITE_MASK) ||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_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 /* If front != back or we have dynamic stencil state we can't emit a single
* packet for both faces. * packet for both faces.
+3
View File
@@ -368,3 +368,6 @@ void
v3dX(viewport_compute_xform)(const VkViewport *viewport, v3dX(viewport_compute_xform)(const VkViewport *viewport,
float scale[3], float scale[3],
float translate[3]); float translate[3]);
uint32_t
v3dX(translate_stencil_op)(VkStencilOp op);