[PATCH vkd3d 1/3] libs/vkd3d: Add support for custom PRESENT state transitions.

Józef Kucia joseph.kucia at gmail.com
Thu Mar 29 11:21:46 CDT 2018


From: Józef Kucia <jkucia at codeweavers.com>

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---

This should be the last feature needed to implement D3D12 swapchains in Wine.

Vulkan swapchains are quite limited, e.g.
* Vulkan implementations support very limited set of formats for swapchains,
* views with a different format cannot be created for swapchains,
* swapchains are not multisampled (AFAIK it's the same in D3D12).

This patch adds flexibility needed to emulate support for missing
swapchain features, e.g. additional swapchain formats.

---
 demos/demo_xcb.h           | 31 ++++++++++++++++---------------
 include/vkd3d.h            | 20 ++++++++++++++------
 libs/vkd3d/command.c       | 28 +++++++++++++++++++---------
 libs/vkd3d/resource.c      | 16 +++++++++++-----
 libs/vkd3d/vkd3d_private.h |  3 ++-
 5 files changed, 62 insertions(+), 36 deletions(-)

diff --git a/demos/demo_xcb.h b/demos/demo_xcb.h
index 9980b506ffb6..053db0df9bab 100644
--- a/demos/demo_xcb.h
+++ b/demos/demo_xcb.h
@@ -307,13 +307,13 @@ static inline void demo_set_idle_func(struct demo *demo,
 static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *command_queue,
         struct demo_window *window, const struct demo_swapchain_desc *desc)
 {
+    struct vkd3d_image_resource_create_info resource_create_info;
     struct VkSwapchainCreateInfoKHR vk_swapchain_desc;
     struct VkXcbSurfaceCreateInfoKHR surface_desc;
     VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE;
     uint32_t format_count, queue_family_index;
     VkSurfaceCapabilitiesKHR surface_caps;
     VkPhysicalDevice vk_physical_device;
-    D3D12_RESOURCE_DESC resource_desc;
     VkFence vk_fence = VK_NULL_HANDLE;
     struct demo_swapchain *swapchain;
     unsigned int image_count, i, j;
@@ -446,22 +446,23 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
     vkWaitForFences(vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX);
     vkResetFences(vk_device, 1, &vk_fence);
 
-    resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
-    resource_desc.Alignment = 0;
-    resource_desc.Width = desc->width;
-    resource_desc.Height = desc->height;
-    resource_desc.DepthOrArraySize = 1;
-    resource_desc.MipLevels = 1;
-    resource_desc.Format = desc->format;
-    resource_desc.SampleDesc.Count = 1;
-    resource_desc.SampleDesc.Quality = 0;
-    resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
-    resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+    resource_create_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+    resource_create_info.desc.Alignment = 0;
+    resource_create_info.desc.Width = desc->width;
+    resource_create_info.desc.Height = desc->height;
+    resource_create_info.desc.DepthOrArraySize = 1;
+    resource_create_info.desc.MipLevels = 1;
+    resource_create_info.desc.Format = desc->format;
+    resource_create_info.desc.SampleDesc.Count = 1;
+    resource_create_info.desc.SampleDesc.Quality = 0;
+    resource_create_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+    resource_create_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+    resource_create_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
+    resource_create_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
     for (i = 0; i < image_count; ++i)
     {
-        if (FAILED(vkd3d_create_image_resource(d3d12_device, &resource_desc, vk_images[i],
-                VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_SWAPCHAIN_IMAGE,
-                &swapchain->buffers[i])))
+        resource_create_info.vk_image = vk_images[i];
+        if (FAILED(vkd3d_create_image_resource(d3d12_device, &resource_create_info, &swapchain->buffers[i])))
         {
             for (j = 0; j < i; ++j)
             {
diff --git a/include/vkd3d.h b/include/vkd3d.h
index 6ec85dbf2ffb..692b58d70065 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -73,9 +73,17 @@ struct vkd3d_device_create_info
     LUID adapter_luid;
 };
 
-/* resource flags */
+/* vkd3d_image_resource_create_info flags */
 #define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
-#define VKD3D_RESOURCE_SWAPCHAIN_IMAGE          0x00000002
+#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
+
+struct vkd3d_image_resource_create_info
+{
+    VkImage vk_image;
+    D3D12_RESOURCE_DESC desc;
+    unsigned int flags;
+    D3D12_RESOURCE_STATES present_state;
+};
 
 #ifndef VKD3D_NO_PROTOTYPES
 
@@ -96,8 +104,8 @@ uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue);
 VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue);
 void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
 
-HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc,
-        VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource);
+HRESULT vkd3d_create_image_resource(ID3D12Device *device,
+        const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
 ULONG vkd3d_resource_decref(ID3D12Resource *resource);
 ULONG vkd3d_resource_incref(ID3D12Resource *resource);
 
@@ -131,8 +139,8 @@ typedef uint32_t (*PFN_vkd3d_get_vk_queue_family_index)(ID3D12CommandQueue *queu
 typedef VkQueue (*PFN_vkd3d_acquire_vk_queue)(ID3D12CommandQueue *queue);
 typedef void (*PFN_vkd3d_release_vk_queue)(ID3D12CommandQueue *queue);
 
-typedef HRESULT (*PFN_vkd3d_create_image_resource)(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc,
-        VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource);
+typedef HRESULT (*PFN_vkd3d_create_image_resource)(ID3D12Device *device,
+        const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
 typedef ULONG (*PFN_vkd3d_resource_decref)(ID3D12Resource *resource);
 typedef ULONG (*PFN_vkd3d_resource_incref)(ID3D12Resource *resource);
 
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 1c0a18ae09e7..39094c24e913 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1150,7 +1150,8 @@ static void d3d12_command_list_invalidate_bindings(struct d3d12_command_list *li
     }
 }
 
-static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, bool is_swapchain_image,
+static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
+        bool is_swapchain_image, D3D12_RESOURCE_STATES present_state,
         VkAccessFlags *access_mask, VkPipelineStageFlags *stage_flags, VkImageLayout *image_layout)
 {
     switch (state)
@@ -1164,10 +1165,18 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
              * state when GPU finishes execution of a command list. */
             if (is_swapchain_image)
             {
-                *access_mask = VK_ACCESS_MEMORY_READ_BIT;
-                *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
-                if (image_layout)
-                    *image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+                if (present_state == D3D12_RESOURCE_STATE_PRESENT)
+                {
+                    *access_mask = VK_ACCESS_MEMORY_READ_BIT;
+                    *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+                    if (image_layout)
+                        *image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+                }
+                else
+                {
+                    vk_barrier_parameters_from_d3d12_resource_state(present_state,
+                            false, 0, access_mask, stage_flags, image_layout);
+                }
             }
             else
             {
@@ -1353,7 +1362,7 @@ static void d3d12_command_list_transition_resource_to_initial_state(struct d3d12
             VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
 
     if (!vk_barrier_parameters_from_d3d12_resource_state(resource->initial_state,
-            resource->flags & VKD3D_RESOURCE_SWAPCHAIN_IMAGE,
+            resource->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION, resource->present_state,
             &barrier.dstAccessMask, &dst_stage_mask, &barrier.newLayout))
     {
         FIXME("Unhandled state %#x.\n", resource->initial_state);
@@ -2877,14 +2886,14 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
                 sub_resource_idx = transition->Subresource;
 
                 if (!vk_barrier_parameters_from_d3d12_resource_state(transition->StateBefore,
-                        resource->flags & VKD3D_RESOURCE_SWAPCHAIN_IMAGE,
+                        resource->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION, resource->present_state,
                         &src_access_mask, &src_stage_mask, &layout_before))
                 {
                     FIXME("Unhandled state %#x.\n", transition->StateBefore);
                     continue;
                 }
                 if (!vk_barrier_parameters_from_d3d12_resource_state(transition->StateAfter,
-                        resource->flags & VKD3D_RESOURCE_SWAPCHAIN_IMAGE,
+                        resource->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION, resource->present_state,
                         &dst_access_mask, &dst_stage_mask, &layout_after))
                 {
                     FIXME("Unhandled state %#x.\n", transition->StateAfter);
@@ -2905,7 +2914,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
 
                 resource = unsafe_impl_from_ID3D12Resource(uav->pResource);
                 vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
-                        resource && (resource->flags & VKD3D_RESOURCE_SWAPCHAIN_IMAGE),
+                        resource && (resource->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION),
+                        resource ? resource->present_state : 0,
                         &access_mask, &stage_mask, &image_layout);
                 src_access_mask = dst_access_mask = access_mask;
                 src_stage_mask = dst_stage_mask = stage_mask;
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 81135d373ae7..4746ee2cf59b 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -797,28 +797,34 @@ HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
     return S_OK;
 }
 
-HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc,
-        VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource)
+HRESULT vkd3d_create_image_resource(ID3D12Device *device,
+        const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource)
 {
     struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device(device);
     struct d3d12_resource *object;
 
+    TRACE("device %p, create_info %p, resource %p.\n", device, create_info, resource);
+
     if (!(object = vkd3d_malloc(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
     object->refcount = 1;
     object->internal_refcount = 1;
-    object->desc = *desc;
-    object->u.vk_image = vk_image;
+    object->desc = create_info->desc;
+    object->u.vk_image = create_info->vk_image;
     object->vk_memory = VK_NULL_HANDLE;
     object->flags = VKD3D_RESOURCE_EXTERNAL;
-    object->flags |= resource_flags & VKD3D_RESOURCE_PUBLIC_FLAGS;
+    object->flags |= create_info->flags & VKD3D_RESOURCE_PUBLIC_FLAGS;
     object->map_count = 0;
     object->map_data = NULL;
     memset(&object->heap_properties, 0, sizeof(object->heap_properties));
     object->heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
     object->initial_state = D3D12_RESOURCE_STATE_COMMON;
+    if (create_info->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
+        object->present_state = create_info->present_state;
+    else
+        object->present_state = D3D12_RESOURCE_STATE_COMMON;
     object->device = d3d12_device;
     ID3D12Device_AddRef(&d3d12_device->ID3D12Device_iface);
 
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 988522f99e70..cf3112e845b3 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -175,7 +175,7 @@ HRESULT d3d12_fence_create(struct d3d12_device *device,
         UINT64 initial_value, D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence) DECLSPEC_HIDDEN;
 
 #define VKD3D_RESOURCE_PUBLIC_FLAGS \
-        (VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_SWAPCHAIN_IMAGE)
+        (VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
 #define VKD3D_RESOURCE_EXTERNAL 0x00000004
 
 /* ID3D12Resource */
@@ -202,6 +202,7 @@ struct d3d12_resource
     D3D12_HEAP_PROPERTIES heap_properties;
     D3D12_HEAP_FLAGS heap_flags;
     D3D12_RESOURCE_STATES initial_state;
+    D3D12_RESOURCE_STATES present_state;
 
     struct d3d12_device *device;
 };
-- 
2.16.1




More information about the wine-devel mailing list