Version 1.1 is required to properly support d3d12 viewports.
From: Conor McCarthy cmccarthy@codeweavers.com
Version 1.1 is required to properly support d3d12 viewports. --- libs/vkd3d/device.c | 11 +++++++++++ libs/vkd3d/vkd3d_private.h | 1 + 2 files changed, 12 insertions(+)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 39a5ca01..b4e7193f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -522,12 +522,14 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, const struct vkd3d_optional_instance_extensions_info *optional_extensions; const struct vkd3d_application_info *vkd3d_application_info; const struct vkd3d_host_time_domain_info *time_domain_info; + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; bool *user_extension_supported = NULL; VkApplicationInfo application_info; VkInstanceCreateInfo instance_info; char application_name[PATH_MAX]; uint32_t extension_count; const char **extensions; + uint32_t vk_api_version; VkInstance vk_instance; VkResult vr; HRESULT hr; @@ -580,6 +582,15 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, application_info.apiVersion = VK_API_VERSION_1_0; instance->api_version = VKD3D_API_VERSION_1_0;
+ vkEnumerateInstanceVersion = (void *)vk_global_procs->vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); + if (vkEnumerateInstanceVersion && vkEnumerateInstanceVersion(&vk_api_version) >= 0 + && vk_api_version >= VK_API_VERSION_1_1) + { + TRACE("Vulkan API version 1.1 is available; requesting it.\n"); + application_info.apiVersion = VK_API_VERSION_1_1; + } + instance->vk_api_version = application_info.apiVersion; + if ((vkd3d_application_info = vkd3d_find_struct(create_info->next, APPLICATION_INFO))) { if (vkd3d_application_info->application_name) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 1a277a47..b57af04e 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -179,6 +179,7 @@ struct vkd3d_instance struct vkd3d_vulkan_info vk_info; struct vkd3d_vk_global_procs vk_global_procs; void *libvulkan; + uint32_t vk_api_version;
uint64_t config_flags; enum vkd3d_api_version api_version;
From: Conor McCarthy cmccarthy@codeweavers.com
Fixes blank screen in Assassin's Creed: Valhalla. --- libs/vkd3d/command.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 6eddcfa2..5647d48c 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -3944,7 +3944,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo VkViewport vk_viewports[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface); const struct vkd3d_vk_device_procs *vk_procs; - unsigned int i; + unsigned int i, count;
TRACE("iface %p, viewport_count %u, viewports %p.\n", iface, viewport_count, viewports);
@@ -3954,24 +3954,25 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo viewport_count = ARRAY_SIZE(vk_viewports); }
- for (i = 0; i < viewport_count; ++i) + for (i = 0, count = 0; i < viewport_count; ++i) { - vk_viewports[i].x = viewports[i].TopLeftX; - vk_viewports[i].y = viewports[i].TopLeftY + viewports[i].Height; - vk_viewports[i].width = viewports[i].Width; - vk_viewports[i].height = -viewports[i].Height; - vk_viewports[i].minDepth = viewports[i].MinDepth; - vk_viewports[i].maxDepth = viewports[i].MaxDepth; + vk_viewports[count].x = viewports[i].TopLeftX; + vk_viewports[count].y = viewports[i].TopLeftY + viewports[i].Height; + vk_viewports[count].width = viewports[i].Width; + vk_viewports[count].height = -viewports[i].Height; + vk_viewports[count].minDepth = viewports[i].MinDepth; + vk_viewports[count].maxDepth = viewports[i].MaxDepth;
- if (!vk_viewports[i].width || !vk_viewports[i].height) + if (!vk_viewports[count].width || !vk_viewports[count].height) { - FIXME_ONCE("Invalid viewport %u, ignoring RSSetViewports().\n", i); - return; + FIXME_ONCE("Ignoring invalid viewport %u.\n", i); + continue; } + ++count; }
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, count, vk_viewports)); }
static void STDMETHODCALLTYPE d3d12_command_list_RSSetScissorRects(ID3D12GraphicsCommandList2 *iface,
From: Conor McCarthy cmccarthy@codeweavers.com
Negative widths are not supported in Vulkan. --- libs/vkd3d/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 5647d48c..f685948d 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -3963,7 +3963,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo vk_viewports[count].minDepth = viewports[i].MinDepth; vk_viewports[count].maxDepth = viewports[i].MaxDepth;
- if (!vk_viewports[count].width || !vk_viewports[count].height) + if (vk_viewports[count].width <= 0.0f || !vk_viewports[count].height) { FIXME_ONCE("Ignoring invalid viewport %u.\n", i); continue;
From: Conor McCarthy cmccarthy@codeweavers.com
Vulkan 1.1 introduced support for heights <= 0. --- libs/vkd3d/command.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index f685948d..5edde229 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -3943,6 +3943,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo { VkViewport vk_viewports[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface); + struct vkd3d_instance *instance = list->device->vkd3d_instance; const struct vkd3d_vk_device_procs *vk_procs; unsigned int i, count;
@@ -3963,10 +3964,26 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo vk_viewports[count].minDepth = viewports[i].MinDepth; vk_viewports[count].maxDepth = viewports[i].MaxDepth;
- if (vk_viewports[count].width <= 0.0f || !vk_viewports[count].height) + /* Vulkan 1.1 is required for height <= 0 */ + if (instance->vk_api_version < VK_API_VERSION_1_1) { - FIXME_ONCE("Ignoring invalid viewport %u.\n", i); - continue; + /* Vulkan height is negative for positive D3D12 heights, so skip only width <= 0 + * or zero height, and hope negative heights work. */ + if (vk_viewports[count].width <= 0.0f || !vk_viewports[count].height) + { + FIXME_ONCE("Ignoring invalid viewport %u.\n", i); + continue; + } + } + else + { + if (vk_viewports[count].width <= 0.0f) + { + /* Vulkan does not support width <= 0 */ + FIXME_ONCE("Setting invalid viewport %u to zero height.\n", i); + vk_viewports[count].width = 1.0f; + vk_viewports[count].height = 0.0f; + } } ++count; }
From patch 2/4:
@@ -3954,24 +3954,25 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCo viewport_count = ARRAY_SIZE(vk_viewports); } - for (i = 0; i < viewport_count; ++i) + for (i = 0, count = 0; i < viewport_count; ++i) { - vk_viewports[i].x = viewports[i].TopLeftX; - vk_viewports[i].y = viewports[i].TopLeftY + viewports[i].Height; - vk_viewports[i].width = viewports[i].Width; - vk_viewports[i].height = -viewports[i].Height; - vk_viewports[i].minDepth = viewports[i].MinDepth; - vk_viewports[i].maxDepth = viewports[i].MaxDepth; + vk_viewports[count].x = viewports[i].TopLeftX; + vk_viewports[count].y = viewports[i].TopLeftY + viewports[i].Height; + vk_viewports[count].width = viewports[i].Width; + vk_viewports[count].height = -viewports[i].Height; + vk_viewports[count].minDepth = viewports[i].MinDepth; + vk_viewports[count].maxDepth = viewports[i].MaxDepth; - if (!vk_viewports[i].width || !vk_viewports[i].height) + if (!vk_viewports[count].width || !vk_viewports[count].height) { - FIXME_ONCE("Invalid viewport %u, ignoring RSSetViewports().\n", i); - return; + FIXME_ONCE("Ignoring invalid viewport %u.\n", i); + continue; } + ++count; } 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, count, vk_viewports)); }
Unfortunately there are no corresponding tests, but this seems to imply that if a viewport in the middle of the array is invalid, subsequent viewports will get a different index for the purpose of e.g. SpvBuiltInViewportIndex. Is that really how it's supposed to work?
From patch 4/4:
Vulkan 1.1 introduced support for heights <= 0.
Yes, but so did VK_KHR_maintenance1, which we already require.