kk: Clean up gfx state flushing

Signed-off-by: Aitor Camacho <aitor@lunarg.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40763>
This commit is contained in:
Aitor Camacho 2026-04-01 23:40:35 +09:00 committed by Marge Bot
parent fa240cec0b
commit 24b14fd095
5 changed files with 78 additions and 76 deletions

View file

@ -136,7 +136,6 @@ struct kk_graphics_state {
struct {
struct kk_addr_range addr_range[KK_MAX_VBUFS];
mtl_buffer *handles[KK_MAX_VBUFS];
uint32_t attribs_read;
/* Required to understand maximum size of index buffer if primitive is
* triangle fans */
uint32_t max_vertices;

View file

@ -644,26 +644,60 @@ set_empty_scissor(mtl_render_encoder *enc)
mtl_set_scissor_rects(enc, &rect, 1);
}
static void
kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
{
#define IS_DIRTY(bit) BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_##bit)
#define IS_SHADER_DIRTY(bit) \
(cmd->state.dirty_shaders & BITFIELD_BIT(MESA_SHADER_##bit))
static void
kk_flush_pipeline(struct kk_cmd_buffer *cmd)
{
struct kk_device *device = kk_cmd_buffer_device(cmd);
mtl_render_encoder *enc = kk_render_encoder(cmd);
struct kk_graphics_state *gfx = &cmd->state.gfx;
struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state;
struct kk_descriptor_state *desc = &cmd->state.gfx.descriptors;
/* Depth/stencil state may be dynamic, handle it as part of the pipeline. */
if (cmd->state.gfx.is_depth_stencil_dynamic &&
(cmd->state.gfx.render.depth_att.vk_format != VK_FORMAT_UNDEFINED ||
cmd->state.gfx.render.stencil_att.vk_format != VK_FORMAT_UNDEFINED) &&
(IS_DIRTY(DS_DEPTH_TEST_ENABLE) | IS_DIRTY(DS_DEPTH_WRITE_ENABLE) |
IS_DIRTY(DS_DEPTH_COMPARE_OP) | IS_DIRTY(DS_STENCIL_TEST_ENABLE) |
IS_DIRTY(DS_STENCIL_OP) | IS_DIRTY(DS_STENCIL_COMPARE_MASK) |
IS_DIRTY(DS_STENCIL_WRITE_MASK))) {
kk_cmd_release_dynamic_ds_state(cmd);
bool has_depth = dyn->rp.attachments & MESA_VK_RP_ATTACHMENT_DEPTH_BIT;
bool has_stencil =
dyn->rp.attachments & MESA_VK_RP_ATTACHMENT_STENCIL_BIT;
gfx->depth_stencil_state = kk_compile_depth_stencil_state(
device, &dyn->ds, has_depth, has_stencil);
mtl_set_depth_stencil_state(enc, gfx->depth_stencil_state);
}
if (IS_SHADER_DIRTY(VERTEX)) {
struct kk_shader *vs = cmd->state.shaders[MESA_SHADER_VERTEX];
mtl_render_set_pipeline_state(enc, vs->pipeline.gfx.handle);
if (gfx->depth_stencil_state)
mtl_set_depth_stencil_state(enc, gfx->depth_stencil_state);
}
}
static void
kk_flush_dynamic_state(struct kk_cmd_buffer *cmd)
{
struct kk_graphics_state *gfx = &cmd->state.gfx;
struct kk_descriptor_state *desc = &gfx->descriptors;
struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state;
mtl_render_encoder *enc = kk_render_encoder(cmd);
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VI_BINDING_STRIDES)) {
if (IS_DIRTY(VI_BINDING_STRIDES)) {
u_foreach_bit(ndx, dyn->vi->bindings_valid) {
desc->root.draw.buffer_strides[ndx] = dyn->vi_binding_strides[ndx];
}
desc->root_dirty = true;
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_RASTERIZER_DISCARD_ENABLE)) {
if (IS_DIRTY(RS_RASTERIZER_DISCARD_ENABLE)) {
if (dyn->rs.rasterizer_discard_enable) {
set_empty_scissor(enc);
} else {
@ -672,7 +706,7 @@ kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
}
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_CULL_MODE)) {
if (IS_DIRTY(RS_CULL_MODE)) {
gfx->is_cull_front_and_back =
dyn->rs.cull_mode == VK_CULL_MODE_FRONT_AND_BACK;
if (gfx->is_cull_front_and_back) {
@ -687,43 +721,17 @@ kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
/* We enable raster discard by setting scissor to size (0, 0) */
if (!(dyn->rs.rasterizer_discard_enable || gfx->is_cull_front_and_back) &&
(BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSOR_COUNT) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS)))
(IS_DIRTY(VP_VIEWPORT_COUNT) || IS_DIRTY(VP_VIEWPORTS) ||
IS_DIRTY(VP_SCISSOR_COUNT) || IS_DIRTY(VP_SCISSORS)))
kk_flush_vp_state(cmd);
if (cmd->state.gfx.is_depth_stencil_dynamic &&
(cmd->state.gfx.render.depth_att.vk_format != VK_FORMAT_UNDEFINED ||
cmd->state.gfx.render.stencil_att.vk_format != VK_FORMAT_UNDEFINED) &&
(BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE) |
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE) |
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP) |
// BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE)
// | BITSET_TEST(dyn->dirty,
// MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS) |
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE) |
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_OP) |
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) |
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK))) {
kk_cmd_release_dynamic_ds_state(cmd);
bool has_depth = dyn->rp.attachments & MESA_VK_RP_ATTACHMENT_DEPTH_BIT;
bool has_stencil =
dyn->rp.attachments & MESA_VK_RP_ATTACHMENT_STENCIL_BIT;
gfx->depth_stencil_state = kk_compile_depth_stencil_state(
device, &dyn->ds, has_depth, has_stencil);
mtl_set_depth_stencil_state(enc, gfx->depth_stencil_state);
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_FRONT_FACE)) {
if (IS_DIRTY(RS_FRONT_FACE)) {
mtl_set_front_face_winding(
enc, vk_front_face_to_mtl_winding(
cmd->vk.dynamic_graphics_state.rs.front_face));
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_ENABLE)) {
if (IS_DIRTY(RS_DEPTH_BIAS_FACTORS) || IS_DIRTY(RS_DEPTH_BIAS_ENABLE)) {
if (dyn->rs.depth_bias.enable)
mtl_set_depth_bias(enc, dyn->rs.depth_bias.constant_factor,
dyn->rs.depth_bias.slope_factor,
@ -732,19 +740,19 @@ kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
mtl_set_depth_bias(enc, 0.0f, 0.0f, 0.0f);
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_CLAMP_ENABLE)) {
if (IS_DIRTY(RS_DEPTH_CLAMP_ENABLE)) {
enum mtl_depth_clip_mode mode = dyn->rs.depth_clamp_enable
? MTL_DEPTH_CLIP_MODE_CLAMP
: MTL_DEPTH_CLIP_MODE_CLIP;
mtl_set_depth_clip_mode(enc, mode);
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE))
if (IS_DIRTY(DS_STENCIL_REFERENCE))
mtl_set_stencil_references(
enc, cmd->vk.dynamic_graphics_state.ds.stencil.front.reference,
cmd->vk.dynamic_graphics_state.ds.stencil.back.reference);
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) {
if (IS_DIRTY(CB_BLEND_CONSTANTS)) {
static_assert(sizeof(desc->root.draw.blend_constant) ==
sizeof(dyn->cb.blend_constants),
"common size");
@ -754,13 +762,12 @@ kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
desc->root_dirty = true;
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VI) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VI_BINDINGS_VALID) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VI_BINDING_STRIDES) ||
gfx->dirty & KK_DIRTY_VB) {
if (IS_DIRTY(VI) || IS_DIRTY(VI_BINDINGS_VALID) ||
IS_DIRTY(VI_BINDING_STRIDES) || gfx->dirty & KK_DIRTY_VB) {
struct kk_shader *vs = cmd->state.shaders[MESA_SHADER_VERTEX];
unsigned slot = 0;
cmd->state.gfx.vb.max_vertices = 0u;
u_foreach_bit(i, cmd->state.gfx.vb.attribs_read) {
u_foreach_bit(i, vs->info.vs.attribs_read) {
if (dyn->vi->attributes_valid & BITFIELD_BIT(i)) {
struct vk_vertex_attribute_state attr = dyn->vi->attributes[i];
struct kk_addr_range vb = gfx->vb.addr_range[attr.binding];
@ -781,15 +788,6 @@ kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
desc->root_dirty = true;
}
if (IS_SHADER_DIRTY(VERTEX)) {
mtl_render_set_pipeline_state(
enc, cmd->state.shaders[MESA_SHADER_VERTEX]->pipeline.gfx.handle);
if (gfx->depth_stencil_state)
mtl_set_depth_stencil_state(enc, gfx->depth_stencil_state);
}
if (desc->push_dirty)
kk_cmd_buffer_flush_push_descriptors(cmd, desc);
if (desc->root_dirty)
kk_upload_descriptor_root(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS);
@ -803,13 +801,27 @@ kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
mtl_set_visibility_result_mode(enc, gfx->occlusion.mode,
gfx->occlusion.index * sizeof(uint64_t));
}
}
static void
kk_flush_gfx_state(struct kk_cmd_buffer *cmd)
{
struct kk_graphics_state *gfx = &cmd->state.gfx;
struct kk_descriptor_state *desc = &gfx->descriptors;
kk_flush_pipeline(cmd);
if (desc->push_dirty)
kk_cmd_buffer_flush_push_descriptors(cmd, desc);
kk_flush_dynamic_state(cmd);
cmd->state.dirty_shaders = 0u;
gfx->dirty = 0u;
vk_dynamic_graphics_state_clear_dirty(dyn);
#undef IS_SHADER_DIRTY
cmd->state.gfx.dirty = 0u;
vk_dynamic_graphics_state_clear_dirty(&cmd->vk.dynamic_graphics_state);
}
#undef IS_SHADER_DIRTY
#undef IS_DIRTY
struct kk_draw_data {
union {

View file

@ -75,7 +75,6 @@ struct kk_meta_save {
struct {
mtl_render_pipeline_state *ps;
mtl_depth_stencil_state *ds;
uint32_t attribs_read;
enum mtl_visibility_result_mode occlusion;
bool is_ds_dynamic;
} gfx;
@ -106,7 +105,6 @@ kk_meta_begin(struct kk_cmd_buffer *cmd, struct kk_meta_save *save,
}
save->pipeline.gfx.ds = cmd->state.gfx.depth_stencil_state;
save->pipeline.gfx.attribs_read = cmd->state.gfx.vb.attribs_read;
save->pipeline.gfx.occlusion = cmd->state.gfx.occlusion.mode;
save->pipeline.gfx.is_ds_dynamic =
cmd->state.gfx.is_depth_stencil_dynamic;
@ -170,7 +168,6 @@ kk_meta_end(struct kk_cmd_buffer *cmd, struct kk_meta_save *save,
if (cmd->state.gfx.is_depth_stencil_dynamic)
mtl_release(cmd->state.gfx.depth_stencil_state);
cmd->state.gfx.depth_stencil_state = save->pipeline.gfx.ds;
cmd->state.gfx.vb.attribs_read = save->pipeline.gfx.attribs_read;
cmd->state.gfx.is_depth_stencil_dynamic =
save->pipeline.gfx.is_ds_dynamic;

View file

@ -569,10 +569,10 @@ kk_shader_destroy(struct vk_device *vk_dev, struct vk_shader *vk_shader,
mtl_release(shader->pipeline.cs);
} else if (shader->info.stage == MESA_SHADER_VERTEX) {
mtl_release(shader->pipeline.gfx.handle);
if (shader->pipeline.gfx.mtl_depth_stencil_state_handle)
mtl_release(shader->pipeline.gfx.mtl_depth_stencil_state_handle);
if (shader->pipeline.gfx.ds_handle)
mtl_release(shader->pipeline.gfx.ds_handle);
shader->pipeline.gfx.handle = NULL;
shader->pipeline.gfx.mtl_depth_stencil_state_handle = NULL;
shader->pipeline.gfx.ds_handle = NULL;
ralloc_free((void *)shader->info.vs.frag_msl_code);
ralloc_free((void *)shader->info.vs.frag_entrypoint_name);
@ -1061,8 +1061,7 @@ kk_compile_graphics_pipeline(struct kk_device *device, const char *vs,
pipeline_descriptor, info->vs.s_format);
if (info->vs.has_ds) {
pipeline->gfx.mtl_depth_stencil_state_handle =
kk_compile_ds_state(device, info);
pipeline->gfx.ds_handle = kk_compile_ds_state(device, info);
}
if (info->vs.view_mask) {
@ -1342,10 +1341,7 @@ kk_cmd_bind_graphics_shader(struct kk_cmd_buffer *cmd,
if (stage != MESA_SHADER_VERTEX)
return;
cmd->state.gfx.vb.attribs_read = shader->info.vs.attribs_read;
bool requires_dynamic_depth_stencil =
shader->pipeline.gfx.mtl_depth_stencil_state_handle == NULL;
bool requires_dynamic_depth_stencil = shader->pipeline.gfx.ds_handle == NULL;
if (cmd->state.gfx.is_depth_stencil_dynamic) {
/* If we are switching from dynamic to static, we need to clean up
* temporary state. Otherwise, leave the existing dynamic state
@ -1353,12 +1349,10 @@ kk_cmd_bind_graphics_shader(struct kk_cmd_buffer *cmd,
*/
if (!requires_dynamic_depth_stencil) {
mtl_release(cmd->state.gfx.depth_stencil_state);
cmd->state.gfx.depth_stencil_state =
shader->pipeline.gfx.mtl_depth_stencil_state_handle;
cmd->state.gfx.depth_stencil_state = shader->pipeline.gfx.ds_handle;
}
} else
cmd->state.gfx.depth_stencil_state =
shader->pipeline.gfx.mtl_depth_stencil_state_handle;
cmd->state.gfx.depth_stencil_state = shader->pipeline.gfx.ds_handle;
cmd->state.gfx.is_depth_stencil_dynamic = requires_dynamic_depth_stencil;
cmd->state.gfx.dirty |= KK_DIRTY_VB;

View file

@ -67,7 +67,7 @@ struct kk_pipeline_handles {
union {
struct {
mtl_render_pipeline_state *handle;
mtl_depth_stencil_state *mtl_depth_stencil_state_handle;
mtl_depth_stencil_state *ds_handle;
} gfx;
mtl_compute_pipeline_state *cs;
};