From 6fdb734b868bb62328ddcc41d04c448bf9ae2a6b Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Mon, 4 Mar 2024 14:36:08 +0100 Subject: [PATCH] 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: 97da0a7734188f4b666bc38833bfadc8b4c53f84 ("tu: Rewrite to use common Vulkan dynamic state") Signed-off-by: Danylo Piliaiev Part-of: (cherry picked from commit a76fcebfc00df371cbf45a48c7e6385c2bda2c75) --- .pick_status.json | 2 +- src/freedreno/vulkan/tu_cmd_buffer.cc | 11 +++++++++++ src/freedreno/vulkan/tu_pipeline.cc | 6 ++++++ src/freedreno/vulkan/tu_pipeline.h | 2 ++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.pick_status.json b/.pick_status.json index 179143eeefe..8fcf42e71a9 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -274,7 +274,7 @@ "description": "tu: Fix dynamic state not always being emitted", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "97da0a7734188f4b666bc38833bfadc8b4c53f84", "notes": null diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index 35acc213795..010e1cb5f1f 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -3058,6 +3058,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; diff --git a/src/freedreno/vulkan/tu_pipeline.cc b/src/freedreno/vulkan/tu_pipeline.cc index e0a119af4ac..a775f83ca03 100644 --- a/src/freedreno/vulkan/tu_pipeline.cc +++ b/src/freedreno/vulkan/tu_pipeline.cc @@ -1963,6 +1963,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); } @@ -3276,6 +3279,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); } diff --git a/src/freedreno/vulkan/tu_pipeline.h b/src/freedreno/vulkan/tu_pipeline.h index a99675ccd4c..2c7b7f5b887 100644 --- a/src/freedreno/vulkan/tu_pipeline.h +++ b/src/freedreno/vulkan/tu_pipeline.h @@ -138,6 +138,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;