From 55fe8df979c19ab4232ba0c39e06e41354ccbac7 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 29 Jul 2025 17:13:57 +0200 Subject: [PATCH] vkd3d: Set the maximum viewport count in d3d12_pipeline_state_get_or_create_pipeline(). VK_DYNAMIC_STATE_VIEWPORT and VK_DYNAMIC_STATE_SCISSOR specify that viewports and scissor rectangles are dynamic state, but not their counts. It took a while to notice this issue because the existing code seemed to largely work as intended on hardware implementations, but tests using the additional viewports would fail on llvmpipe. --- libs/vkd3d/command.c | 21 +++++++++++++++------ libs/vkd3d/state.c | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index e487ed0b9..074d84305 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4221,13 +4221,21 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo TRACE("iface %p, viewport_count %u, viewports %p.\n", iface, viewport_count, viewports); if (viewport_count > ARRAY_SIZE(vk_viewports)) - { FIXME("Viewport count %u > D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE.\n", viewport_count); - viewport_count = ARRAY_SIZE(vk_viewports); - } - for (i = 0; i < viewport_count; ++i) + for (i = 0; i < ARRAY_SIZE(vk_viewports); ++i) { + if (i >= viewport_count) + { + vk_viewports[i].x = 0.0f; + vk_viewports[i].y = 0.0f; + vk_viewports[i].width = 1.0f; + vk_viewports[i].height = 1.0f; + vk_viewports[i].minDepth = 0.0f; + vk_viewports[i].maxDepth = 0.0f; + continue; + } + vk_viewports[i].x = viewports[i].TopLeftX; vk_viewports[i].y = viewports[i].TopLeftY + viewports[i].Height; vk_viewports[i].width = viewports[i].Width; @@ -4245,7 +4253,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo } vk_procs = &list->device->vk_procs; - VK_CALL(vkCmdSetViewport(list->vk_command_buffer, 0, viewport_count, vk_viewports)); + VK_CALL(vkCmdSetViewport(list->vk_command_buffer, 0, ARRAY_SIZE(vk_viewports), vk_viewports)); } static void STDMETHODCALLTYPE d3d12_command_list_RSSetScissorRects(ID3D12GraphicsCommandList6 *iface, @@ -4264,6 +4272,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetScissorRects(ID3D12Graphic rect_count = ARRAY_SIZE(vk_rects); } + memset(vk_rects, 0, sizeof(vk_rects)); for (i = 0; i < rect_count; ++i) { vk_rects[i].offset.x = rects[i].left; @@ -4273,7 +4282,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetScissorRects(ID3D12Graphic } vk_procs = &list->device->vk_procs; - VK_CALL(vkCmdSetScissor(list->vk_command_buffer, 0, rect_count, vk_rects)); + VK_CALL(vkCmdSetScissor(list->vk_command_buffer, 0, ARRAY_SIZE(vk_rects), vk_rects)); } static void STDMETHODCALLTYPE d3d12_command_list_OMSetBlendFactor(ID3D12GraphicsCommandList6 *iface, diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 9e9811bf9..413892789 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -3971,9 +3971,9 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pNext = NULL, .flags = 0, - .viewportCount = 1, + .viewportCount = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, .pViewports = NULL, - .scissorCount = 1, + .scissorCount = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, .pScissors = NULL, }; static const VkDynamicState dynamic_states[] =