radv: fix emitting dynamic viewports/scissors when the count is static

In a scenario where the viewports/scissors are a dynamic state but the
count is static (ie. updated when a graphics pipeline is bound), the
driver wasn't considering that and it was re-emitting the previous
number of viewports/scissors.

This fixes rendering issue with Blender.

Cc: mesa-stable
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13127
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34921>
(cherry picked from commit 9a07ccbc89)
This commit is contained in:
Samuel Pitoiset 2025-05-09 16:58:02 +02:00 committed by Eric Engestrom
parent 63b0a527ed
commit db4b914bd5
4 changed files with 46 additions and 31 deletions

View file

@ -174,7 +174,7 @@
"description": "radv: fix emitting dynamic viewports/scissors when the count is static",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -71,11 +71,6 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_dy
dest->sample_location.count = src->sample_location.count;
if (copy_mask & RADV_DYNAMIC_VIEWPORT) {
if (dest->vk.vp.viewport_count != src->vk.vp.viewport_count) {
dest->vk.vp.viewport_count = src->vk.vp.viewport_count;
dest_mask |= RADV_DYNAMIC_VIEWPORT;
}
if (memcmp(&dest->vk.vp.viewports, &src->vk.vp.viewports, src->vk.vp.viewport_count * sizeof(VkViewport))) {
typed_memcpy(dest->vk.vp.viewports, src->vk.vp.viewports, src->vk.vp.viewport_count);
typed_memcpy(dest->hw_vp.xform, src->hw_vp.xform, src->vk.vp.viewport_count);
@ -83,18 +78,27 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_dy
}
}
if (copy_mask & RADV_DYNAMIC_SCISSOR) {
if (dest->vk.vp.scissor_count != src->vk.vp.scissor_count) {
dest->vk.vp.scissor_count = src->vk.vp.scissor_count;
dest_mask |= RADV_DYNAMIC_SCISSOR;
if (copy_mask & RADV_DYNAMIC_VIEWPORT_WITH_COUNT) {
if (dest->vk.vp.viewport_count != src->vk.vp.viewport_count) {
dest->vk.vp.viewport_count = src->vk.vp.viewport_count;
dest_mask |= RADV_DYNAMIC_VIEWPORT;
}
}
if (copy_mask & RADV_DYNAMIC_SCISSOR) {
if (memcmp(&dest->vk.vp.scissors, &src->vk.vp.scissors, src->vk.vp.scissor_count * sizeof(VkRect2D))) {
typed_memcpy(dest->vk.vp.scissors, src->vk.vp.scissors, src->vk.vp.scissor_count);
dest_mask |= RADV_DYNAMIC_SCISSOR;
}
}
if (copy_mask & RADV_DYNAMIC_SCISSOR_WITH_COUNT) {
if (dest->vk.vp.scissor_count != src->vk.vp.scissor_count) {
dest->vk.vp.scissor_count = src->vk.vp.scissor_count;
dest_mask |= RADV_DYNAMIC_SCISSOR;
}
}
if (copy_mask & RADV_DYNAMIC_BLEND_CONSTANTS) {
if (memcmp(&dest->vk.cb.blend_constants, &src->vk.cb.blend_constants, sizeof(src->vk.cb.blend_constants))) {
typed_memcpy(dest->vk.cb.blend_constants, src->vk.cb.blend_constants, 4);
@ -8034,9 +8038,6 @@ radv_CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint3
assert(firstViewport < MAX_VIEWPORTS);
assert(total_count >= 1 && total_count <= MAX_VIEWPORTS);
if (state->dynamic.vk.vp.viewport_count < total_count)
state->dynamic.vk.vp.viewport_count = total_count;
memcpy(state->dynamic.vk.vp.viewports + firstViewport, pViewports, viewportCount * sizeof(*pViewports));
for (unsigned i = 0; i < viewportCount; i++) {
radv_get_viewport_xform(&pViewports[i], state->dynamic.hw_vp.xform[i + firstViewport].scale,
@ -8058,9 +8059,6 @@ radv_CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_
assert(firstScissor < MAX_SCISSORS);
assert(total_count >= 1 && total_count <= MAX_SCISSORS);
if (state->dynamic.vk.vp.scissor_count < total_count)
state->dynamic.vk.vp.scissor_count = total_count;
memcpy(state->dynamic.vk.vp.scissors + firstScissor, pScissors, scissorCount * sizeof(*pScissors));
state->dirty_dynamic |= RADV_DYNAMIC_SCISSOR;
@ -8233,12 +8231,22 @@ radv_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer, VkPrimitiveTopology
VKAPI_ATTR void VKAPI_CALL
radv_CmdSetViewportWithCount(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport *pViewports)
{
VK_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
struct radv_cmd_state *state = &cmd_buffer->state;
state->dynamic.vk.vp.viewport_count = viewportCount;
radv_CmdSetViewport(commandBuffer, 0, viewportCount, pViewports);
}
VKAPI_ATTR void VKAPI_CALL
radv_CmdSetScissorWithCount(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D *pScissors)
{
VK_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
struct radv_cmd_state *state = &cmd_buffer->state;
state->dynamic.vk.vp.scissor_count = scissorCount;
radv_CmdSetScissor(commandBuffer, 0, scissorCount, pScissors);
}

View file

@ -77,7 +77,9 @@ enum radv_dynamic_state_bits {
RADV_DYNAMIC_COLOR_ATTACHMENT_MAP = 1ull << 51,
RADV_DYNAMIC_INPUT_ATTACHMENT_MAP = 1ull << 52,
RADV_DYNAMIC_DEPTH_CLAMP_RANGE = 1ull << 53,
RADV_DYNAMIC_ALL = (1ull << 54) - 1,
RADV_DYNAMIC_VIEWPORT_WITH_COUNT = 1ull << 54,
RADV_DYNAMIC_SCISSOR_WITH_COUNT = 1ull << 55,
RADV_DYNAMIC_ALL = (1ull << 56) - 1,
};
enum radv_cmd_dirty_bits {

View file

@ -272,10 +272,8 @@ radv_dynamic_state_mask(VkDynamicState state)
{
switch (state) {
case VK_DYNAMIC_STATE_VIEWPORT:
case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
return RADV_DYNAMIC_VIEWPORT;
case VK_DYNAMIC_STATE_SCISSOR:
case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
return RADV_DYNAMIC_SCISSOR;
case VK_DYNAMIC_STATE_LINE_WIDTH:
return RADV_DYNAMIC_LINE_WIDTH;
@ -377,6 +375,10 @@ radv_dynamic_state_mask(VkDynamicState state)
return RADV_DYNAMIC_ALPHA_TO_ONE_ENABLE;
case VK_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT:
return RADV_DYNAMIC_DEPTH_CLAMP_RANGE;
case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
return RADV_DYNAMIC_VIEWPORT | RADV_DYNAMIC_VIEWPORT_WITH_COUNT;
case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
return RADV_DYNAMIC_SCISSOR | RADV_DYNAMIC_SCISSOR_WITH_COUNT;
default:
unreachable("Unhandled dynamic state");
}
@ -732,21 +734,24 @@ radv_pipeline_init_dynamic_state(const struct radv_device *device, struct radv_g
}
/* Viewport. */
if (needed_states & RADV_DYNAMIC_VIEWPORT) {
dynamic->vk.vp.viewport_count = state->vp->viewport_count;
if (states & RADV_DYNAMIC_VIEWPORT) {
typed_memcpy(dynamic->vk.vp.viewports, state->vp->viewports, state->vp->viewport_count);
for (unsigned i = 0; i < dynamic->vk.vp.viewport_count; i++)
radv_get_viewport_xform(&dynamic->vk.vp.viewports[i], dynamic->hw_vp.xform[i].scale,
dynamic->hw_vp.xform[i].translate);
}
if (states & RADV_DYNAMIC_VIEWPORT) {
typed_memcpy(dynamic->vk.vp.viewports, state->vp->viewports, state->vp->viewport_count);
for (unsigned i = 0; i < state->vp->viewport_count; i++)
radv_get_viewport_xform(&dynamic->vk.vp.viewports[i], dynamic->hw_vp.xform[i].scale,
dynamic->hw_vp.xform[i].translate);
}
if (needed_states & RADV_DYNAMIC_SCISSOR) {
if (states & RADV_DYNAMIC_VIEWPORT_WITH_COUNT) {
dynamic->vk.vp.viewport_count = state->vp->viewport_count;
}
/* Scissor. */
if (states & RADV_DYNAMIC_SCISSOR) {
typed_memcpy(dynamic->vk.vp.scissors, state->vp->scissors, state->vp->scissor_count);
}
if (states & RADV_DYNAMIC_SCISSOR_WITH_COUNT) {
dynamic->vk.vp.scissor_count = state->vp->scissor_count;
if (states & RADV_DYNAMIC_SCISSOR) {
typed_memcpy(dynamic->vk.vp.scissors, state->vp->scissors, state->vp->scissor_count);
}
}
if (states & RADV_DYNAMIC_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE) {