tu: Fix dynamic state not always being emitted

We precompile static state and count it as dynamic, so we have to
manually clear bitset that tells which dynamic state is set, in order to
make sure that future dynamic state will be emitted. The issue is that
framework remembers only a past REAL dynamic state and compares a new
dynamic state against it, and not against our static state masquaraded
as dynamic.

Example:
 - Set dynamic state S with value A
 - Bind pipeline with dynamic state S
 - Draw
 - Bind pipeline with static state S with value B
 - Draw
 - Set dynamic state S with value A
 - Bind pipeline with dynamic state S
 - Draw

Previously, at the last draw the dynamic state S was not dirty and
current dynamic state was equal to the past dynamic state, so
it was not emitted, while GPU used value B from static pipeline.

This fix, at the point of static pipeline binding, clears the
bitset which tells that dynamic state S was previously set.
This forces the next dynamic state to be re-emitted.

Fixes broken rendering in Arma 3, and probably some other
games running through DXVK.

Fixes: 97da0a7734
("tu: Rewrite to use common Vulkan dynamic state")

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27961>
This commit is contained in:
Danylo Piliaiev 2024-03-04 14:36:08 +01:00 committed by Marge Bot
parent 6823ffe70e
commit a76fcebfc0
3 changed files with 19 additions and 0 deletions

View file

@ -3159,6 +3159,17 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
tu_bind_gs(cmd, pipeline->shaders[MESA_SHADER_GEOMETRY]);
tu_bind_fs(cmd, pipeline->shaders[MESA_SHADER_FRAGMENT]);
/* We precompile static state and count it as dynamic, so we have to
* manually clear bitset that tells which dynamic state is set, in order to
* make sure that future dynamic state will be emitted. The issue is that
* framework remembers only a past REAL dynamic state and compares a new
* dynamic state against it, and not against our static state masquaraded
* as dynamic.
*/
BITSET_ANDNOT(cmd->vk.dynamic_graphics_state.set,
cmd->vk.dynamic_graphics_state.set,
pipeline->static_state_mask);
vk_cmd_set_dynamic_graphics_state(&cmd->vk,
&gfx_pipeline->dynamic_state);
cmd->state.program = pipeline->program;

View file

@ -2057,6 +2057,9 @@ tu_pipeline_builder_parse_libraries(struct tu_pipeline_builder *builder,
}
}
BITSET_OR(pipeline->static_state_mask, pipeline->static_state_mask,
library->base.static_state_mask);
vk_graphics_pipeline_state_merge(&builder->graphics_state,
&library->graphics_state);
}
@ -3367,6 +3370,9 @@ tu_pipeline_builder_emit_state(struct tu_pipeline_builder *builder,
* binding the pipeline by making it "dynamic".
*/
BITSET_ANDNOT(remove, remove, keep);
BITSET_OR(pipeline->static_state_mask, pipeline->static_state_mask, remove);
BITSET_OR(builder->graphics_state.dynamic, builder->graphics_state.dynamic,
remove);
}

View file

@ -136,6 +136,8 @@ struct tu_pipeline
uint32_t set_state_mask;
struct tu_draw_state dynamic_state[TU_DYNAMIC_STATE_COUNT];
BITSET_DECLARE(static_state_mask, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
struct {
bool raster_order_attachment_access;
} ds;